Files
org-social-relay/app/groups/tests.py
2025-11-05 15:03:20 +01:00

271 lines
10 KiB
Python

from django.test import TestCase, override_settings
from rest_framework.test import APIClient
from rest_framework import status
from app.feeds.models import Profile, Post
class GroupsViewTest(TestCase):
"""Test cases for the GroupsView API."""
def setUp(self):
self.client = APIClient()
self.groups_url = "/groups/"
@override_settings(ENABLED_GROUPS=[], GROUPS_MAP={})
def test_no_groups_configured(self):
"""Test GET /groups/ when no groups are configured."""
# Given: No groups configured
# When: We request groups list
response = self.client.get(self.groups_url)
# Then: Should return 404 with error message
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["type"], "Error")
self.assertIn("No groups configured", response.data["errors"][0])
@override_settings(
ENABLED_GROUPS=["emacs", "org-social", "python"],
GROUPS_MAP={"emacs": "Emacs", "org-social": "Org Social", "python": "Python"},
)
def test_list_groups_success(self):
"""Test GET /groups/ returns configured groups."""
# Given: Groups configured
# When: We request groups list
response = self.client.get(self.groups_url)
# Then: Should return success with group display names
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["type"], "Success")
self.assertEqual(len(response.data["data"]), 3)
# Data should contain display names, not slugs
self.assertIn("Emacs", response.data["data"])
self.assertIn("Org Social", response.data["data"])
self.assertIn("Python", response.data["data"])
@override_settings(
ENABLED_GROUPS=["emacs", "org-social"],
GROUPS_MAP={"emacs": "Emacs", "org-social": "Org Social"},
)
def test_list_groups_empty_groups(self):
"""Test GET /groups/ when groups are configured."""
# Given: Groups configured
# When: We request groups list
response = self.client.get(self.groups_url)
# Then: Should return group display names
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["type"], "Success")
self.assertEqual(len(response.data["data"]), 2)
self.assertIn("Emacs", response.data["data"])
self.assertIn("Org Social", response.data["data"])
class GroupMessagesViewTest(TestCase):
"""Test cases for the GroupMessagesView API."""
def setUp(self):
self.client = APIClient()
# Create test profiles
self.profile1 = Profile.objects.create(
feed="https://example.com/social.org", nick="user1"
)
self.profile2 = Profile.objects.create(
feed="https://test.com/social.org", nick="user2"
)
@override_settings(
ENABLED_GROUPS=["emacs", "python"],
GROUPS_MAP={"emacs": "Emacs", "python": "Python"},
)
def test_get_group_messages_success(self):
"""Test GET /groups/{id}/ returns group messages."""
# Given: Posts with group metadata (using slugs)
Post.objects.create(
profile=self.profile1,
post_id="2025-01-01T12:00:00+00:00",
content="First emacs post",
group="emacs",
)
Post.objects.create(
profile=self.profile2,
post_id="2025-01-01T13:00:00+00:00",
content="Second emacs post",
group="emacs",
)
# Post from non-emacs group (should not appear)
other_profile = Profile.objects.create(
feed="https://other.com/social.org", nick="other"
)
Post.objects.create(
profile=other_profile,
post_id="2025-01-01T14:00:00+00:00",
content="Other post",
group="python",
)
# When: We request emacs group messages (using slug in URL)
response = self.client.get("/groups/emacs/")
# Then: Should return only emacs posts
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["type"], "Success")
self.assertEqual(len(response.data["data"]), 2)
# Check meta - should contain display name, not slug
self.assertEqual(response.data["meta"]["group"], "Emacs")
self.assertIn("members", response.data["meta"])
# Then: Should have ETag and Last-Modified headers
self.assertIn("ETag", response)
self.assertIn("Last-Modified", response)
@override_settings(ENABLED_GROUPS=["emacs"], GROUPS_MAP={"emacs": "Emacs"})
def test_get_group_messages_with_replies(self):
"""Test group messages with reply tree structure."""
# Given: Posts with replies in group
post1 = Post.objects.create(
profile=self.profile1,
post_id="2025-01-01T12:00:00+00:00",
content="Original post",
group="emacs",
)
Post.objects.create(
profile=self.profile2,
post_id="2025-01-01T13:00:00+00:00",
content="Reply to post1",
reply_to=f"{self.profile1.feed}#{post1.post_id}",
group="emacs",
)
# When: We request group messages
response = self.client.get("/groups/emacs/")
# Then: Should return tree structure
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = response.data["data"]
# Find the original post
original = None
for msg in data:
if "2025-01-01T12:00:00" in msg["post"]:
original = msg
break
self.assertIsNotNone(original)
# Check if reply is in children
self.assertEqual(len(original["children"]), 1)
self.assertIn("2025-01-01T13:00:00", original["children"][0]["post"])
@override_settings(ENABLED_GROUPS=["emacs"], GROUPS_MAP={"emacs": "Emacs"})
def test_get_group_messages_empty(self):
"""Test group with no messages."""
# Given: No posts in group
# When: We request group messages
response = self.client.get("/groups/emacs/")
# Then: Should return empty data
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["type"], "Success")
self.assertEqual(response.data["data"], [])
self.assertEqual(len(response.data["data"]), 0)
@override_settings(ENABLED_GROUPS=["emacs"], GROUPS_MAP={"emacs": "Emacs"})
def test_get_group_messages_invalid_group(self):
"""Test getting messages from invalid group."""
# Given: Invalid group ID
# When: We request invalid group
response = self.client.get("/groups/invalid-group/")
# Then: Should return 404
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data["type"], "Error")
@override_settings(
ENABLED_GROUPS=["emacs", "python"],
GROUPS_MAP={"emacs": "Emacs", "python": "Python"},
)
def test_get_group_messages_caching(self):
"""Test that group messages are cached."""
# Given: Posts in group
Post.objects.create(
profile=self.profile1,
post_id="2025-01-01T12:00:00+00:00",
content="Test post",
group="emacs",
)
# When: We request group messages twice
response1 = self.client.get("/groups/emacs/")
response2 = self.client.get("/groups/emacs/")
# Then: Both should succeed
self.assertEqual(response1.status_code, status.HTTP_200_OK)
self.assertEqual(response2.status_code, status.HTTP_200_OK)
# And ETag should be the same (indicating cache hit)
self.assertEqual(response1["ETag"], response2["ETag"])
class GroupsIntegrationTest(TestCase):
"""Integration tests for groups functionality."""
def setUp(self):
self.client = APIClient()
@override_settings(
ENABLED_GROUPS=["emacs", "org-social", "python"],
GROUPS_MAP={"emacs": "Emacs", "org-social": "Org Social", "python": "Python"},
)
def test_full_group_workflow(self):
"""Test complete group workflow: list, create profile/post, retrieve."""
# Given: Initial state
feed_url = "https://example.com/social.org"
# Step 1: List groups
response = self.client.get("/groups/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data["data"]), 3)
# Step 2: Create profile (simulating what would happen via feed parsing)
profile = Profile.objects.create(feed=feed_url)
# Step 3: Create posts in group (simulating what would happen via feed parsing)
Post.objects.create(
profile=profile,
post_id="2025-01-01T12:00:00+00:00",
content="My emacs config",
group="emacs",
)
# Step 4: Retrieve group messages
response = self.client.get("/groups/emacs/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data["data"]), 1)
# Check that we have a post from the feed we registered
self.assertIn(
"https://example.com/social.org#", response.data["data"][0]["post"]
)
# Step 5: Verify groups list still works
response = self.client.get("/groups/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
# Should contain display name, not slug
self.assertIn("Emacs", response.data["data"])
@override_settings(ENABLED_GROUPS=[], GROUPS_MAP={})
def test_groups_disabled(self):
"""Test behavior when groups are not configured."""
# When: We try to access any group endpoint
response = self.client.get("/groups/")
# Then: Should indicate no groups configured
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertIn("No groups configured", response.data["errors"][0])