Skip to content
quarry Artifact [161fe24c13]
Login

Artifact [161fe24c13]

Artifact 161fe24c13eea84728480c25b4460e85d1a0d4bbe777cb518700a98d485c9e25:


package web

import (
	"net/url"
	"os"
	"regexp"
	"strings"
	"testing"
)

// opsFleetFixture is a page with findings of two kinds and five stores.
func opsFleetFixture(t *testing.T, query string) string {
	t.Helper()
	var v opsView
	remarshal(map[string]any{
		"liveSubprocess": 0, "peakSubprocess": 6, "routesOver": 2, "routes": 57, "budgetMs": 500,
		"signals": map[string]any{"minutes": 4, "renders": []int{9, 18, 12, 20}, "slow": []int{0, 2, 0, 1}, "busy": []int{1, 6, 2, 1}, "errors": []int{0, 0, 0, 0}},
		"findings": []map[string]any{
			{"key": "slow:GET /r/{repo}", "about": "slow", "severity": "warn", "text": "GET /r/{repo} p95 3.74s over the 500.0ms budget", "figure": "3.74s", "note": "7.5× the budget"},
			{"key": "slow:GET /fleet", "about": "slow", "severity": "warn", "text": "GET /fleet p95 992.1ms over the 500.0ms budget", "figure": "992.1ms", "note": "2.0× the budget"},
			{"key": "store:tcl", "about": "store", "severity": "warn", "text": "tcl index behind: last successful round 1h24m ago", "figure": "1h24m", "note": "behind"},
			{"key": "store:zit", "about": "store", "severity": "warn", "text": "zit index behind: last successful round 9m ago", "figure": "9m", "note": "behind"},
			{"key": "store:fossil", "about": "store", "severity": "warn", "text": "fossil index behind: last successful round 5m ago", "figure": "5m", "note": "behind"},
		},
		"stores": []map[string]any{
			{"name": "tcl", "state": "behind", "storeBytes": 300, "indexBytes": 900, "lastSync": "2026-10-30T15:00:00Z", "roundSeconds": 0.3, "checkins": 40000},
			{"name": "Notify", "state": "current", "storeBytes": 5, "indexBytes": 27, "lastSync": "2026-10-30T16:40:00Z", "roundSeconds": 0.06, "checkins": 324},
			{"name": "althttpd", "state": "current", "storeBytes": 1, "indexBytes": 11, "lastSync": "2026-10-30T16:41:00Z", "roundSeconds": 0.06, "checkins": 323},
			{"name": "fossil", "state": "current", "storeBytes": 134, "indexBytes": 181, "lastSync": "2026-10-30T16:39:00Z", "roundSeconds": 0.18, "checkins": 21030},
			{"name": "zit", "state": "current", "storeBytes": 20, "indexBytes": 40, "lastSync": "2026-10-30T16:42:00Z", "roundSeconds": 0.07, "checkins": 900},
		},
	}, &v)
	q, _ := url.ParseQuery(query)
	v.StoreSort, v.Query = q.Get("stores"), q
	var buf strings.Builder
	if err := noHooks.template(opsPage).Execute(&buf, pageData{Title: "Operations", Ops: v}); err != nil {
		t.Fatal(err)
	}
	return buf.String()
}

func storeOrder(body string) string {
	var names []string
	for _, m := range regexp.MustCompile(`data-hook="ops-store" data-store="([^"]+)"`).FindAllStringSubmatch(body, -1) {
		names = append(names, m[1])
	}
	return strings.Join(names, ",")
}

// Every store is listed, in a scroll box, and a header sorts by its
// column: names A to Z, sizes largest first, syncs oldest first, and the
// header already sorting reverses it.
func TestTheStoresTableSortsByItsHeaders(t *testing.T) {
	for q, want := range map[string]string{
		"":                "tcl,Notify,althttpd,fossil,zit",
		"stores=name":     "althttpd,fossil,Notify,tcl,zit",
		"stores=-name":    "zit,tcl,Notify,fossil,althttpd",
		"stores=checkins": "tcl,fossil,zit,Notify,althttpd",
		"stores=sync":     "tcl,fossil,Notify,althttpd,zit",
		"stores=nonsense": "tcl,Notify,althttpd,fossil,zit",
	} {
		body := opsFleetFixture(t, q)
		if got := storeOrder(body); got != want {
			t.Errorf("FAIL: ?%s lists %s, want %s", q, got, want)
		}
	}
	body := opsFleetFixture(t, "stores=checkins&find=x")
	if !strings.Contains(body, `href="?find=x&stores=-checkins#stores" data-hook="ops-store-sort" data-key="checkins"`) {
		t.Errorf("FAIL: the sorting header does not reverse, or drops the page's other parameters")
	}
	if !strings.Contains(body, `aria-sort="descending"><a href="?find=x&amp;stores=-checkins#stores"`) {
		t.Errorf("FAIL: the sorting header does not say its direction")
	}
	if !strings.Contains(body, `class="tw ops-scroll"`) {
		t.Errorf("FAIL: the stores table is not in a scroll box")
	}
}

// Each finding sets its figure apart, and the header counts the kinds.
func TestFindingsLeadWithTheirFigure(t *testing.T) {
	body := opsFleetFixture(t, "")
	if n := strings.Count(body, `data-hook="ops-figure"`); n != 5 {
		t.Errorf("FAIL: %d figures, want 5", n)
	}
	if !strings.Contains(body, `<span class="ops-att-f ov-warn" data-hook="ops-figure">3.74s<small>7.5× the budget</small></span>`) {
		t.Errorf("FAIL: the slow route's figure is not set apart")
	}
	if !strings.Contains(body, "3 store · 2 slow · what notifies") {
		t.Errorf("FAIL: the header does not count the kinds")
	}
	if !strings.Contains(body, `class="ops-att ops-scroll"`) {
		t.Errorf("FAIL: the findings are not in a scroll box")
	}
	if out := os.Getenv("OPS_FLEET_HTML"); out != "" {
		os.WriteFile(out, []byte(`<!doctype html><meta charset=utf-8><style>`+sheet+`</style><body><main style="max-width:72rem;margin:0 auto;padding:1rem">`+body+`</main>`), 0o644)
	}
}