package web import ( "net/url" "testing" "time" "github.com/m/projax/store" ) // TestBuildKanbanBoardGroupByStatus exercises the default group_by — three // columns in canonical order (active/done/archived) populated by status. func TestBuildKanbanBoardGroupByStatus(t *testing.T) { items := []*store.Item{ {ID: "a", Title: "Active1", Status: "active", Paths: []string{"dev.a"}, UpdatedAt: time.Unix(2, 0)}, {ID: "b", Title: "Active2", Status: "active", Paths: []string{"dev.b"}, UpdatedAt: time.Unix(3, 0), Pinned: true}, {ID: "c", Title: "Done1", Status: "done", Paths: []string{"dev.c"}, UpdatedAt: time.Unix(1, 0)}, } board := BuildKanbanBoard(items, GroupByStatus) if got, want := len(board.Columns), 2; got != want { t.Fatalf("columns = %d, want %d", got, want) } if board.Columns[0].Key != "active" { t.Errorf("first column = %q, want active", board.Columns[0].Key) } if board.Columns[1].Key != "done" { t.Errorf("second column = %q, want done", board.Columns[1].Key) } if board.Total != 3 { t.Errorf("Total = %d, want 3", board.Total) } // active column: pinned-first (b), then updated_at desc (a). if board.Columns[0].Items[0].ID != "b" { t.Errorf("pinned item should be first; got %q", board.Columns[0].Items[0].ID) } if board.Columns[0].Items[1].ID != "a" { t.Errorf("second active item = %q, want a", board.Columns[0].Items[1].ID) } } // TestBuildKanbanBoardGroupByTag puts an item with multiple tags into multiple // columns. Columns sort alphabetically (no canonical preference for tags). func TestBuildKanbanBoardGroupByTag(t *testing.T) { items := []*store.Item{ {ID: "a", Title: "A", Status: "active", Paths: []string{"a"}, Tags: []string{"work", "dev"}}, {ID: "b", Title: "B", Status: "active", Paths: []string{"b"}, Tags: []string{"dev"}}, {ID: "c", Title: "C", Status: "active", Paths: []string{"c"}, Tags: []string{}}, } board := BuildKanbanBoard(items, GroupByTag) keys := map[string]int{} for _, col := range board.Columns { keys[col.Key] = len(col.Items) } if keys["dev"] != 2 { t.Errorf("dev column items = %d, want 2", keys["dev"]) } if keys["work"] != 1 { t.Errorf("work column items = %d, want 1", keys["work"]) } if keys["untagged"] != 1 { t.Errorf("untagged column items = %d, want 1", keys["untagged"]) } } // TestBuildKanbanBoardGroupByArea uses the first path segment as the area. func TestBuildKanbanBoardGroupByArea(t *testing.T) { items := []*store.Item{ {ID: "a", Title: "A", Status: "active", Paths: []string{"dev.a"}}, {ID: "b", Title: "B", Status: "active", Paths: []string{"work.upc.b"}}, {ID: "c", Title: "C", Status: "active", Paths: []string{"work.c"}}, } board := BuildKanbanBoard(items, GroupByArea) keys := map[string]int{} for _, col := range board.Columns { keys[col.Key] = len(col.Items) } if keys["dev"] != 1 { t.Errorf("dev column = %d, want 1", keys["dev"]) } if keys["work"] != 2 { t.Errorf("work column = %d, want 2", keys["work"]) } } // TestParseGroupByFallsBackOnUnknown verifies the parser's defaulting. func TestParseGroupByFallsBackOnUnknown(t *testing.T) { cases := map[string]string{ "": GroupByStatus, "status": GroupByStatus, "tag": GroupByTag, "area": GroupByArea, "management": GroupByManagement, "MaNaGeMeNt": GroupByManagement, "made-up": GroupByStatus, } for raw, want := range cases { q := url.Values{} if raw != "" { q.Set("group_by", raw) } if got := ParseGroupBy(q); got != want { t.Errorf("ParseGroupBy(%q) = %q, want %q", raw, got, want) } } }