from django.test import TestCase from rest_framework.test import APIClient from unittest.mock import patch, Mock from app.feeds.models import Profile import requests class FeedContentViewTests(TestCase): def setUp(self): """Set up test fixtures.""" self.client = APIClient() self.profile = Profile.objects.create( feed="https://example.com/social.org", title="Test Profile", nick="testuser", ) def test_get_feed_content_success(self): """Test successfully fetching feed content""" # Given: A registered feed whose server returns valid Org Social content mock_content = """#+TITLE: My Social Feed #+AUTHOR: John Doe * 2025-02-05T10:00:00+0100 :PROPERTIES: :ID: 2025-02-05T10:00:00+0100 :END: Hello, world! This is my first post. """ with patch("app.feedcontent.views.requests.get") as mock_get: mock_response = Mock() mock_response.status_code = 200 mock_response.content = mock_content.encode("utf-8") mock_response.raise_for_status = Mock() mock_get.return_value = mock_response # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://example.com/social.org"} ) # Then: The content is returned verbatim with HATEOAS links self.assertEqual(response.status_code, 200) self.assertEqual(response.data["type"], "Success") self.assertEqual(response.data["data"]["content"], mock_content) self.assertIn("_links", response.data) self.assertIn("self", response.data["_links"]) def test_get_feed_content_missing_parameter(self): """Test error when feed parameter is missing""" # Given: No feed parameter # When: The feed content endpoint is requested response = self.client.get("/feed-content/") # Then: A 400 error explains the missing parameter self.assertEqual(response.status_code, 400) self.assertEqual(response.data["type"], "Error") self.assertIn("Feed URL parameter is required", response.data["errors"]) def test_get_feed_content_empty_parameter(self): """Test error when feed parameter is empty""" # Given: A blank feed parameter # When: The feed content endpoint is requested response = self.client.get("/feed-content/", {"feed": " "}) # Then: A 400 error explains the missing parameter self.assertEqual(response.status_code, 400) self.assertEqual(response.data["type"], "Error") self.assertIn("Feed URL parameter is required", response.data["errors"]) def test_get_feed_content_feed_not_found(self): """Test error when feed is not registered in relay""" # Given: A feed URL that is not registered in the relay # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://unknown.com/social.org"} ) # Then: A 404 error explains the feed is unknown self.assertEqual(response.status_code, 404) self.assertEqual(response.data["type"], "Error") self.assertIn("Feed not found in relay", response.data["errors"]) def test_get_feed_content_timeout(self): """Test error when feed server times out""" # Given: A registered feed whose server times out with patch("app.feedcontent.views.requests.get") as mock_get: mock_get.side_effect = requests.exceptions.Timeout() # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://example.com/social.org"} ) # Then: A 502 error reports the timeout self.assertEqual(response.status_code, 502) self.assertEqual(response.data["type"], "Error") self.assertIn("Request timeout", response.data["errors"][0]) def test_get_feed_content_connection_error(self): """Test error when connection to feed server fails""" # Given: A registered feed whose server refuses the connection with patch("app.feedcontent.views.requests.get") as mock_get: mock_get.side_effect = requests.exceptions.ConnectionError() # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://example.com/social.org"} ) # Then: A 502 error reports the connection failure self.assertEqual(response.status_code, 502) self.assertEqual(response.data["type"], "Error") self.assertIn("Connection error", response.data["errors"][0]) def test_get_feed_content_http_error(self): """Test error when feed server returns HTTP error""" # Given: A registered feed whose server answers with an HTTP error with patch("app.feedcontent.views.requests.get") as mock_get: mock_response = Mock() mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError( "404 Not Found" ) mock_get.return_value = mock_response # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://example.com/social.org"} ) # Then: A 502 error reports the upstream HTTP error self.assertEqual(response.status_code, 502) self.assertEqual(response.data["type"], "Error") self.assertIn("HTTP error", response.data["errors"][0]) def test_get_feed_content_unicode(self): """Test fetching feed content with unicode characters""" # Given: A registered feed whose content includes unicode and emojis mock_content = """#+TITLE: Mi Feed Social #+AUTHOR: José García * 2025-02-05T10:00:00+0100 :PROPERTIES: :ID: 2025-02-05T10:00:00+0100 :END: ¡Hola mundo! Este es mi primer post con émojis 🚀 ❤️ """ with patch("app.feedcontent.views.requests.get") as mock_get: mock_response = Mock() mock_response.status_code = 200 mock_response.content = mock_content.encode("utf-8") mock_response.raise_for_status = Mock() mock_get.return_value = mock_response # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://example.com/social.org"} ) # Then: The unicode content survives the round trip intact self.assertEqual(response.status_code, 200) self.assertEqual(response.data["type"], "Success") self.assertEqual(response.data["data"]["content"], mock_content) self.assertIn("🚀", response.data["data"]["content"]) self.assertIn("❤️", response.data["data"]["content"]) def test_get_feed_content_preserves_formatting(self): """Test that feed content preserves whitespace and formatting""" # Given: A registered feed whose content mixes blank lines, spaces and tabs mock_content = """#+TITLE: Test Feed * 2025-02-05T10:00:00+0100 :PROPERTIES: :ID: 2025-02-05T10:00:00+0100 :END: Line 1 Line 2 with multiple spaces Line 3 with tab """ with patch("app.feedcontent.views.requests.get") as mock_get: mock_response = Mock() mock_response.status_code = 200 mock_response.content = mock_content.encode("utf-8") mock_response.raise_for_status = Mock() mock_get.return_value = mock_response # When: The feed content endpoint is requested response = self.client.get( "/feed-content/", {"feed": "https://example.com/social.org"} ) # Then: The content is exactly as provided, preserving all whitespace self.assertEqual(response.status_code, 200) self.assertEqual(response.data["data"]["content"], mock_content)