Implement flexible entity relation system (Phases A–E)
Declarative relation registry via defrelation s-expressions with cardinality enforcement (one-to-one, one-to-many, many-to-many), registry-aware relate/unrelate/can-relate API endpoints, generic container-nav fragment, and relation-driven UI components. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -264,6 +264,80 @@ class TestErrorPage:
|
||||
assert "<img" not in html
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ~relation-nav
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestRelationNav:
|
||||
def test_renders_link(self):
|
||||
html = sexp(
|
||||
'(~relation-nav :href "/market/farm/" :name "Farm Shop" :icon "fa fa-shopping-bag")',
|
||||
)
|
||||
assert 'href="/market/farm/"' in html
|
||||
assert "Farm Shop" in html
|
||||
assert "fa fa-shopping-bag" in html
|
||||
|
||||
def test_no_icon(self):
|
||||
html = sexp(
|
||||
'(~relation-nav :href "/cal/" :name "Events")',
|
||||
)
|
||||
assert 'href="/cal/"' in html
|
||||
assert "Events" in html
|
||||
assert "fa " not in html
|
||||
|
||||
def test_custom_nav_class(self):
|
||||
html = sexp(
|
||||
'(~relation-nav :href "/" :name "X" :nav-class "custom-class")',
|
||||
**{"nav-class": "custom-class"},
|
||||
)
|
||||
assert 'class="custom-class"' in html
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ~relation-attach
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestRelationAttach:
|
||||
def test_renders_button(self):
|
||||
html = sexp(
|
||||
'(~relation-attach :create-url "/market/create/" :label "Add Market" :icon "fa fa-plus")',
|
||||
**{"create-url": "/market/create/"},
|
||||
)
|
||||
assert 'href="/market/create/"' in html
|
||||
assert 'hx-get="/market/create/"' in html
|
||||
assert "Add Market" in html
|
||||
assert "fa fa-plus" in html
|
||||
|
||||
def test_default_label(self):
|
||||
html = sexp(
|
||||
'(~relation-attach :create-url "/create/")',
|
||||
**{"create-url": "/create/"},
|
||||
)
|
||||
assert "Add" in html
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ~relation-detach
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestRelationDetach:
|
||||
def test_renders_button(self):
|
||||
html = sexp(
|
||||
'(~relation-detach :detach-url "/api/unrelate" :name "Farm Shop")',
|
||||
**{"detach-url": "/api/unrelate"},
|
||||
)
|
||||
assert 'hx-delete="/api/unrelate"' in html
|
||||
assert 'hx-confirm="Remove Farm Shop?"' in html
|
||||
assert "fa fa-times" in html
|
||||
|
||||
def test_default_name(self):
|
||||
html = sexp(
|
||||
'(~relation-detach :detach-url "/api/unrelate")',
|
||||
**{"detach-url": "/api/unrelate"},
|
||||
)
|
||||
assert "this item" in html
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# render_page() helper
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user