Refinements to the dependency exploration ui

This commit is contained in:
2026-05-04 12:17:48 +02:00
parent 07c9a95efc
commit 356c0026ef
8 changed files with 408 additions and 36 deletions

View File

@@ -333,16 +333,169 @@ def test_dependency_graph_enriches_layers_and_filters_with_profiles(tmp_path):
assert fact_node["layer"] == "fact"
assert fact_node["path"] == fact.path
assert fact_node["displayState"] == "blur"
assert fact_node["reviewState"] == "accepted"
assert fact_node["visualSize"] == 36
assert feature_node["displayState"] == "show"
assert feature_node["visibilitySource"] == "manual"
assert feature_node["visualSize"] == 50
assert evidence_node["layer"] == "evidence"
assert evidence_node["visualSize"] == 53
assert payload["filter"]["orphaned_overrides"] == ["missing:1"]
assert payload["metrics"]["hidden_count"] == 0
assert any(
element["data"].get("target") == f"feature:{feature_id}"
and element["data"].get("sourceKind") == "evidence"
evidence_edge = next(
element["data"]
for element in payload["elements"]
if element["data"].get("target") == f"feature:{feature_id}"
and element["data"].get("sourceKind") == "evidence"
)
assert evidence_edge["edgeWidth"] == 5
assert evidence_edge["reviewState"] == "accepted"
def test_dependency_graph_filters_review_state_and_marks_blurred_edges(tmp_path):
service = make_service(tmp_path)
repository = service.register_repository(
name="Review State",
url="https://example.com/review-state.git",
description="Review state fixture.",
)
ability_id = service.add_ability(repository.id, name="Graph Review")
capability_id = service.add_capability(repository.id, ability_id, name="Inspect")
feature_id = service.add_feature(
repository.id,
capability_id,
name="Inspector",
type="UI",
confidence=0.5,
)
payload = service.dependency_graph_elements(
repository.id,
rules=[
{
"name": "blur accepted",
"action": "blur",
"match": {"reviewState": "accepted"},
}
],
use_latest_profile=False,
)
feature = next(
element["data"]
for element in payload["elements"]
if element["data"].get("id") == f"feature:{feature_id}"
)
edge = next(
element["data"]
for element in payload["elements"]
if element["data"].get("source") == f"feature:{feature_id}"
)
assert feature["displayState"] == "blur"
assert edge["connectedToBlurred"] is True
def test_dependency_graph_uses_latest_profile_by_default(tmp_path):
service = make_service(tmp_path)
repository = service.register_repository(
name="Latest Profile",
url="https://example.com/latest-profile.git",
description="Latest profile fixture.",
)
ability_id = service.add_ability(repository.id, name="Profile Defaults")
service.add_capability(repository.id, ability_id, name="Load Profile")
first = service.create_dependency_graph_profile(
repository.id,
name="First",
filter_rules=[
{"name": "blur abilities", "action": "blur", "match": {"layer": "ability"}}
],
)
second = service.create_dependency_graph_profile(
repository.id,
name="Second",
filter_rules=[
{"name": "hide abilities", "action": "hide", "match": {"layer": "ability"}}
],
)
default_payload = service.dependency_graph_elements(repository.id)
explicit_payload = service.dependency_graph_elements(
repository.id,
profile_id=first.id,
)
unsaved_payload = service.dependency_graph_elements(
repository.id,
use_latest_profile=False,
)
assert default_payload["profile"]["id"] == second.id
assert default_payload["metrics"]["hidden_count"] >= 1
assert explicit_payload["profile"]["id"] == first.id
assert unsaved_payload["profile"] is None
def test_dependency_graph_deduplicates_document_fact_nodes(tmp_path):
service = make_service(tmp_path)
repository = service.register_repository(
name="Docs",
url="https://example.com/docs.git",
description="Document graph fixture.",
)
ability_id = service.add_ability(repository.id, name="Documented Operation")
capability_id = service.add_capability(repository.id, ability_id, name="Read Docs")
run = service.store.create_analysis_run(repository.id)
with service.store.connect() as connection:
cursor = connection.execute(
"""
INSERT INTO observed_facts
(repository_id, analysis_run_id, snapshot_id, kind, path, name, value, metadata)
VALUES (?, ?, NULL, 'documentation', 'README.md', 'README', '', '{}')
""",
(repository.id, run.id),
)
readme_fact_id = int(cursor.lastrowid)
cursor = connection.execute(
"""
INSERT INTO observed_facts
(repository_id, analysis_run_id, snapshot_id, kind, path, name, value, metadata)
VALUES (?, ?, NULL, 'scope', 'SCOPE.md', 'SCOPE', '', ?)
""",
(repository.id, run.id, '{"source_role": "derived_scope"}'),
)
scope_fact_id = int(cursor.lastrowid)
service.store.create_feature(
repository.id,
capability_id,
name="README backed feature",
type="docs",
location="README.md",
confidence=0.7,
source_refs=[
SourceReference(
fact_id=readme_fact_id,
path="README.md",
kind="documentation",
name="README",
),
SourceReference(
fact_id=scope_fact_id,
path="SCOPE.md",
kind="scope",
name="SCOPE",
),
],
)
payload = service.dependency_graph_elements(repository.id, use_latest_profile=False)
fact_nodes = [
element["data"]
for element in payload["elements"]
if element["data"].get("kind") == "fact"
]
assert [node["id"] for node in fact_nodes] == ["fact:document:README.md"]
assert fact_nodes[0]["label"] == "README.md (documentation)"
def test_manual_registry_updates_and_deletes_approved_entries(tmp_path):

View File

@@ -1542,8 +1542,27 @@ def test_ui_register_analyze_and_approve_loop(tmp_path):
)
assert all(
"layer" in element["data"]
and "reviewState" in element["data"]
for element in graph_payload["elements"]
)
review_filter_response = client.post(
f"/repos/{repository_id}/dependency-graph/filter",
json={
"rules": [
{
"name": "blur accepted",
"action": "blur",
"match": {"reviewState": "accepted"},
}
],
"manual_overrides": {},
},
)
assert review_filter_response.status_code == 200
assert all(
element["data"]["displayState"] == "blur"
for element in review_filter_response.json()["elements"]
)
profile_response = client.post(
f"/repos/{repository_id}/dependency-graph/profiles",
@@ -1578,6 +1597,15 @@ def test_ui_register_analyze_and_approve_loop(tmp_path):
)
assert duplicate_response.status_code == 201
assert duplicate_response.json()["name"] == "Hide Facts Copy"
latest_response = client.get(f"/repos/{repository_id}/dependency-graph")
assert latest_response.status_code == 200
assert latest_response.json()["profile"]["name"] == "Hide Facts Copy"
unsaved_response = client.get(
f"/repos/{repository_id}/dependency-graph",
params={"use_latest_profile": False},
)
assert unsaved_response.status_code == 200
assert unsaved_response.json()["profile"] is None
graph_page = client.get(f"/ui/repos/{repository_id}/dependency-graph")
assert graph_page.status_code == 200
@@ -1585,7 +1613,9 @@ def test_ui_register_analyze_and_approve_loop(tmp_path):
assert "cytoscape.min.js" in graph_page.text
assert 'data-graph-mode="impact"' in graph_page.text
assert 'id="profile-select"' in graph_page.text
assert 'id="filter-review-state"' in graph_page.text
assert 'data-override="blur"' in graph_page.text
assert "graph-popup" in graph_page.text
scope_listing = client.get(
f"/ui/repos/{repository_id}/elements",