Implement phased modernization infrastructure for transitioning from multi-page legacy routing to SPA portal-shell architecture, plus post-delivery hardening fixes for policy loading, fallback consistency, and governance drift detection. Key changes: - Add route contract enrichment with scope/visibility/compatibility policies - Canonical 302 redirects from legacy direct-entry to /portal-shell/ routes - Asset readiness enforcement and runtime fallback retirement for in-scope routes - Shared feature-flag helpers (env > config > default) replacing duplicated _to_bool - Defensive copy for lru_cached policy payloads preventing mutation corruption - Unified retired-fallback response helper across app and blueprint routes - Frontend/backend route-contract cross-validation in governance gates - Shell CSS token fallback values for routes rendered outside shell scope - Local-safe .env.example defaults with production recommendation comments - Legacy contract fallback warning logging and single-hop redirect optimization Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Hardening tests for modernization policy caching behavior."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from mes_dashboard.core import modernization_policy as policy
|
|
|
|
|
|
def test_scope_matrix_loader_returns_defensive_copy(tmp_path, monkeypatch):
|
|
scope_file = tmp_path / "route_scope_matrix.json"
|
|
scope_file.write_text(
|
|
json.dumps({"in_scope": [{"route": "/wip-overview"}], "deferred": []}),
|
|
encoding="utf-8",
|
|
)
|
|
monkeypatch.setattr(policy, "SCOPE_MATRIX_FILE", scope_file)
|
|
policy.clear_modernization_policy_cache()
|
|
|
|
payload = policy.load_scope_matrix()
|
|
payload["in_scope"].append({"route": "/mutated"})
|
|
|
|
fresh_payload = policy.load_scope_matrix()
|
|
routes = [item["route"] for item in fresh_payload["in_scope"]]
|
|
assert routes == ["/wip-overview"]
|
|
|
|
|
|
def test_scope_matrix_cache_refresh_requires_explicit_clear(tmp_path, monkeypatch):
|
|
scope_file = tmp_path / "route_scope_matrix.json"
|
|
scope_file.write_text(
|
|
json.dumps({"in_scope": [{"route": "/before"}], "deferred": []}),
|
|
encoding="utf-8",
|
|
)
|
|
monkeypatch.setattr(policy, "SCOPE_MATRIX_FILE", scope_file)
|
|
policy.clear_modernization_policy_cache()
|
|
assert [item["route"] for item in policy.load_scope_matrix()["in_scope"]] == ["/before"]
|
|
|
|
scope_file.write_text(
|
|
json.dumps({"in_scope": [{"route": "/after"}], "deferred": []}),
|
|
encoding="utf-8",
|
|
)
|
|
assert [item["route"] for item in policy.load_scope_matrix()["in_scope"]] == ["/before"]
|
|
|
|
policy.clear_modernization_policy_cache()
|
|
assert [item["route"] for item in policy.load_scope_matrix()["in_scope"]] == ["/after"]
|