App shell with sidebar and theme switch; attribute-set management; project rename; new pages for projects, runbooks and activity
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477
This commit is contained in:
parent
a6ee6a0a6e
commit
6579618737
9 changed files with 663 additions and 13 deletions
|
|
@ -249,3 +249,67 @@ def test_project_without_a_given_name_uses_its_id_never_the_templates_title(repo
|
|||
J.instantiate(reg, "lighthouse-watch", "ab", "staging")
|
||||
with pytest.raises(ValueError, match="secret"):
|
||||
J.instantiate(reg, "lighthouse-watch", "leaky-one", "staging", description="token hvs.ABCDEFGHIJKLMN")
|
||||
|
||||
|
||||
# ---- managing attribute sets and editing projects --------------------------------------------------------------------
|
||||
|
||||
def test_used_by_finds_projects_templates_targets_and_extending_sets(repo):
|
||||
from rtut.attrs import used_by
|
||||
reg = project(repo) # north-watch uses stormy-coast, which extends harbour-defaults
|
||||
u = used_by(reg, "stormy-coast")
|
||||
assert u == {"projects": ["north-watch"], "templates": [], "sets": []}
|
||||
u = used_by(reg, "harbour-defaults")
|
||||
assert u["templates"] == ["lighthouse-watch"] and u["sets"] == ["stormy-coast"]
|
||||
|
||||
|
||||
def test_save_set_writes_validates_and_normalizes(repo):
|
||||
from rtut.attrs import save_set
|
||||
reg = Registry([repo])
|
||||
path = save_set(reg, repo, "team-defaults", "Team defaults", ["harbour-defaults"],
|
||||
{"lamp": {"value": "electric"}, "keeper": {"requirement": "required", "note": "who"}, "empty_note": {"note": "later"}})
|
||||
made = yaml.safe_load(path.read_text())
|
||||
assert path == repo / "attribute-sets/team-defaults.yaml" and made["extends"] == ["harbour-defaults"]
|
||||
assert made["attributes"]["lamp"] == "electric" # a lone value is written as a scalar
|
||||
assert made["attributes"]["keeper"] == {"requirement": "required", "note": "who"}
|
||||
reg = Registry([repo])
|
||||
assert reg.sets["team-defaults"].ok and fold(set_layers(reg, "team-defaults"))["lamp"]["value"] == "electric"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kwargs,frag", [
|
||||
({"set_id": "Bad Id"}, "lower-case"), ({"title": "ab"}, "3 characters"), ({"extends": ["ghost"]}, "unknown attribute set"),
|
||||
({"extends": ["team-x"]}, "itself"), ({"attributes": {"Bad-Name": {"value": "x"}}}, "bad attribute name"),
|
||||
({"attributes": {"a": {"value": "hvs.ABCDEFGHIJKLMN"}}}, "secret"), ({"attributes": {"a": {"requirement": "maybe", "value": "x"}}}, "requirement"),
|
||||
({"attributes": {"a": {}}}, "give a value"),
|
||||
])
|
||||
def test_save_set_refusals(repo, kwargs, frag):
|
||||
from rtut.attrs import save_set
|
||||
args = {"set_id": "team-x", "title": "Team x", "extends": [], "attributes": {"a": {"value": "1"}}, **kwargs}
|
||||
with pytest.raises(ValueError, match=frag):
|
||||
save_set(Registry([repo]), repo, **args)
|
||||
assert not (repo / "attribute-sets/team-x.yaml").exists()
|
||||
|
||||
|
||||
def test_save_set_refuses_a_cycle(repo):
|
||||
from rtut.attrs import save_set
|
||||
reg = Registry([repo])
|
||||
with pytest.raises(ValueError, match="circular"):
|
||||
save_set(reg, repo, "harbour-defaults", "Harbour defaults", ["stormy-coast"], {"lamp": {"value": "x"}}, reg.sets["harbour-defaults"].path)
|
||||
|
||||
|
||||
def test_update_project_renames_and_keeps_everything_else(repo):
|
||||
reg = project(repo)
|
||||
doc = reg.projects["north-watch"]
|
||||
before = yaml.safe_load(doc.path.read_text())
|
||||
J.update_project(doc, "North harbour watch", "Our harbour", "Both lights burn")
|
||||
after = yaml.safe_load(doc.path.read_text())
|
||||
assert after["title"] == "North harbour watch" and after["description"] == "Our harbour" and after["goal"] == "Both lights burn"
|
||||
assert after["runbooks"] == before["runbooks"] and after["attributes"] == before["attributes"] and after["id"] == "north-watch"
|
||||
assert list(after)[:5] == ["spec", "id", "title", "description", "goal"]
|
||||
J.update_project(Registry([repo]).projects["north-watch"], "North harbour watch", "", "")
|
||||
assert "description" not in yaml.safe_load(doc.path.read_text())
|
||||
for bad, frag in (("ab", "3 characters"), ("x" * 5 + "hvs.ABCDEFGHIJKLMN", "secret")):
|
||||
with pytest.raises(ValueError, match=frag):
|
||||
J.update_project(Registry([repo]).projects["north-watch"], bad)
|
||||
reg = Registry([repo])
|
||||
with pytest.raises(ValueError, match="only a project"):
|
||||
J.update_project(reg.templates["lighthouse-watch"], "Renamed template")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue