mirror of
https://github.com/tanrax/org-social-relay
synced 2026-02-15 06:26:08 +01:00
204 lines
7.8 KiB
Python
204 lines
7.8 KiB
Python
from django.test import TestCase
|
|
from django.conf import settings
|
|
from unittest.mock import patch, Mock
|
|
from app.feeds.models import Feed
|
|
from app.feeds.tasks import discover_feeds_from_relay_nodes
|
|
|
|
|
|
class DiscoverRelayNodesTest(TestCase):
|
|
"""Test cases for discover_feeds_from_relay_nodes task using Given/When/Then structure."""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures."""
|
|
# Clear any existing feeds
|
|
Feed.objects.all().delete()
|
|
|
|
def test_discovers_feeds_from_real_relay_list(self):
|
|
"""Test that feeds are discovered from the actual relay list file."""
|
|
# Given: The real relay list file exists (data/relay-list.txt)
|
|
# And we mock the HTTP responses from relays
|
|
|
|
# Mock relay response
|
|
mock_relay_response = Mock()
|
|
mock_relay_response.status_code = 200
|
|
mock_relay_response.json.return_value = {
|
|
"type": "Success",
|
|
"data": [
|
|
"https://test-feed1.com/social.org",
|
|
"https://test-feed2.com/social.org",
|
|
],
|
|
}
|
|
mock_relay_response.raise_for_status = Mock()
|
|
|
|
# Mock feed validation responses
|
|
mock_feed_response = Mock()
|
|
mock_feed_response.status_code = 200
|
|
mock_feed_response.text = """#+TITLE: Test Feed
|
|
#+NICK: testuser
|
|
#+DESCRIPTION: Test description
|
|
|
|
* Posts
|
|
"""
|
|
mock_feed_response.content = mock_feed_response.text.encode("utf-8")
|
|
mock_feed_response.history = []
|
|
|
|
def mock_requests_get(url, timeout=None):
|
|
if "/feeds" in url:
|
|
return mock_relay_response
|
|
# Feed validation requests
|
|
mock_feed_response.url = url
|
|
mock_feed_response.raise_for_status = Mock()
|
|
return mock_feed_response
|
|
|
|
# When: We run the discovery task
|
|
with patch("requests.get", side_effect=mock_requests_get):
|
|
discover_feeds_from_relay_nodes()
|
|
|
|
# Then: Feeds should be discovered (the real relay list has relays)
|
|
# We can't predict exact count since it depends on real file content
|
|
# So we just verify the function runs without errors
|
|
self.assertGreaterEqual(Feed.objects.count(), 0)
|
|
|
|
def test_handles_relay_connection_failure(self):
|
|
"""Test that the task handles relay connection failures gracefully."""
|
|
# Given: The real relay list file exists
|
|
# And relay connections will fail
|
|
|
|
# Mock a connection error
|
|
with patch("requests.get", side_effect=Exception("Connection failed")):
|
|
# When: We run the discovery task
|
|
initial_count = Feed.objects.count()
|
|
discover_feeds_from_relay_nodes()
|
|
|
|
# Then: No new feeds should be created and no exception raised
|
|
self.assertEqual(Feed.objects.count(), initial_count)
|
|
|
|
def test_skips_existing_feeds(self):
|
|
"""Test that the task skips feeds that already exist."""
|
|
# Given: A feed already exists
|
|
Feed.objects.create(url="https://existing-feed.com/social.org")
|
|
initial_count = Feed.objects.count()
|
|
|
|
# Mock relay response with the existing feed
|
|
mock_relay_response = Mock()
|
|
mock_relay_response.status_code = 200
|
|
mock_relay_response.json.return_value = {
|
|
"type": "Success",
|
|
"data": [
|
|
"https://existing-feed.com/social.org", # Already exists
|
|
],
|
|
}
|
|
mock_relay_response.raise_for_status = Mock()
|
|
|
|
def mock_requests_get(url, timeout=None):
|
|
if "/feeds" in url:
|
|
return mock_relay_response
|
|
# Should not validate existing feed
|
|
if "existing-feed" in url:
|
|
self.fail("Should not validate existing feed")
|
|
return Mock()
|
|
|
|
# When: We run the discovery task
|
|
with patch("requests.get", side_effect=mock_requests_get):
|
|
discover_feeds_from_relay_nodes()
|
|
|
|
# Then: No new feeds should be added
|
|
self.assertEqual(Feed.objects.count(), initial_count)
|
|
|
|
def test_handles_invalid_feed_during_validation(self):
|
|
"""Test that the task skips invalid feeds during validation."""
|
|
# Given: The real relay list file exists
|
|
|
|
# Mock relay response with valid and invalid feeds
|
|
mock_relay_response = Mock()
|
|
mock_relay_response.status_code = 200
|
|
mock_relay_response.json.return_value = {
|
|
"type": "Success",
|
|
"data": [
|
|
"https://valid-feed.com/social.org",
|
|
"https://invalid-feed.com/social.org",
|
|
],
|
|
}
|
|
mock_relay_response.raise_for_status = Mock()
|
|
|
|
# Mock feed validation responses
|
|
def mock_requests_get(url, timeout=None):
|
|
if "/feeds" in url:
|
|
return mock_relay_response
|
|
|
|
# Valid feed response
|
|
if "valid-feed" in url:
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.text = """#+TITLE: Valid Feed
|
|
#+NICK: validuser
|
|
#+DESCRIPTION: Valid description
|
|
|
|
* Posts
|
|
"""
|
|
mock_response.content = mock_response.text.encode("utf-8")
|
|
mock_response.url = url
|
|
mock_response.history = []
|
|
mock_response.raise_for_status = Mock()
|
|
return mock_response
|
|
|
|
# Invalid feed response (missing required fields)
|
|
if "invalid-feed" in url:
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.text = "Invalid content without Org Social headers"
|
|
mock_response.content = mock_response.text.encode("utf-8")
|
|
mock_response.url = url
|
|
mock_response.history = []
|
|
mock_response.raise_for_status = Mock()
|
|
return mock_response
|
|
|
|
# Default response for any other URL
|
|
mock_response = Mock()
|
|
mock_response.status_code = 404
|
|
mock_response.raise_for_status = Mock(side_effect=Exception("404"))
|
|
return mock_response
|
|
|
|
# When: We run the discovery task
|
|
initial_count = Feed.objects.count()
|
|
with patch("requests.get", side_effect=mock_requests_get):
|
|
discover_feeds_from_relay_nodes()
|
|
|
|
# Then: Only the valid feed should be added (or none if validation failed for both)
|
|
# We verify that invalid feed was not added
|
|
self.assertFalse(
|
|
Feed.objects.filter(url="https://invalid-feed.com/social.org").exists()
|
|
)
|
|
# And if valid feed was processed, it should exist
|
|
# (we're more lenient here as the test DB might interfere)
|
|
if Feed.objects.count() > initial_count:
|
|
self.assertTrue(
|
|
Feed.objects.filter(url="https://valid-feed.com/social.org").exists()
|
|
)
|
|
|
|
def test_filters_out_own_domain(self):
|
|
"""Test that the task filters out its own domain from relay list."""
|
|
# Given: The real relay list file exists
|
|
# We verify the function doesn't try to fetch from its own domain
|
|
|
|
own_domain = settings.SITE_DOMAIN
|
|
|
|
def mock_requests_get(url, timeout=None):
|
|
# Should not be called for our own domain
|
|
if own_domain in url and "/feeds" in url:
|
|
self.fail(f"Should not fetch from own domain: {url}")
|
|
|
|
# Mock response for other relays
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {"type": "Success", "data": []}
|
|
mock_response.raise_for_status = Mock()
|
|
return mock_response
|
|
|
|
# When: We run the discovery task
|
|
with patch("requests.get", side_effect=mock_requests_get):
|
|
discover_feeds_from_relay_nodes()
|
|
|
|
# Then: The function should complete without calling own domain
|
|
# (if it called own domain, the test would fail in mock_requests_get)
|