diff --git a/tests/integration/test_app_routes.py b/tests/integration/test_app_routes.py index 18e0a73..d362ddb 100644 --- a/tests/integration/test_app_routes.py +++ b/tests/integration/test_app_routes.py @@ -6,6 +6,7 @@ import subprocess import sys import tempfile import unittest +from html.parser import HTMLParser from pathlib import Path from unittest.mock import Mock, patch @@ -112,18 +113,29 @@ class TestEscaping(AppRouteMixin, unittest.TestCase): self.assertIn("<script>alert('config')", body) +class InlineScriptCollector(HTMLParser): + def __init__(self): + super().__init__() + self.inline = [] + + def handle_starttag(self, tag, attrs): + if tag != "script": + return + attributes = dict(attrs) + if "src" in attributes or attributes.get("type") == "application/json": + return + self.inline.append(self.get_starttag_text()) + + class TestContentSecurityPolicy(AppRouteMixin, unittest.TestCase): def test_page_ships_no_executable_inline_script(self): body = self.client.get("/de/").get_data(as_text=True) - inline = [ - tag - for tag in re.findall(r"]*>", body) - if "src=" not in tag and 'type="application/json"' not in tag - ] + collector = InlineScriptCollector() + collector.feed(body) self.assertEqual( - inline, + collector.inline, [], "a host CSP can only hash an inline script whose content it knows, " "and this one changes with every language", diff --git a/tests/unit/test_i18n.py b/tests/unit/test_i18n.py index 5366c19..50ef208 100644 --- a/tests/unit/test_i18n.py +++ b/tests/unit/test_i18n.py @@ -2,8 +2,8 @@ import re import shutil import tempfile import unittest +import unittest.mock from pathlib import Path -from unittest import mock import yaml @@ -170,7 +170,7 @@ class TestCatalogMerge(unittest.TestCase): ) def test_an_unsupported_code_never_becomes_a_path(self): - with mock.patch.object(i18n, "read_catalog") as read: + with unittest.mock.patch.object(i18n, "read_catalog") as read: self.assertEqual(i18n.catalog("../content/de"), {}) read.assert_not_called()