refactor: establish frontend page modules

This commit is contained in:
leefer
2026-07-29 22:15:36 +08:00
parent ed2b47fe90
commit b284531dfa
19 changed files with 350 additions and 50 deletions
+56
View File
@@ -22,12 +22,19 @@ class FrontendBoundaryTests(unittest.TestCase):
def test_shared_dependencies_load_before_application(self) -> None:
html = (STATIC / "index.html").read_text(encoding="utf-8")
ui_position = html.index('/ui-core.js')
components_position = html.index('/shared/components.js')
pages_position = html.index('/pages.config.js')
runtime_position = html.index('/pages/runtime.js')
state_position = html.index('/shared/state.js')
api_position = html.index('/shared/api.js')
shell_position = html.index('/shared/shell.js')
app_position = html.index('/app.js')
self.assertLess(ui_position, components_position)
self.assertLess(components_position, pages_position)
self.assertLess(pages_position, state_position)
self.assertLess(pages_position, runtime_position)
self.assertLess(runtime_position, state_position)
self.assertLess(state_position, api_position)
self.assertLess(api_position, shell_position)
self.assertLess(shell_position, app_position)
@@ -72,6 +79,55 @@ class FrontendBoundaryTests(unittest.TestCase):
self.assertIn("function openModalDialog(dialog)", shell)
self.assertNotIn('document.querySelectorAll(".module-tab").forEach', app)
def test_every_registered_view_has_one_feature_page_module(self) -> None:
html = (STATIC / "index.html").read_text(encoding="utf-8")
runtime_position = html.index('/pages/runtime.js')
app_position = html.index('/app.js')
expected = {
page["id"]: page["feature"]
for page in json.loads(
(ROOT / "config" / "pages.config.json").read_text(encoding="utf-8")
)["pages"]
}
expected["screenerTrackingView"] = "screener"
actual: dict[str, str] = {}
for path in (STATIC / "pages").glob("*/page.js"):
script_url = f'/pages/{path.parent.name}/page.js'
self.assertIn(script_url, html)
self.assertLess(runtime_position, html.index(script_url))
self.assertLess(html.index(script_url), app_position)
script = path.read_text(encoding="utf-8")
for match in re.finditer(
r'XiaobaiPageModules\.register\("([^"]+)",\s*\[(.*?)\]',
script,
re.DOTALL,
):
feature = match.group(1)
for view_id in re.findall(r'"([A-Za-z][A-Za-z0-9]+)"', match.group(2)):
self.assertNotIn(view_id, actual)
actual[view_id] = feature
self.assertEqual(actual, expected)
def test_page_lifecycle_is_owned_outside_application_monolith(self) -> None:
app = (STATIC / "app.js").read_text(encoding="utf-8")
runtime = (STATIC / "pages" / "runtime.js").read_text(encoding="utf-8")
start = app.index("function openView(")
end = app.index("\nfunction initializeAutoTableSorting", start)
open_view = app[start:end]
self.assertIn("pageModules.beforeMount(viewId, previousView);", open_view)
self.assertIn("pageModules.afterMount(viewId, previousView);", open_view)
self.assertNotRegex(open_view, r'viewId\s*[!=]==?\s*"')
self.assertIn("function beforeMount(viewId, previousView)", runtime)
self.assertIn("function afterMount(viewId, previousView)", runtime)
def test_shared_empty_state_component_is_used_by_multiple_features(self) -> None:
components = (STATIC / "shared" / "components.js").read_text(encoding="utf-8")
app = (STATIC / "app.js").read_text(encoding="utf-8")
self.assertIn("function emptyStateHtml(message, options = {})", components)
self.assertIn("function renderEmptyState(target, message, options = {})", components)
self.assertGreaterEqual(app.count("renderEmptyState("), 8)
self.assertGreaterEqual(app.count("emptyStateHtml("), 8)
if __name__ == "__main__":
unittest.main()