Merge branch 'worktree-iso-phase-4' into macros

# Conflicts:
#	shared/static/scripts/sx-browser.js
This commit is contained in:
2026-03-07 18:01:56 +00:00
13 changed files with 1018 additions and 111 deletions

View File

@@ -115,6 +115,8 @@
(dict :label "Parser" :href "/testing/parser")
(dict :label "Router" :href "/testing/router")
(dict :label "Renderer" :href "/testing/render")
(dict :label "Dependencies" :href "/testing/deps")
(dict :label "Engine" :href "/testing/engine")
(dict :label "Runners" :href "/testing/runners")))
(define isomorphism-nav-items (list

View File

@@ -6,7 +6,7 @@
;; Overview page
;; ---------------------------------------------------------------------------
(defcomp ~testing-overview-content (&key server-results framework-source eval-source parser-source router-source render-source)
(defcomp ~testing-overview-content (&key server-results framework-source eval-source parser-source router-source render-source deps-source engine-source)
(~doc-page :title "Testing"
(div :class "space-y-8"
@@ -35,6 +35,8 @@
+-- test-parser.sx 39 tests: tokenizer, parser, serializer
+-- test-router.sx 18 tests: route matching + param extraction
+-- test-render.sx 23 tests: HTML rendering + components
+-- test-deps.sx 33 tests: dependency analysis + IO detection
+-- test-engine.sx 37 tests: trigger/swap/retry parsing
Runners:
run.js Node.js — injects platform fns, runs specs
@@ -51,7 +53,9 @@ Platform functions (5 total):
Per-spec platform functions:
parser: sx-parse, sx-serialize, make-symbol, make-keyword, ...
router: (none — pure spec, uses bootstrapped functions)
render: render-html (wraps parse + render-to-html)")))
render: render-html (wraps parse + render-to-html)
deps: test-env (returns current evaluation environment)
engine: (none — pure spec, uses bootstrapped functions)")))
;; Server results
(when server-results
@@ -86,6 +90,8 @@ Per-spec platform functions:
(textarea :id "test-spec-parser" :style "display:none" parser-source)
(textarea :id "test-spec-router" :style "display:none" router-source)
(textarea :id "test-spec-render" :style "display:none" render-source)
(textarea :id "test-spec-deps" :style "display:none" deps-source)
(textarea :id "test-spec-engine" :style "display:none" engine-source)
(script :src (asset-url "/scripts/sx-test-runner.js")))
;; Test spec index
@@ -107,7 +113,15 @@ Per-spec platform functions:
(a :href "/testing/render" :class "block rounded-lg border border-stone-200 p-5 hover:border-violet-300 hover:bg-violet-50 transition-colors"
(h3 :class "font-semibold text-stone-800" "Renderer")
(p :class "text-sm text-stone-500" "23 tests — elements, attributes, void elements, fragments, escaping, control flow, components")
(p :class "text-xs text-violet-600 mt-1" "test-render.sx"))))
(p :class "text-xs text-violet-600 mt-1" "test-render.sx"))
(a :href "/testing/deps" :class "block rounded-lg border border-stone-200 p-5 hover:border-violet-300 hover:bg-violet-50 transition-colors"
(h3 :class "font-semibold text-stone-800" "Dependencies")
(p :class "text-sm text-stone-500" "33 tests — scan-refs, transitive-deps, components-needed, IO detection, purity classification")
(p :class "text-xs text-violet-600 mt-1" "test-deps.sx"))
(a :href "/testing/engine" :class "block rounded-lg border border-stone-200 p-5 hover:border-violet-300 hover:bg-violet-50 transition-colors"
(h3 :class "font-semibold text-stone-800" "Engine")
(p :class "text-sm text-stone-500" "37 tests — parse-time, trigger specs, swap specs, retry logic, param filtering")
(p :class "text-xs text-violet-600 mt-1" "test-engine.sx"))))
;; What it proves
(div :class "rounded-lg border border-blue-200 bg-blue-50 p-5 space-y-3"

View File

@@ -555,7 +555,9 @@
:eval-source eval-source
:parser-source parser-source
:router-source router-source
:render-source render-source))
:render-source render-source
:deps-source deps-source
:engine-source engine-source))
(defpage testing-page
:path "/testing/<slug>"
@@ -572,6 +574,8 @@
"parser" (run-modular-tests "parser")
"router" (run-modular-tests "router")
"render" (run-modular-tests "render")
"deps" (run-modular-tests "deps")
"engine" (run-modular-tests "engine")
:else (dict))
:content (case slug
"eval" (~testing-spec-content
@@ -602,6 +606,20 @@
:spec-source spec-source
:framework-source framework-source
:server-results server-results)
"deps" (~testing-spec-content
:spec-name "deps"
:spec-title "Dependency Analysis Tests"
:spec-desc "33 tests covering component dependency analysis — scan-refs, scan-components-from-source, transitive-deps, components-needed, scan-io-refs, and component-pure? classification."
:spec-source spec-source
:framework-source framework-source
:server-results server-results)
"engine" (~testing-spec-content
:spec-name "engine"
:spec-title "Engine Tests"
:spec-desc "37 tests covering engine pure functions — parse-time, parse-trigger-spec, default-trigger, parse-swap-spec, parse-retry-spec, next-retry-ms, and filter-params."
:spec-source spec-source
:framework-source framework-source
:server-results server-results)
"runners" (~testing-runners-content)
:else (~testing-overview-content
:server-results server-results)))

