generated from westfarn/web_django_template
208 lines
7.3 KiB
Python
208 lines
7.3 KiB
Python
from unittest.mock import patch
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import Client, TestCase
|
|
from django.urls import reverse
|
|
|
|
from social.models import (
|
|
Platform,
|
|
SocialAccount,
|
|
SocialPost,
|
|
is_generic_account_label,
|
|
)
|
|
|
|
|
|
class AccountLabelTests(TestCase):
|
|
def test_generic_placeholders(self):
|
|
self.assertTrue(is_generic_account_label(""))
|
|
self.assertTrue(is_generic_account_label("LinkedIn member"))
|
|
self.assertTrue(is_generic_account_label("Instagram account"))
|
|
self.assertTrue(is_generic_account_label("Page 123456"))
|
|
self.assertTrue(is_generic_account_label("urn:li:person:abc"))
|
|
self.assertFalse(is_generic_account_label("Monica Dhillon"))
|
|
self.assertFalse(is_generic_account_label("@mkdrealtor"))
|
|
|
|
def test_resolve_keeps_custom_name(self):
|
|
existing = SocialAccount(
|
|
platform=Platform.LINKEDIN,
|
|
label="Monica (personal)",
|
|
external_id="urn:li:person:abc",
|
|
)
|
|
self.assertEqual(
|
|
SocialAccount.resolve_label(existing, "LinkedIn member"),
|
|
"Monica (personal)",
|
|
)
|
|
|
|
def test_resolve_replaces_generic(self):
|
|
existing = SocialAccount(
|
|
platform=Platform.LINKEDIN,
|
|
label="LinkedIn member",
|
|
external_id="urn:li:person:abc",
|
|
)
|
|
self.assertEqual(
|
|
SocialAccount.resolve_label(existing, "Monica Dhillon"),
|
|
"Monica Dhillon",
|
|
)
|
|
|
|
|
|
class SocialComposerTests(TestCase):
|
|
def setUp(self):
|
|
User = get_user_model()
|
|
self.user = User.objects.create_user(
|
|
username="composer", password="test-pass-123"
|
|
)
|
|
self.client = Client()
|
|
self.client.login(username="composer", password="test-pass-123")
|
|
self.account = SocialAccount.objects.create(
|
|
platform=Platform.LINKEDIN,
|
|
label="LinkedIn member",
|
|
external_id="urn:li:person:abc123",
|
|
is_active=True,
|
|
owner=self.user,
|
|
)
|
|
|
|
def test_composer_shows_send_now_and_full_name(self):
|
|
response = self.client.get(reverse("social:composer"))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "Send now")
|
|
self.assertContains(response, "Schedule")
|
|
self.assertContains(response, "LinkedIn member")
|
|
self.assertContains(response, "urn:li:person:abc123")
|
|
self.assertNotContains(response, "Save / publish")
|
|
|
|
def test_send_now_queues_without_schedule(self):
|
|
mock_task = patch("social.views.publish_social_post").start()
|
|
self.addCleanup(patch.stopall)
|
|
response = self.client.post(
|
|
reverse("social:composer"),
|
|
{
|
|
"body": "Open house Saturday",
|
|
"account_ids": [str(self.account.pk)],
|
|
"action": "send_now",
|
|
},
|
|
)
|
|
post = SocialPost.objects.get()
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertEqual(
|
|
response.url, reverse("social:post_detail", kwargs={"pk": post.pk})
|
|
)
|
|
self.assertEqual(post.status, SocialPost.Status.QUEUED)
|
|
self.assertIsNotNone(post.scheduled_for)
|
|
self.assertEqual(post.targets.count(), 1)
|
|
mock_task.enqueue.assert_called_once_with(post_id=str(post.pk))
|
|
|
|
def test_schedule_requires_datetime(self):
|
|
response = self.client.post(
|
|
reverse("social:composer"),
|
|
{
|
|
"body": "Open house Saturday",
|
|
"account_ids": [str(self.account.pk)],
|
|
"action": "schedule",
|
|
},
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "Pick a schedule date/time, or choose Send now.")
|
|
self.assertFalse(SocialPost.objects.exists())
|
|
|
|
def test_schedule_with_datetime(self):
|
|
response = self.client.post(
|
|
reverse("social:composer"),
|
|
{
|
|
"body": "Open house Saturday",
|
|
"account_ids": [str(self.account.pk)],
|
|
"action": "schedule",
|
|
"scheduled_for": "2026-08-10T09:30",
|
|
},
|
|
)
|
|
post = SocialPost.objects.get()
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertEqual(post.status, SocialPost.Status.SCHEDULED)
|
|
self.assertIsNotNone(post.scheduled_for)
|
|
|
|
def test_save_draft(self):
|
|
response = self.client.post(
|
|
reverse("social:composer"),
|
|
{
|
|
"body": "Draft caption",
|
|
"action": "save",
|
|
},
|
|
)
|
|
post = SocialPost.objects.get()
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertEqual(post.status, SocialPost.Status.DRAFT)
|
|
|
|
|
|
class SocialAccountRenameTests(TestCase):
|
|
def setUp(self):
|
|
User = get_user_model()
|
|
self.user = User.objects.create_user(
|
|
username="renamer", password="test-pass-123"
|
|
)
|
|
self.client = Client()
|
|
self.client.login(username="renamer", password="test-pass-123")
|
|
self.account = SocialAccount.objects.create(
|
|
platform=Platform.FACEBOOK,
|
|
label="Page 999",
|
|
external_id="999",
|
|
is_active=True,
|
|
owner=self.user,
|
|
)
|
|
|
|
def test_accounts_page_shows_rename_field(self):
|
|
response = self.client.get(reverse("social:account_list"))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, 'name="label"')
|
|
self.assertContains(response, "Page 999")
|
|
self.assertContains(response, "Rename")
|
|
|
|
def test_rename_updates_label(self):
|
|
response = self.client.post(
|
|
reverse("social:account_list"),
|
|
{
|
|
"action": "rename",
|
|
"account_id": str(self.account.pk),
|
|
"label": "Monica Dhillon Realty",
|
|
},
|
|
)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.account.refresh_from_db()
|
|
self.assertEqual(self.account.label, "Monica Dhillon Realty")
|
|
|
|
def test_rename_rejects_blank(self):
|
|
response = self.client.post(
|
|
reverse("social:account_list"),
|
|
{
|
|
"action": "rename",
|
|
"account_id": str(self.account.pk),
|
|
"label": " ",
|
|
},
|
|
)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.account.refresh_from_db()
|
|
self.assertEqual(self.account.label, "Page 999")
|
|
|
|
|
|
from datetime import timedelta
|
|
from io import StringIO
|
|
from unittest.mock import patch as _patch
|
|
|
|
from django.core.management import call_command
|
|
from django.utils import timezone
|
|
|
|
|
|
class DispatchDueSocialTests(TestCase):
|
|
def test_enqueues_past_scheduled_social_post(self):
|
|
post = SocialPost.objects.create(
|
|
body="Open house",
|
|
status=SocialPost.Status.SCHEDULED,
|
|
scheduled_for=timezone.now() - timedelta(minutes=5),
|
|
)
|
|
mock_task = _patch("social.tasks.publish_social_post").start()
|
|
self.addCleanup(_patch.stopall)
|
|
out = StringIO()
|
|
call_command("dispatch_due", stdout=out)
|
|
post.refresh_from_db()
|
|
self.assertEqual(post.status, SocialPost.Status.QUEUED)
|
|
mock_task.enqueue.assert_called_once_with(post_id=str(post.pk))
|
|
self.assertIn("Enqueued 1 due item(s).", out.getvalue())
|