summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatalia <124304+nessita@users.noreply.github.com>2025-06-25 17:22:46 -0300
committernessita <124304+nessita@users.noreply.github.com>2025-06-27 15:57:02 -0300
commitff0ff98d427982b7225df59f454a86bdf66251d6 (patch)
tree6af4889cfdea447484db5fc4afc447fc2315cab0
parentd63241ebc7067fdebbaf704989b34fcd8f26bbe9 (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.py30
-rw-r--r--django/test/selenium.py19
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