204 lines
8 KiB
Python
204 lines
8 KiB
Python
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)
|