Skip to content
quarry Artifact [46db2577cd]
Login

Artifact [46db2577cd]

Artifact 46db2577cd5606e3199ad5f56235b4b7c1275c2de8456db6cfa4f47a8da5a4c5:


package web

import (
	"strings"
	"testing"
)

// RFC 0028: requests live on a page of their own. Waiting ones answer
// with two POSTed buttons that return to the list (never a link, so
// nothing runs from a GET); decided ones fold into History, filterable
// by agent; and /me no longer draws them.
func TestRequestsHaveAPageOfTheirOwn(t *testing.T) {
	render := func(v requestsView) string {
		var b strings.Builder
		if err := noHooks.template(requestsPageTmpl).ExecuteTemplate(&b, "content", pageData{Title: "Requests", Requests: &v}); err != nil {
			t.Fatal(err)
		}
		return b.String()
	}
	waiting := render(requestsView{Tab: "waiting",
		Waiting: []meSignOff{{ID: "abc", Agent: "zeitgeist", Summary: "agent.new for rajeev", Reason: "a QA tester", State: "pending", Requested: "2026-11-08T10:00:00Z"}}})
	for what, want := range map[string]string{
		"approve posts back to the list": `<form method="post" action="/me/signoffs/abc"><input type="hidden" name="approve" value="true"><input type="hidden" name="back" value="list">`,
		"deny posts back to the list":    `<form method="post" action="/me/signoffs/abc"><input type="hidden" name="approve" value="false"><input type="hidden" name="back" value="list">`,
		"each row opens its request":     `href="/me/requests/abc"`,
		"the waiting tab is current":     `data-hook="requests-tab-waiting">`,
	} {
		if !strings.Contains(waiting, want) {
			t.Errorf("FAIL: %s (%q)", what, want)
		}
	}
	history := render(requestsView{Tab: "history", Agent: "zeitgeist", Agents: []string{"zeitgeist", "jva-bot"},
		History: []meSignOff{{ID: "def", Agent: "zeitgeist", Summary: "x", State: "denied", Requested: "2026-11-07T10:00:00Z"}}})
	if !strings.Contains(history, `data-hook="request" data-state="denied"`) || strings.Contains(history, `action="/me/signoffs/def"`) {
		t.Error("FAIL: a decided request is not in History, or can still be answered")
	}
	if !strings.Contains(history, `agent=jva-bot`) {
		t.Error("FAIL: History cannot be narrowed to one agent")
	}
	if empty := render(requestsView{Tab: "waiting"}); !strings.Contains(empty, `data-hook="requests-none"`) {
		t.Error("FAIL: an empty Waiting tab says nothing")
	}
	var me strings.Builder
	if err := noHooks.template(mePageTmpl).ExecuteTemplate(&me, "content", pageData{Title: "ann", User: "ann", Me: &meView{Name: "ann", Notify: &prefsView{}}}); err != nil {
		t.Fatal(err)
	}
	if strings.Contains(me.String(), `id="signoffs"`) {
		t.Error("FAIL: /me still draws a sign-off section")
	}
	if h := requestsBadgeHTML(3); !strings.Contains(h, `id="requests-btn"`) || !strings.Contains(h, `data-count="3"`) || !strings.Contains(h, `href="/me/requests"`) {
		t.Errorf("FAIL: the bar's badge: %s", h)
	}
}

// RFC 0027: the page an email links to shows one request, who asks and
// why, and answers it with two posted buttons that return to it; a
// decided request has no buttons left.
func TestASignOffHasAPageOfItsOwn(t *testing.T) {
	render := func(s meSignOff) string {
		var b strings.Builder
		if err := noHooks.template(signOffPageTmpl).ExecuteTemplate(&b, "content", pageData{Title: "Approve?", SignOff: &s}); err != nil {
			t.Fatal(err)
		}
		return b.String()
	}
	got := render(meSignOff{ID: "abc", Agent: "zeitgeist", Summary: "agent.new for rajeev", Reason: "a QA tester", State: "pending", Requested: "2026-11-08T10:00:00Z"})
	for what, want := range map[string]string{
		"who asks":          `data-hook="signoff-agent">zeitgeist<`,
		"what runs":         `data-hook="signoff-summary">agent.new for rajeev<`,
		"why":               `data-hook="signoff-reason"`,
		"approve posts":     `<form method="post" action="/me/signoffs/abc"><input type="hidden" name="approve" value="true"><input type="hidden" name="back" value="page">`,
		"deny posts":        `<form method="post" action="/me/signoffs/abc"><input type="hidden" name="approve" value="false"><input type="hidden" name="back" value="page">`,
		"its state is read": `data-hook="signoff-page" data-state="pending"`,
	} {
		if !strings.Contains(got, want) {
			t.Errorf("FAIL: %s (%q)", what, want)
		}
	}
	if done := render(meSignOff{ID: "abc", Agent: "zeitgeist", Summary: "x", State: "approved", Requested: "2026-11-08T10:00:00Z"}); strings.Contains(done, "<form") {
		t.Errorf("FAIL: an approved request can still be answered")
	}
}

// A call an agent ran on its own right is a row of its own kind: the
// page says so with a hook of its own, never reads as an approval, has
// no buttons, and the history chip says it too.
func TestAParkedCallIsNotShownAsAnApproval(t *testing.T) {
	var b strings.Builder
	s := meSignOff{ID: "abc", Agent: "jva-bot", Summary: "x", State: "ran", Requested: "2026-11-08T10:00:00Z",
		Pickup: strings.Repeat("ab", 32)}
	if err := noHooks.template(signOffPageTmpl).ExecuteTemplate(&b, "content", pageData{Title: "Ran", SignOff: &s}); err != nil {
		t.Fatal(err)
	}
	got := b.String()
	for what, want := range map[string]string{
		"the parked hook": `data-hook="signoff-parked"`,
		"its state":       `data-state="ran"`,
		"the pickup line": `data-hook="signoff-pickup"`,
		"not collected":   `data-hook="signoff-uncollected"`,
	} {
		if !strings.Contains(got, want) {
			t.Errorf("FAIL: %s (%q)", what, want)
		}
	}
	if strings.Contains(got, "<form") || strings.Contains(got, "approved") {
		t.Error("FAIL: a parked row reads as an approval or can be answered")
	}
	s.Collected = "2026-11-08T11:00:00Z"
	b.Reset()
	if err := noHooks.template(signOffPageTmpl).ExecuteTemplate(&b, "content", pageData{Title: "Ran", SignOff: &s}); err != nil || !strings.Contains(b.String(), `data-hook="signoff-collected"`) {
		t.Errorf("FAIL: a collected row says so: %v", err)
	}
	var h strings.Builder
	v := requestsView{Tab: "history", History: []meSignOff{s}}
	if err := noHooks.template(requestsPageTmpl).ExecuteTemplate(&h, "content", pageData{Title: "Requests", Requests: &v}); err != nil || !strings.Contains(h.String(), `data-state="ran"`) || strings.Contains(h.String(), ">denied<") {
		t.Errorf("FAIL: the history row: %v", err)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}