View File

@@ -707,6 +707,8 @@ def _run_modular_tests(spec_name: str) -> dict:
"parser": {"file": "test-parser.sx", "needs": ["sx-parse"]},
"router": {"file": "test-router.sx", "needs": []},
"render": {"file": "test-render.sx", "needs": ["render-html"]},
"deps": {"file": "test-deps.sx", "needs": []},
"engine": {"file": "test-engine.sx", "needs": []},
}
specs_to_run = list(SPECS.keys()) if spec_name == "all" else [spec_name]
@@ -721,7 +723,7 @@ def _run_modular_tests(spec_name: str) -> dict:
if not spec:
continue
# Load router from bootstrap if needed
# Load module functions from bootstrap
if sn == "router":
try:
from shared.sx.ref.sx_ref import (
@@ -740,6 +742,46 @@ def _run_modular_tests(spec_name: str) -> dict:
env["make-route-segment"] = make_route_segment
except ImportError:
eval_file("router.sx")
elif sn == "deps":
try:
from shared.sx.ref.sx_ref import (
scan_refs, scan_components_from_source,
transitive_deps, compute_all_deps,
components_needed, page_component_bundle,
page_css_classes, scan_io_refs,
transitive_io_refs, compute_all_io_refs,
component_pure_p,
)
env["scan-refs"] = scan_refs
env["scan-components-from-source"] = scan_components_from_source
env["transitive-deps"] = transitive_deps
env["compute-all-deps"] = compute_all_deps
env["components-needed"] = components_needed
env["page-component-bundle"] = page_component_bundle
env["page-css-classes"] = page_css_classes
env["scan-io-refs"] = scan_io_refs
env["transitive-io-refs"] = transitive_io_refs
env["compute-all-io-refs"] = compute_all_io_refs
env["component-pure?"] = component_pure_p
env["test-env"] = lambda: env
except ImportError:
eval_file("deps.sx")
env["test-env"] = lambda: env
elif sn == "engine":
try:
from shared.sx.ref.sx_ref import (
parse_time, parse_trigger_spec, default_trigger,
parse_swap_spec, parse_retry_spec, filter_params,
)
env["parse-time"] = parse_time
env["parse-trigger-spec"] = parse_trigger_spec
env["default-trigger"] = default_trigger
env["parse-swap-spec"] = parse_swap_spec
env["parse-retry-spec"] = parse_retry_spec
env["next-retry-ms"] = lambda cur, cap: min(cur * 2, cap)
env["filter-params"] = filter_params
except ImportError:
eval_file("engine.sx")
eval_file(spec["file"])
@@ -763,6 +805,8 @@ def _run_modular_tests(spec_name: str) -> dict:
result["parser-source"] = _read_spec_file("test-parser.sx")
result["router-source"] = _read_spec_file("test-router.sx")
result["render-source"] = _read_spec_file("test-render.sx")
result["deps-source"] = _read_spec_file("test-deps.sx")
result["engine-source"] = _read_spec_file("test-engine.sx")
else:
spec = SPECS.get(spec_name)
if spec: