Add server-side test runner to /specs/testing page

Python evaluator runs test.sx at page load, results shown alongside
the browser runner. Both hosts prove the same 81 tests from the same
spec file — server on render, client on click.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 11:10:24 +00:00
parent 9b3b2ea224
commit 6f403c0c2d
4 changed files with 94 additions and 5 deletions

View File

@@ -342,7 +342,8 @@
:source (read-spec-file (get item "filename"))))
extension-spec-items))
"testing" (~spec-testing-content
:spec-source (read-spec-file "test.sx"))
:spec-source (read-spec-file "test.sx")
:server-results (run-spec-tests))
:else (let ((spec (find-spec slug)))
(if spec
(~spec-detail-content

View File

@@ -24,6 +24,7 @@ def _register_sx_helpers() -> None:
"bundle-analyzer-data": _bundle_analyzer_data,
"routing-analyzer-data": _routing_analyzer_data,
"data-test-data": _data_test_data,
"run-spec-tests": _run_spec_tests,
})
@@ -491,6 +492,76 @@ def _event_detail_data(slug: str) -> dict:
}
def _run_spec_tests() -> dict:
"""Run test.sx against the Python SX evaluator and return results."""
import os
import time
from shared.sx.parser import parse_all
from shared.sx.evaluator import _eval, _trampoline
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
if not os.path.isdir(ref_dir):
ref_dir = "/app/shared/sx/ref"
test_path = os.path.join(ref_dir, "test.sx")
with open(test_path, encoding="utf-8") as f:
src = f.read()
suite_stack: list[str] = []
passed = 0
failed = 0
test_num = 0
lines: list[str] = []
def try_call(thunk):
try:
_trampoline(_eval([thunk], {}))
return {"ok": True}
except Exception as e:
return {"ok": False, "error": str(e)}
def report_pass(name):
nonlocal passed, test_num
test_num += 1
passed += 1
lines.append("ok " + str(test_num) + " - " + " > ".join(suite_stack + [name]))
def report_fail(name, error):
nonlocal failed, test_num
test_num += 1
failed += 1
full = " > ".join(suite_stack + [name])
lines.append("not ok " + str(test_num) + " - " + full)
lines.append(" # " + str(error))
def push_suite(name):
suite_stack.append(name)
def pop_suite():
suite_stack.pop()
env = {
"try-call": try_call,
"report-pass": report_pass,
"report-fail": report_fail,
"push-suite": push_suite,
"pop-suite": pop_suite,
}
t0 = time.monotonic()
exprs = parse_all(src)
for expr in exprs:
_trampoline(_eval(expr, env))
elapsed = round((time.monotonic() - t0) * 1000)
return {
"passed": passed,
"failed": failed,
"total": passed + failed,
"elapsed-ms": elapsed,
"output": "\n".join(lines),
}
def _data_test_data() -> dict:
"""Return test data for the client-side data rendering test page.