import functools from unittest import TestCase from django.conf import settings from django.http import HttpRequest from django.test import override_settings from django.urls import reverse from .middleware import ContentSecurityPolicyMiddleware from .middleware import CSPSources from .middleware import ReportToMiddleware def get_response(request): class MockResponse(dict): def __init__(self, request): self.request = request def has_header(self, name): return name in self return MockResponse(request) def get_html_response(request, markup=""): response = get_response(request) response["Content-Type"] = "text/html" response.content = ( f'
{markup}' ).encode() return response get_html_response_with_nonce = functools.partial( get_html_response, markup='' ) TEST_REPORT_TO_DIRECTIVE = ( '{"group":"default","max_age":31536000,' '"endpoints":[{"url":"https://example.com/"}],' '"include_subdomains":true}' ) class ReportToMiddlewareTests(TestCase): @override_settings(REPORT_TO_DIRECTIVE=TEST_REPORT_TO_DIRECTIVE) def setUp(self): super().setUp() self.request = HttpRequest() self.request.method = "GET" self.request.path = reverse("home") self.middleware = ReportToMiddleware(get_response) def test_header_is_set(self): output = self.middleware(self.request) self.assertIn("Report-To", output) self.assertEqual(output.get("Report-To"), TEST_REPORT_TO_DIRECTIVE) def test_header_is_not_set_for_assets(self): self.request.path = settings.STATIC_URL output = self.middleware(self.request) self.assertNotIn("Report-To", output) class ContentSecurityPolicyMiddlewareTests(TestCase): maxDiff = None def setUp(self): super().setUp() self.request = HttpRequest() self.request.method = "GET" self.request.path = reverse("home") self.middleware = ContentSecurityPolicyMiddleware(get_response) def test_default_csp_header(self): self.middleware.nonce = "TEST_NONCE" output = self.middleware(self.request) self.assertIn("Content-Security-Policy", output) self.assertEqual( output["Content-Security-Policy"], CSPSources.get_csp_header(nonce=self.middleware.nonce), ) @override_settings(STATIC_URL="/static/") def test_header_is_not_set_for_assets(self): self.request.path = "/static/test.js" output = self.middleware(self.request) self.assertNotIn("Content-Security-Policy", output) def test_csp_nonce_is_replaced(self): self.middleware = ContentSecurityPolicyMiddleware(get_html_response_with_nonce) self.middleware.nonce = "TEST_NONCE" output = self.middleware(self.request) self.assertIn(b'