Spec server definition forms (defhandler/defquery/defaction/defpage) in forms.sx

Previously defhandler routed to sf-define which tried to evaluate
(&key ...) params as expressions. Now each form has its own spec
with parse-key-params and platform constructors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 22:36:56 +00:00
parent 5aa13a99d1
commit d076fc1465
5 changed files with 283 additions and 2 deletions

View File

@@ -328,6 +328,62 @@ class TestAser:
# Macros
# ---------------------------------------------------------------------------
class TestDefcomp:
def test_defcomp_basic(self):
"""defcomp should parse &key params without trying to eval &key as a symbol."""
env = {}
ev('(defcomp ~card (&key title) (div title))', env)
assert isinstance(env.get("~card"), Component)
def test_defcomp_render(self):
env = {}
ev('(defcomp ~card (&key title) (div title))', env)
result = render('(~card :title "hello")', env)
assert result == '<div>hello</div>'
def test_defcomp_with_children(self):
env = {}
ev('(defcomp ~wrap (&key title &rest children) (div title children))', env)
comp = env["~wrap"]
assert comp.has_children is True
assert "title" in comp.params
def test_defcomp_multiple_params(self):
env = {}
ev('(defcomp ~box (&key a b c) (div a b c))', env)
result = render('(~box :a "1" :b "2" :c "3")', env)
assert result == '<div>123</div>'
class TestDefhandler:
def test_defhandler_basic(self):
"""defhandler should parse &key params and create a HandlerDef."""
from shared.sx.types import HandlerDef
env = {}
ev('(defhandler link-card (&key slug keys) (div slug))', env)
hdef = env.get("handler:link-card")
assert isinstance(hdef, HandlerDef)
assert hdef.name == "link-card"
assert hdef.params == ["slug", "keys"]
def test_defquery_basic(self):
from shared.sx.types import QueryDef
env = {}
ev('(defquery get-post (&key slug) "Fetch a post" (list slug))', env)
qdef = env.get("query:get-post")
assert isinstance(qdef, QueryDef)
assert qdef.params == ["slug"]
assert qdef.doc == "Fetch a post"
def test_defaction_basic(self):
from shared.sx.types import ActionDef
env = {}
ev('(defaction save-post (&key title body) (list title body))', env)
adef = env.get("action:save-post")
assert isinstance(adef, ActionDef)
assert adef.params == ["title", "body"]
class TestMacros:
def test_defmacro_and_expand(self):
env = {}