diff --git a/mandelstudio/models.py b/mandelstudio/models.py index a9a19a2..e90e0e6 100644 --- a/mandelstudio/models.py +++ b/mandelstudio/models.py @@ -20,7 +20,9 @@ from mandelblog_content_guard.mixins import MultilingualValidationMixin @register_snippet -class LocalizedFooterContent(MultilingualValidationMixin, TranslatableMixin, models.Model): +class LocalizedFooterContent( + MultilingualValidationMixin, TranslatableMixin, models.Model +): title = models.CharField(max_length=120, default="Footer content") site = models.ForeignKey( Site, on_delete=models.CASCADE, related_name="localized_footer_contents" diff --git a/mandelstudio/settings/base.py b/mandelstudio/settings/base.py index 240e64e..08a23f6 100644 --- a/mandelstudio/settings/base.py +++ b/mandelstudio/settings/base.py @@ -77,5 +77,7 @@ CONTENT_GUARD_REWRITE_BACKEND = None if "test" in sys.argv: MIGRATION_MODULES = globals().get("MIGRATION_MODULES", {}).copy() - MIGRATION_MODULES["template_engine"] = "mandelstudio.test_migrations.template_engine" + MIGRATION_MODULES["template_engine"] = ( + "mandelstudio.test_migrations.template_engine" + ) TEST_RUNNER = "django.test.runner.DiscoverRunner" diff --git a/mandelstudio/test_migrations/template_engine/0001_initial.py b/mandelstudio/test_migrations/template_engine/0001_initial.py index 74a149a..387071c 100644 --- a/mandelstudio/test_migrations/template_engine/0001_initial.py +++ b/mandelstudio/test_migrations/template_engine/0001_initial.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0001_initial").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0001_initial" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0002_templateenginesitesettings.py b/mandelstudio/test_migrations/template_engine/0002_templateenginesitesettings.py index 412f092..084f57e 100644 --- a/mandelstudio/test_migrations/template_engine/0002_templateenginesitesettings.py +++ b/mandelstudio/test_migrations/template_engine/0002_templateenginesitesettings.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0002_templateenginesitesettings").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0002_templateenginesitesettings" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0003_templateenginesitesettings_nav_items.py b/mandelstudio/test_migrations/template_engine/0003_templateenginesitesettings_nav_items.py index dc89c8a..1bb5f35 100644 --- a/mandelstudio/test_migrations/template_engine/0003_templateenginesitesettings_nav_items.py +++ b/mandelstudio/test_migrations/template_engine/0003_templateenginesitesettings_nav_items.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0003_templateenginesitesettings_nav_items").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0003_templateenginesitesettings_nav_items" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0004_alter_basehomepage_body_alter_basestandardpage_body.py b/mandelstudio/test_migrations/template_engine/0004_alter_basehomepage_body_alter_basestandardpage_body.py index 245fe91..65c0ddd 100644 --- a/mandelstudio/test_migrations/template_engine/0004_alter_basehomepage_body_alter_basestandardpage_body.py +++ b/mandelstudio/test_migrations/template_engine/0004_alter_basehomepage_body_alter_basestandardpage_body.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0004_alter_basehomepage_body_alter_basestandardpage_body").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0004_alter_basehomepage_body_alter_basestandardpage_body" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0005_templateenginesitesettings_header_variant_and_more.py b/mandelstudio/test_migrations/template_engine/0005_templateenginesitesettings_header_variant_and_more.py index f41fea5..f2e42c0 100644 --- a/mandelstudio/test_migrations/template_engine/0005_templateenginesitesettings_header_variant_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0005_templateenginesitesettings_header_variant_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0005_templateenginesitesettings_header_variant_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0005_templateenginesitesettings_header_variant_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0006_templateenginesitesettings_footer_dynamic_fields.py b/mandelstudio/test_migrations/template_engine/0006_templateenginesitesettings_footer_dynamic_fields.py index 895ebb9..c9973b8 100644 --- a/mandelstudio/test_migrations/template_engine/0006_templateenginesitesettings_footer_dynamic_fields.py +++ b/mandelstudio/test_migrations/template_engine/0006_templateenginesitesettings_footer_dynamic_fields.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0006_templateenginesitesettings_footer_dynamic_fields").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0006_templateenginesitesettings_footer_dynamic_fields" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0007_templateenginesitesettings_header_cta_fields.py b/mandelstudio/test_migrations/template_engine/0007_templateenginesitesettings_header_cta_fields.py index de4ef28..0750119 100644 --- a/mandelstudio/test_migrations/template_engine/0007_templateenginesitesettings_header_cta_fields.py +++ b/mandelstudio/test_migrations/template_engine/0007_templateenginesitesettings_header_cta_fields.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0007_templateenginesitesettings_header_cta_fields").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0007_templateenginesitesettings_header_cta_fields" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0008_templateenginesitesettings_footer_bottom_links_and_more.py b/mandelstudio/test_migrations/template_engine/0008_templateenginesitesettings_footer_bottom_links_and_more.py index e704758..5302803 100644 --- a/mandelstudio/test_migrations/template_engine/0008_templateenginesitesettings_footer_bottom_links_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0008_templateenginesitesettings_footer_bottom_links_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0008_templateenginesitesettings_footer_bottom_links_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0008_templateenginesitesettings_footer_bottom_links_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0009_alter_basehomepage_body_alter_basestandardpage_body_and_more.py b/mandelstudio/test_migrations/template_engine/0009_alter_basehomepage_body_alter_basestandardpage_body_and_more.py index 3c9266d..334bb93 100644 --- a/mandelstudio/test_migrations/template_engine/0009_alter_basehomepage_body_alter_basestandardpage_body_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0009_alter_basehomepage_body_alter_basestandardpage_body_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0009_alter_basehomepage_body_alter_basestandardpage_body_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0009_alter_basehomepage_body_alter_basestandardpage_body_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0010_enginepage_and_more.py b/mandelstudio/test_migrations/template_engine/0010_enginepage_and_more.py index f3ab3c2..dfe8125 100644 --- a/mandelstudio/test_migrations/template_engine/0010_enginepage_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0010_enginepage_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0010_enginepage_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0010_enginepage_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0011_alter_basehomepage_body_alter_basestandardpage_body_and_more.py b/mandelstudio/test_migrations/template_engine/0011_alter_basehomepage_body_alter_basestandardpage_body_and_more.py index ab5d61f..088adf9 100644 --- a/mandelstudio/test_migrations/template_engine/0011_alter_basehomepage_body_alter_basestandardpage_body_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0011_alter_basehomepage_body_alter_basestandardpage_body_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0011_alter_basehomepage_body_alter_basestandardpage_body_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0011_alter_basehomepage_body_alter_basestandardpage_body_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0012_alter_basehomepage_body_alter_basestandardpage_body_and_more.py b/mandelstudio/test_migrations/template_engine/0012_alter_basehomepage_body_alter_basestandardpage_body_and_more.py index 1e8b5ba..dcfd4f6 100644 --- a/mandelstudio/test_migrations/template_engine/0012_alter_basehomepage_body_alter_basestandardpage_body_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0012_alter_basehomepage_body_alter_basestandardpage_body_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0012_alter_basehomepage_body_alter_basestandardpage_body_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0012_alter_basehomepage_body_alter_basestandardpage_body_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0013_engineblockpreset.py b/mandelstudio/test_migrations/template_engine/0013_engineblockpreset.py index fc35c85..7238dba 100644 --- a/mandelstudio/test_migrations/template_engine/0013_engineblockpreset.py +++ b/mandelstudio/test_migrations/template_engine/0013_engineblockpreset.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0013_engineblockpreset").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0013_engineblockpreset" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0014_alter_basehomepage_body_alter_basestandardpage_body_and_more.py b/mandelstudio/test_migrations/template_engine/0014_alter_basehomepage_body_alter_basestandardpage_body_and_more.py index 0b531c9..ce15905 100644 --- a/mandelstudio/test_migrations/template_engine/0014_alter_basehomepage_body_alter_basestandardpage_body_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0014_alter_basehomepage_body_alter_basestandardpage_body_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0014_alter_basehomepage_body_alter_basestandardpage_body_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0014_alter_basehomepage_body_alter_basestandardpage_body_and_more" +).Migration diff --git a/mandelstudio/test_migrations/template_engine/0015_ensure_templateenginenavitem_table.py b/mandelstudio/test_migrations/template_engine/0015_ensure_templateenginenavitem_table.py index fbf5130..af6aa13 100644 --- a/mandelstudio/test_migrations/template_engine/0015_ensure_templateenginenavitem_table.py +++ b/mandelstudio/test_migrations/template_engine/0015_ensure_templateenginenavitem_table.py @@ -13,7 +13,10 @@ def _ensure_navitem_table(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ("template_engine", "0014_alter_basehomepage_body_alter_basestandardpage_body_and_more"), + ( + "template_engine", + "0014_alter_basehomepage_body_alter_basestandardpage_body_and_more", + ), ] operations = [ diff --git a/mandelstudio/test_migrations/template_engine/0016_alter_basehomepage_body_alter_basestandardpage_body_and_more.py b/mandelstudio/test_migrations/template_engine/0016_alter_basehomepage_body_alter_basestandardpage_body_and_more.py index 6ca0012..0f95a2a 100644 --- a/mandelstudio/test_migrations/template_engine/0016_alter_basehomepage_body_alter_basestandardpage_body_and_more.py +++ b/mandelstudio/test_migrations/template_engine/0016_alter_basehomepage_body_alter_basestandardpage_body_and_more.py @@ -1,2 +1,5 @@ from importlib import import_module -Migration = import_module("ocyan.plugin.template_engine.engine.migrations.0016_alter_basehomepage_body_alter_basestandardpage_body_and_more").Migration + +Migration = import_module( + "ocyan.plugin.template_engine.engine.migrations.0016_alter_basehomepage_body_alter_basestandardpage_body_and_more" +).Migration diff --git a/mandelstudio/tests/test_content_guard.py b/mandelstudio/tests/test_content_guard.py index e96fb76..fa0baca 100644 --- a/mandelstudio/tests/test_content_guard.py +++ b/mandelstudio/tests/test_content_guard.py @@ -9,39 +9,66 @@ from django.test import SimpleTestCase, override_settings from mandelblog_content_guard.agents import get_language_agent from mandelblog_content_guard.ai import rewrite_ai_output -from mandelblog_content_guard.system_strings import build_system_rewrite_candidates, build_system_vocabulary +from mandelblog_content_guard.system_strings import ( + build_system_rewrite_candidates, + build_system_vocabulary, +) from mandelblog_content_guard.types import split_issues -from mandelblog_content_guard.validators.multilingual import extract_visible_rendered_text, validate_text_nodes +from mandelblog_content_guard.validators.multilingual import ( + extract_visible_rendered_text, + validate_text_nodes, +) class ContentGuardRuleTests(SimpleTestCase): def test_mixed_language_detection_blocks(self): issues = validate_text_nodes( "pt", - [("body.hero_text", 'Poiché l\'input "Unverbindliche Erstberatung" è in tedesco')], + [ + ( + "body.hero_text", + 'Poiché l\'input "Unverbindliche Erstberatung" è in tedesco', + ) + ], ) blocking, _warnings = split_issues(issues) self.assertTrue(blocking) - self.assertTrue(any(issue.issue_type == "known_bad_pattern" for issue in blocking)) + self.assertTrue( + any(issue.issue_type == "known_bad_pattern" for issue in blocking) + ) def test_cta_mismatch_detection_blocks(self): issues = validate_text_nodes("en", [("body.cta_text", "Plan kennismaking")]) blocking, _warnings = split_issues(issues) - self.assertTrue(any(issue.issue_type == "cta_language_mismatch" for issue in blocking)) + self.assertTrue( + any(issue.issue_type == "cta_language_mismatch" for issue in blocking) + ) def test_form_validation_blocks_wrong_language(self): issues = validate_text_nodes("ru", [("body.form.label", "Correo electrónico")]) blocking, _warnings = split_issues(issues) - self.assertTrue(any(issue.issue_type in {"known_bad_pattern", "form_language_mismatch"} for issue in blocking)) + self.assertTrue( + any( + issue.issue_type in {"known_bad_pattern", "form_language_mismatch"} + for issue in blocking + ) + ) @override_settings(CONTENT_GUARD_BLOCK_MEDIUM=True) def test_medium_can_be_blocked_in_strict_mode(self): issues = validate_text_nodes( "en", - [("body.summary", "le la les et avec pour vous une pas des extra words to trigger heuristic")], + [ + ( + "body.summary", + "le la les et avec pour vous une pas des extra words to trigger heuristic", + ) + ], ) blocking, _warnings = split_issues(issues) - self.assertTrue(any(issue.issue_type == "language_heuristic" for issue in blocking)) + self.assertTrue( + any(issue.issue_type == "language_heuristic" for issue in blocking) + ) def test_language_agent_registry(self): agent = get_language_agent("pt") @@ -56,7 +83,9 @@ class ContentGuardRuleTests(SimpleTestCase): def test_portuguese_agent_contextual_badge_rewrite(self): agent = get_language_agent("pt") self.assertEqual(agent.rewrite("SERVICES", "body.cards[0].badge"), "SERVIÇOS") - self.assertEqual(agent.rewrite("Transparent", "body.metrics[0].label"), "Investimento claro") + self.assertEqual( + agent.rewrite("Transparent", "body.metrics[0].label"), "Investimento claro" + ) def test_french_agent_contextual_badge_rewrite(self): agent = get_language_agent("fr") @@ -66,8 +95,12 @@ class ContentGuardRuleTests(SimpleTestCase): def test_german_agent_normalizes_non_system_copy(self): agent = get_language_agent("de") self.assertEqual(agent.rewrite("New", "body.cards[0].badge"), "Neu") - self.assertEqual(agent.rewrite("Intakegespräch", "body.stats[0].label"), "Erstgespräch") - self.assertEqual(agent.rewrite("Was du bekommst", "body.heading"), "Was Sie erhalten") + self.assertEqual( + agent.rewrite("Intakegespräch", "body.stats[0].label"), "Erstgespräch" + ) + self.assertEqual( + agent.rewrite("Was du bekommst", "body.heading"), "Was Sie erhalten" + ) self.assertEqual( agent.rewrite("Sales-ready mit skalierbarem Stack", "body.cards[0].text"), "Verkaufsbereit mit skalierbarer Architektur", @@ -91,9 +124,16 @@ class ContentGuardRuleTests(SimpleTestCase): def test_portuguese_rewrite_candidates_are_detected(self): issues = validate_text_nodes( "pt", - [("body.hero_text", "Siti web e negozi online che sono rapidamente online e facili da gestire")], + [ + ( + "body.hero_text", + "Siti web e negozi online che sono rapidamente online e facili da gestire", + ) + ], + ) + self.assertTrue( + any(issue.issue_type == "mixed_locale_heading" for issue in issues) ) - self.assertTrue(any(issue.issue_type == "mixed_locale_heading" for issue in issues)) def test_french_foreign_ui_label_is_detected(self): issues = validate_text_nodes( @@ -105,9 +145,14 @@ class ContentGuardRuleTests(SimpleTestCase): def test_de_canonical_system_strings_are_not_rewrite_candidates(self): issues = validate_text_nodes( "de", - [("body.metric_label", "Durchschnittliche Lieferung"), ("body.badge", "PLAN")], + [ + ("body.metric_label", "Durchschnittliche Lieferung"), + ("body.badge", "PLAN"), + ], + ) + self.assertFalse( + any(issue.bad_value == "Durchschnittliche Lieferung" for issue in issues) ) - self.assertFalse(any(issue.bad_value == "Durchschnittliche Lieferung" for issue in issues)) self.assertFalse(any(issue.bad_value == "PLAN" for issue in issues)) def test_extract_visible_rendered_text_ignores_hidden_script_and_style(self): @@ -131,21 +176,40 @@ class ContentGuardRuleTests(SimpleTestCase): def test_system_strings_are_centralized_for_fr_and_pt(self): self.assertEqual(build_system_vocabulary("fr")["PLAN"], "FORFAIT") - self.assertEqual(build_system_vocabulary("fr")["Reaktionszeit"], "Temps de réponse") + self.assertEqual( + build_system_vocabulary("fr")["Reaktionszeit"], "Temps de réponse" + ) self.assertEqual(build_system_vocabulary("pt")["Transparent"], "Transparente") - self.assertEqual(build_system_vocabulary("fr")["Transparente Investition"], "Investissement transparent") - self.assertEqual(build_system_vocabulary("pt")["Transparente Investition"], "Investimento transparente") - self.assertEqual(build_system_rewrite_candidates()["Durchschnittliche Lieferung"], "foreign_ui_label") + self.assertEqual( + build_system_vocabulary("fr")["Transparente Investition"], + "Investissement transparent", + ) + self.assertEqual( + build_system_vocabulary("pt")["Transparente Investition"], + "Investimento transparente", + ) + self.assertEqual( + build_system_rewrite_candidates()["Durchschnittliche Lieferung"], + "foreign_ui_label", + ) class AuditLocalesCommandTests(SimpleTestCase): - @mock.patch("mandelblog_content_guard.management.commands.audit_locales.audit_locales") + @mock.patch( + "mandelblog_content_guard.management.commands.audit_locales.audit_locales" + ) def test_json_output(self, audit_locales_mock): run = mock.Mock() run.pk = 12 run.total_urls_checked = 2 run.issues_found = 1 - run.summary = {"en": {"total_urls_checked": 2, "issues_found": 1, "by_severity": {"block": 1}}} + run.summary = { + "en": { + "total_urls_checked": 2, + "issues_found": 1, + "by_severity": {"block": 1}, + } + } issue = mock.Mock( url="/en/contact/", title="Contact", @@ -166,16 +230,29 @@ class AuditLocalesCommandTests(SimpleTestCase): self.assertEqual(payload["run_id"], 12) self.assertEqual(payload["issues"]["en"][0]["bad_value"], "Correo electrónico") - @mock.patch("mandelblog_content_guard.management.commands.audit_locales.audit_locales") + @mock.patch( + "mandelblog_content_guard.management.commands.audit_locales.audit_locales" + ) def test_rewrite_flags_are_forwarded(self, audit_locales_mock): run = mock.Mock() run.pk = 13 run.total_urls_checked = 1 run.issues_found = 0 - run.summary = {"pt": {"total_urls_checked": 1, "issues_found": 0, "issues_fixed": 0, "by_severity": {"block": 0, "warn": 0, "log": 0}}} + run.summary = { + "pt": { + "total_urls_checked": 1, + "issues_found": 0, + "issues_fixed": 0, + "by_severity": {"block": 0, "warn": 0, "log": 0}, + } + } run.issues.all.return_value.order_by.return_value = [] audit_locales_mock.return_value = run out = StringIO() - call_command("audit_locales", "--locale", "pt", "--rewrite", "--dry-run", stdout=out) - audit_locales_mock.assert_called_once_with(["pt"], fix=False, rewrite=True, dry_run=True) + call_command( + "audit_locales", "--locale", "pt", "--rewrite", "--dry-run", stdout=out + ) + audit_locales_mock.assert_called_once_with( + ["pt"], fix=False, rewrite=True, dry_run=True + )