Merge branch 'mai/kahn/phase-5i-phase-a-design' (phase 5i slice A: project filter dim + descendants toggle)
# Conflicts: # web/dashboard.go # web/server.go # web/templates/dashboard_section.tmpl
This commit is contained in:
@@ -294,3 +294,71 @@ func TestMultiParentBothPathsRouteToSameRow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestProjectFilterScopesTreeToDescendants verifies the Phase 5i Slice A
|
||||
// project scope semantics end-to-end: ?project=<path> narrows / to the picked
|
||||
// item + descendants; ?project_descendants=0 narrows further to the picked
|
||||
// item alone. Both round-trip through ParseTreeFilter + TreeFilter.Matches +
|
||||
// the tree handler.
|
||||
func TestProjectFilterScopesTreeToDescendants(t *testing.T) {
|
||||
srv, pool := mustServer(t)
|
||||
defer pool.Close()
|
||||
h := srv.Routes()
|
||||
ctx := context.Background()
|
||||
|
||||
stamp := strings.ReplaceAll(time.Now().UTC().Format("150405.000"), ".", "")
|
||||
parentSlug := "p5i-parent-" + stamp
|
||||
childSlug := "p5i-child-" + stamp
|
||||
siblingSlug := "p5i-sib-" + stamp
|
||||
|
||||
var dev string
|
||||
if err := pool.QueryRow(ctx, `select id from projax.items where slug='dev' and cardinality(parent_ids)=0`).Scan(&dev); err != nil {
|
||||
t.Fatalf("dev: %v", err)
|
||||
}
|
||||
var parentID, childID, siblingID string
|
||||
if err := pool.QueryRow(ctx,
|
||||
`insert into projax.items (kind, title, slug, parent_ids) values (array['project']::text[], 'P5i Parent', $1, ARRAY[$2]::uuid[]) returning id`,
|
||||
parentSlug, dev).Scan(&parentID); err != nil {
|
||||
t.Fatalf("seed parent: %v", err)
|
||||
}
|
||||
if err := pool.QueryRow(ctx,
|
||||
`insert into projax.items (kind, title, slug, parent_ids) values (array['project']::text[], 'P5i Child', $1, ARRAY[$2]::uuid[]) returning id`,
|
||||
childSlug, parentID).Scan(&childID); err != nil {
|
||||
t.Fatalf("seed child: %v", err)
|
||||
}
|
||||
if err := pool.QueryRow(ctx,
|
||||
`insert into projax.items (kind, title, slug, parent_ids) values (array['project']::text[], 'P5i Sib', $1, ARRAY[$2]::uuid[]) returning id`,
|
||||
siblingSlug, dev).Scan(&siblingID); err != nil {
|
||||
t.Fatalf("seed sibling: %v", err)
|
||||
}
|
||||
defer pool.Exec(context.Background(), `delete from projax.items where id in ($1,$2,$3)`, childID, parentID, siblingID)
|
||||
|
||||
parentPath := "dev." + parentSlug
|
||||
parentLink := `href="/i/` + parentPath + `"`
|
||||
childLink := `href="/i/` + parentPath + `.` + childSlug + `"`
|
||||
siblingLink := `href="/i/dev.` + siblingSlug + `"`
|
||||
|
||||
// Descendants on (default): parent + child visible, sibling hidden.
|
||||
_, withDesc := get(t, h, "/?project="+parentPath)
|
||||
if !strings.Contains(withDesc, parentLink) {
|
||||
t.Errorf("?project=%s should show parent row", parentPath)
|
||||
}
|
||||
if !strings.Contains(withDesc, childLink) {
|
||||
t.Errorf("?project=%s should include descendant child row", parentPath)
|
||||
}
|
||||
if strings.Contains(withDesc, siblingLink) {
|
||||
t.Errorf("?project=%s should exclude sibling row", parentPath)
|
||||
}
|
||||
|
||||
// Descendants off: only the picked item, no children.
|
||||
_, noDesc := get(t, h, "/?project="+parentPath+"&project_descendants=0")
|
||||
if !strings.Contains(noDesc, parentLink) {
|
||||
t.Errorf("?project_descendants=0 should still show the picked parent row")
|
||||
}
|
||||
if strings.Contains(noDesc, childLink) {
|
||||
t.Errorf("?project_descendants=0 should hide the child row")
|
||||
}
|
||||
if strings.Contains(noDesc, siblingLink) {
|
||||
t.Errorf("?project_descendants=0 should hide the sibling row")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user