package web
import (
"strings"
"testing"
)
func recordBody(t *testing.T, state, title string) string {
t.Helper()
var buf strings.Builder
if err := noHooks.template(landingPage).ExecuteTemplate(&buf, "landing-body", pageData{
Repo: "quarry",
Landing: &landingDetail{landingRow: landingRow{
ID: "aa11bb22cc33", Branch: "b", Target: "trunk", State: state, Title: title,
}},
}); err != nil {
t.Fatal(err)
}
return buf.String()
}
// Most work is the addressing case: a landing that moves a ticket
// forward without ending it. It had no way to say so, so it either
// said nothing — and the ticket showed no sign the work existed — or
// said "closes" and the ticket was wrongly shut.
func TestTheRecordLinksWhatItAddresses(t *testing.T) {
got := recordBody(t, "open", "ops: the lanes panel lists what it holds. addresses a488d7fa42")
if !strings.Contains(got, `href="/r/quarry/ticket/a488d7fa42"`) {
t.Error("FAIL: the record does not link the ticket it addresses")
}
if !strings.Contains(got, "addresses") {
t.Error("FAIL: the record does not say it addresses anything")
}
}
// An addresses makes no promise about a ticket's state, in either
// state of the record. Accepting it changed nothing about the ticket,
// so nothing here may read as a close.
func TestAnAddressesNeverReadsAsAClose(t *testing.T) {
for _, state := range []string{"open", "accepted"} {
got := recordBody(t, state, "addresses a488d7fa42")
if strings.Contains(got, "l-closes-chip") {
t.Errorf("FAIL: %s record drew a closing chip for an addresses", state)
}
// The closing line is the one that says "closes"/"closed"; the
// addressing line shares its class but never its verb.
for _, no := range []string{">closes\n", ">closed\n", " closed\n"} {
if strings.Contains(got, no) {
t.Errorf("FAIL: %s record says %q for an addresses", state, strings.TrimSpace(no))
}
}
}
}
// Both at once is the ordinary shape of a landing that finishes one
// ticket while working on another, and the reader must see both.
func TestARecordCanCloseOneAndAddressAnother(t *testing.T) {
got := recordBody(t, "open", "closes 0eafaa1984 and addresses a488d7fa42")
for _, want := range []string{`href="/r/quarry/ticket/0eafaa1984"`, `href="/r/quarry/ticket/a488d7fa42"`} {
if !strings.Contains(got, want) {
t.Errorf("FAIL: the record is missing %s", want)
}
}
}
// A landing that says nothing shows nothing — the line exists only
// when the record made the declaration.
func TestAnOrdinaryRecordShowsNoAddressingLine(t *testing.T) {
if got := recordBody(t, "open", "csp: allow the page to state its own address"); strings.Contains(got, "l-addresses") {
t.Error("FAIL: a record that declared nothing drew an addressing line")
}
}
// The list view carries both chips, because a reader scanning landings
// is looking for the one that touched their ticket and cannot open
// every record to find it.
func TestTheListRowChipsBothVerbs(t *testing.T) {
ids := addressingIDs("ops: lanes. addresses a488d7fa42")
if len(ids) != 1 || ids[0] != "a488d7fa42" {
t.Fatalf("FAIL: addressingIDs = %q", ids)
}
// A full-length hash is trimmed to what a person reads it by.
long := addressingIDs("addresses a488d7fa4200112233445566778899aabbccddeeff00112233445566")
if len(long) != 1 || long[0] != "a488d7fa4200" {
t.Fatalf("FAIL: a long hash chipped as %q", long)
}
}