"""The ES-module layer of the web UI is served the way browsers need it. static/v3/js/core/ and js/pages/ are native ES modules, loaded with ', page) assert tag, "base.html must load js/core/boot.js as a versioned module script" # After every classic script, so nothing classic can depend on it at load. assert page.index(tag.group(0)) > page.index("plugins_manager.js") @pytest.mark.parametrize("module", MODULES, ids=[m.name for m in MODULES]) def test_every_import_resolves_inside_the_module_tree(module): source = module.read_text(encoding="utf-8") for spec in _IMPORT.findall(source): assert spec.startswith("./") or spec.startswith("../"), ( f"{module.name}: {spec!r} -- no bundler, so only relative imports work") target = (module.parent / spec).resolve() assert target.is_file(), f"{module.name}: {spec!r} does not exist" assert any(target.parent == d.resolve() for d in MODULE_DIRS), ( f"{module.name}: {spec!r} leaves js/core and js/pages") # Converted so far: page name -> (its partial, the route that serves it). The # migration order is in docs/WEB_FRONTEND_ARCHITECTURE.md. CONVERTED = { "cache": ("cache.html", "/partials/cache"), "durations": ("durations.html", "/partials/durations"), "operation-history": ("operation_history.html", "/partials/operation-history"), "raw-json": ("raw_json.html", "/partials/raw-json"), "backup-restore": ("backup_restore.html", "/partials/backup-restore"), } # Old window.* names that moved into a page module. Each stays as a # deprecated alias in boot.js that forwards to the module's export. ALIASES = { "cache": ["deleteCacheFile"], "raw-json": ["formatJson", "manualValidateJson", "validateJSON", "saveMainConfig", "saveSecretsConfig"], "backup-restore": ["exportBackup", "loadBackupList", "validateRestoreFile", "clearRestore", "runRestore"], } def _boot(): return (JS / "core" / "boot.js").read_text(encoding="utf-8") def _registered_pages(): return re.findall(r"'([\w-]+)':\s*page\(function\(\)\s*\{\s*return import\('\.\./pages/([\w-]+)\.js'\)", _boot()) def test_every_converted_page_is_registered(): assert dict(_registered_pages()) == {name: name for name in CONVERTED} @pytest.mark.parametrize("name", sorted(CONVERTED)) def test_a_converted_partial_roots_its_page(client, name): partial, route = CONVERTED[name] text = (PARTIALS / partial).read_text(encoding="utf-8") assert f'data-page="{name}"' in text assert "