diff options
| author | Natalia <124304+nessita@users.noreply.github.com> | 2025-06-25 17:22:46 -0300 |
|---|---|---|
| committer | nessita <124304+nessita@users.noreply.github.com> | 2025-06-27 15:57:02 -0300 |
| commit | ff0ff98d427982b7225df59f454a86bdf66251d6 (patch) | |
| tree | 6af4889cfdea447484db5fc4afc447fc2315cab0 | |
| parent | d63241ebc7067fdebbaf704989b34fcd8f26bbe9 (diff) | |
Refs #15727 -- Updated AdminSeleniumTestCase to use ContentSecurityPolicyMiddleware.
Replaced the custom CSP middleware previously used in the admin's
AdminSeleniumTestCase with the official ContentSecurityPolicyMiddleware.
This change ensures alignment with Django's built-in CSP support.
Also updates the test logic to inspect browser console logs to assert
that no CSP violations are triggered during Selenium admin tests.
| -rw-r--r-- | django/contrib/admin/tests.py | 30 | ||||
| -rw-r--r-- | django/test/selenium.py | 19 |
2 files changed, 37 insertions, 12 deletions
diff --git a/django/contrib/admin/tests.py b/django/contrib/admin/tests.py index f64a4c47f8..3982142330 100644 --- a/django/contrib/admin/tests.py +++ b/django/contrib/admin/tests.py @@ -1,24 +1,27 @@ from contextlib import contextmanager from django.contrib.staticfiles.testing import StaticLiveServerTestCase -from django.test import modify_settings +from django.test import modify_settings, override_settings from django.test.selenium import SeleniumTestCase -from django.utils.deprecation import MiddlewareMixin +from django.utils.csp import CSP from django.utils.translation import gettext as _ # Make unittest ignore frames in this module when reporting failures. __unittest = True -class CSPMiddleware(MiddlewareMixin): - """The admin's JavaScript should be compatible with CSP.""" - - def process_response(self, request, response): - response.headers["Content-Security-Policy"] = "default-src 'self'" - return response - - -@modify_settings(MIDDLEWARE={"append": "django.contrib.admin.tests.CSPMiddleware"}) +@modify_settings( + MIDDLEWARE={"append": "django.middleware.csp.ContentSecurityPolicyMiddleware"} +) +@override_settings( + SECURE_CSP={ + "default-src": [CSP.NONE], + "connect-src": [CSP.SELF], + "img-src": [CSP.SELF], + "script-src": [CSP.SELF], + "style-src": [CSP.SELF], + }, +) class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase): available_apps = [ "django.contrib.admin", @@ -28,6 +31,11 @@ class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase): "django.contrib.sites", ] + def tearDown(self): + # Ensure that no CSP violations were logged in the browser. + self.assertEqual(self.get_browser_logs(source="security"), []) + super().tearDown() + def wait_until(self, callback, timeout=10): """ Block the execution of the tests until the specified callback returns a diff --git a/django/test/selenium.py b/django/test/selenium.py index 15ee3002ec..be8f4a815f 100644 --- a/django/test/selenium.py +++ b/django/test/selenium.py @@ -77,7 +77,11 @@ class SeleniumTestCaseBase(type(LiveServerTestCase)): def get_capability(cls, browser): from selenium.webdriver.common.desired_capabilities import DesiredCapabilities - return getattr(DesiredCapabilities, browser.upper()) + caps = getattr(DesiredCapabilities, browser.upper()) + if browser == "chrome": + caps["goog:loggingPrefs"] = {"browser": "ALL"} + + return caps def create_options(self): options = self.import_options(self.browser)() @@ -237,6 +241,19 @@ class SeleniumTestCase(LiveServerTestCase, metaclass=SeleniumTestCaseBase): path.parent.mkdir(exist_ok=True, parents=True) self.selenium.save_screenshot(path) + def get_browser_logs(self, source=None, level="ALL"): + """Return Chrome console logs filtered by level and optionally source.""" + try: + logs = self.selenium.get_log("browser") + except AttributeError: + logs = [] + return [ + log + for log in logs + if (level == "ALL" or log["level"] == level) + and (source is None or log["source"] == source) + ] + @classmethod def _quit_selenium(cls): # quit() the WebDriver before attempting to terminate and join the |
