All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m51s
The SX parser produces native Python dicts for {:key val} syntax, but
both JSEmitter and PyEmitter had no dict case in emit() — falling through
to str(expr) which output raw AST. This broke client-side routing because
process-page-scripts used {"parsed" (parse-route-pattern ...)} and the
function call was emitted as a JS array of Symbols instead of an actual
function call.
Add _emit_native_dict() to both bootstrappers + 8 unit tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
64 lines
2.1 KiB
Python
64 lines
2.1 KiB
Python
"""Test bootstrapper transpilation: JSEmitter and PyEmitter."""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from shared.sx.parser import parse
|
|
from shared.sx.ref.bootstrap_js import JSEmitter
|
|
from shared.sx.ref.bootstrap_py import PyEmitter
|
|
|
|
|
|
class TestJSEmitterNativeDict:
|
|
"""JS bootstrapper must handle native Python dicts from {:key val} syntax."""
|
|
|
|
def test_simple_string_values(self):
|
|
expr = parse('{"name" "hello"}')
|
|
assert isinstance(expr, dict)
|
|
js = JSEmitter().emit(expr)
|
|
assert js == '{"name": "hello"}'
|
|
|
|
def test_function_call_value(self):
|
|
"""Dict value containing a function call must emit the call, not raw AST."""
|
|
expr = parse('{"parsed" (parse-route-pattern (get page "path"))}')
|
|
js = JSEmitter().emit(expr)
|
|
assert "parseRoutePattern" in js
|
|
assert "Symbol" not in js
|
|
assert js == '{"parsed": parseRoutePattern(get(page, "path"))}'
|
|
|
|
def test_multiple_keys(self):
|
|
expr = parse('{"a" 1 "b" (+ x 2)}')
|
|
js = JSEmitter().emit(expr)
|
|
assert '"a": 1' in js
|
|
assert '"b": (x + 2)' in js
|
|
|
|
def test_nested_dict(self):
|
|
expr = parse('{"outer" {"inner" 42}}')
|
|
js = JSEmitter().emit(expr)
|
|
assert '{"outer": {"inner": 42}}' == js
|
|
|
|
def test_nil_value(self):
|
|
expr = parse('{"key" nil}')
|
|
js = JSEmitter().emit(expr)
|
|
assert '"key": NIL' in js
|
|
|
|
|
|
class TestPyEmitterNativeDict:
|
|
"""Python bootstrapper must handle native Python dicts from {:key val} syntax."""
|
|
|
|
def test_simple_string_values(self):
|
|
expr = parse('{"name" "hello"}')
|
|
py = PyEmitter().emit(expr)
|
|
assert py == "{'name': 'hello'}"
|
|
|
|
def test_function_call_value(self):
|
|
"""Dict value containing a function call must emit the call, not raw AST."""
|
|
expr = parse('{"parsed" (parse-route-pattern (get page "path"))}')
|
|
py = PyEmitter().emit(expr)
|
|
assert "parse_route_pattern" in py
|
|
assert "Symbol" not in py
|
|
|
|
def test_multiple_keys(self):
|
|
expr = parse('{"a" 1 "b" (+ x 2)}')
|
|
py = PyEmitter().emit(expr)
|
|
assert "'a': 1" in py
|
|
assert "'b': (x + 2)" in py
|