repositories / bugabinga.net
bugabinga.net
personal infrastructure for bugabinga!
owned by admin
services/luci/internal/web/view_test.go
Rawpackage web
import (
"fmt"
"testing"
"time"
"bugabinga.net/luci/internal/history"
"bugabinga.net/luci/internal/inbox"
"bugabinga.net/luci/internal/proquint"
"bugabinga.net/luci/internal/runstate"
"bugabinga.net/luci/internal/trigger"
)
func TestBuildDashboardProjectsLatestRepositoryHealth(t *testing.T) {
now := time.Date(2026, 8, 5, 12, 0, 0, 0, time.UTC)
events := []history.Event{
{RunID: "1", ChildID: "run", Repo: "fixed", Job: "push", Status: "failed", Time: now.Add(-3 * time.Minute)},
{RunID: "2", ChildID: "run", Repo: "fixed", Job: "push", Status: "success", Rev: "1234567890", Time: now.Add(-time.Minute), StartedAt: now.Add(-time.Minute - time.Second)},
{RunID: "3", ChildID: "run", Repo: "broken", Job: "push", Status: "failed", Time: now.Add(-2 * time.Minute)},
{RunID: "3", ChildID: "001", Repo: "broken", Job: "smoke", Status: "failed", Time: now.Add(-2 * time.Minute)},
}
queuedID := fmt.Sprintf("%d", now.Add(-10*time.Second).UnixNano())
pending := []inbox.Pending{{ID: queuedID, Phase: "queued", Event: trigger.PushEvent{Kind: "push", Repo: "queued", New: "abcdef123", Ref: "refs/heads/trunk"}}}
view := buildDashboard(now, events, pending, nil, false)
if view.FailingRepos != 1 || view.RunningRepos != 1 || view.HealthyRepos != 1 {
t.Fatalf("counts=%#v", view)
}
if len(view.Attention) != 1 || view.Attention[0].Repo != "broken" {
t.Fatalf("attention=%#v", view.Attention)
}
if len(view.Progress) != 1 || view.Progress[0].Repo != "queued" || view.Progress[0].Timing != "10s" {
t.Fatalf("progress=%#v", view.Progress)
}
if len(view.Success) != 1 || view.Success[0].Rev != "1234" || view.Success[0].Timing != "1s" {
t.Fatalf("success=%#v", view.Success)
}
}
func TestBuildDashboardCountsFailingActiveRepoOnce(t *testing.T) {
now := time.Now().UTC()
events := []history.Event{{RunID: "1", ChildID: "run", Repo: "repo", Job: "push", Status: "failed", Time: now.Add(-time.Minute)}}
active := []runstate.Active{{RunID: "2", ChildID: "001", Repo: "repo", Job: "smoke", StartedAt: now.Add(-5 * time.Second)}}
view := buildDashboard(now, events, nil, active, false)
if view.FailingRepos != 1 || view.RunningRepos != 0 || len(view.Progress) != 1 {
t.Fatalf("view=%#v", view)
}
}
func TestBuildDashboardLimitsAndAll(t *testing.T) {
now := time.Now().UTC()
var events []history.Event
for i := range 55 {
events = append(events, history.Event{RunID: fmt.Sprint(i), ChildID: "run", Repo: fmt.Sprintf("repo-%02d", i), Job: "push", Status: "success", Time: now.Add(-time.Duration(i) * time.Second)})
}
if got := len(buildDashboard(now, events, nil, nil, false).Success); got != 50 {
t.Fatalf("limited=%d", got)
}
if got := len(buildDashboard(now, events, nil, nil, true).Success); got != 55 {
t.Fatalf("all=%d", got)
}
}
func TestBuildRunResolvesPendingActiveAndTerminal(t *testing.T) {
now := time.Now().UTC()
id := fmt.Sprint(now.UnixNano())
pending := []inbox.Pending{{ID: id, Phase: "preparing", Event: trigger.ManualEvent{Kind: "manual", Repo: "repo", Job: "check", Rev: ptr("abc")}}}
got := buildRun(id, now, nil, pending, nil)
if !got.Known || got.Parent.Status != "preparing" || got.Parent.Repo != "repo" {
t.Fatalf("pending=%#v", got)
}
active := []runstate.Active{{RunID: id, ChildID: "001", Repo: "repo", Job: "check", Rev: "abcdef123", StartedAt: now.Add(-time.Second)}}
got = buildRun(id, now, nil, pending, active)
if got.Parent.Status != "running" || len(got.Children) != 1 {
t.Fatalf("active=%#v", got)
}
events := []history.Event{{RunID: id, ChildID: "run", Repo: "repo", Job: "check", Status: "success", Time: now}, {RunID: id, ChildID: "001", Repo: "repo", Job: "check", Status: "success", Time: now}}
got = buildRun(id, now, events, nil, nil)
if got.Parent.Status != "success" || len(got.Children) != 1 {
t.Fatalf("terminal=%#v", got)
}
}
func TestFormattersUseCompactValuesAndPlaceholders(t *testing.T) {
if shortRev("") != "—" || shortRev("abc") != "abc" || shortRev("123456789") != "1234567" {
t.Fatal("short rev")
}
for duration, want := range map[time.Duration]string{18 * time.Second: "18s", 4 * time.Minute: "4m", 2 * time.Hour: "2h", 72 * time.Hour: "3d"} {
if got := compactDuration(duration); got != want {
t.Fatalf("%v=%s want %s", duration, got, want)
}
}
}
func ptr(value string) *string { return &value }
func TestShortenerShrinksToUniquePrefixes(t *testing.T) {
events := []history.Event{
{RunID: "1", ChildID: "run", Repo: "a", Job: "push", Status: "success", Rev: "aa100000", Time: time.Now()},
{RunID: "2", ChildID: "run", Repo: "b", Job: "push", Status: "success", Rev: "aa200000", Time: time.Now()},
}
short := buildShortener(events, nil, nil)
view := runView{RunID: "1", Rev: "aa100000", FullRev: "aa100000", Pronounce: proquint.Encode(1)}
short.apply(&view)
if view.Rev != "aa10" || view.FullHead != "aa10" || view.FullTail != "0000" {
t.Fatalf("rev shortening: %#v", view)
}
}
func TestRunningPushPreservesParentIdentity(t *testing.T) {
now := time.Now().UTC()
id := fmt.Sprint(now.Add(-time.Second).UnixNano())
pending := []inbox.Pending{{ID: id, Phase: "preparing", Event: trigger.PushEvent{Kind: "push", Repo: "repo", New: "requested", Ref: "refs/heads/trunk"}}}
active := []runstate.Active{{RunID: id, ChildID: "001", Repo: "repo", Job: "smoke", Rev: "abcdef123", Ref: "refs/heads/trunk", Trigger: "push", StartedAt: now.Add(-time.Second)}}
dashboard := buildDashboard(now, nil, pending, active, false)
if len(dashboard.Progress) != 1 || dashboard.Progress[0].Job != "push" || dashboard.Progress[0].Status != "running" || dashboard.Progress[0].Rev != "abcd" {
t.Fatalf("progress=%#v", dashboard.Progress)
}
detail := buildRun(id, now, nil, pending, active)
if detail.Parent.Job != "push" || detail.Parent.Status != "running" || detail.Parent.Rev != "abcd" || len(detail.Children) != 1 {
t.Fatalf("detail=%#v", detail)
}
}
func TestBuildRunPreservesLegacyChildren(t *testing.T) {
now := time.Now().UTC()
events := []history.Event{
{RunID: "old", Repo: "repo", Job: "check", Status: "failed", Detail: "boom", Time: now.Add(-time.Minute)},
{RunID: "old", Repo: "repo", Job: "test", Status: "success", Time: now},
}
got := buildRun("old", now, events, nil, nil)
if !got.Known || got.Parent.Job != "test" || len(got.Children) != 2 || got.Children[0].ChildID != "legacy-001" || got.Children[0].Detail != "boom" {
t.Fatalf("legacy=%#v", got)
}
}
func TestDashboardUsesRunIDAsOrderingTieBreaker(t *testing.T) {
now := time.Now().UTC()
events := []history.Event{{RunID: "a", ChildID: "run", Repo: "a", Status: "success", Time: now}, {RunID: "b", ChildID: "run", Repo: "b", Status: "success", Time: now}}
view := buildDashboard(now, events, nil, nil, false)
if view.Success[0].RunID != "b" {
t.Fatalf("success order=%#v", view.Success)
}
pending := []inbox.Pending{{ID: "a", Phase: "queued", Event: trigger.PushEvent{Kind: "push", Repo: "a", New: "x", Ref: "r"}}, {ID: "b", Phase: "queued", Event: trigger.PushEvent{Kind: "push", Repo: "b", New: "x", Ref: "r"}}}
view = buildDashboard(now, nil, pending, nil, false)
if view.Progress[0].RunID != "b" {
t.Fatalf("progress order=%#v", view.Progress)
}
}