Skip to content
quarry Artifact [20f3669f98]
Login

Artifact [20f3669f98]

Artifact 20f3669f983adfa738f805f0c53302a1b8a2c38577ae9022181658a6f4762d40:


package markup

import "testing"

func closing(t *testing.T, text string) []string {
	t.Helper()
	var out []string
	for _, tok := range ClosingRefs(text) {
		out = append(out, tok.Canonical())
	}
	return out
}

// The three verbs, in the spellings a landing message actually uses.
func TestAClosingPhraseNamesItsTicket(t *testing.T) {
	// A bare hash canonicalizes bracketed — [hash] is the one spelling
	// every reference to it collapses to, so a pasted URL and a typed
	// hash never look like two references.
	for _, tc := range []struct{ text, want string }{
		{"zitcli: record every store subprocess. closes cafb1f21be", "[cafb1f21be]"},
		{"fixes cafb1f21be", "[cafb1f21be]"},
		{"resolves cafb1f21be", "[cafb1f21be]"},
		{"Closes cafb1f21be", "[cafb1f21be]"},
		{"CLOSES cafb1f21be", "[cafb1f21be]"},
		{"closes: cafb1f21be", "[cafb1f21be]"},
		{"closes  cafb1f21be", "[cafb1f21be]"},
		// Trailing punctuation is the sentence's, not the token's.
		{"closes cafb1f21be.", "[cafb1f21be]"},
		{"closes cafb1f21be, and tidies up", "[cafb1f21be]"},
	} {
		got := closing(t, tc.text)
		if len(got) != 1 || got[0] != tc.want {
			t.Errorf("FAIL: %q gave %v, want [%s]", tc.text, got, tc.want)
		}
	}
}

// The verb must govern the token. Prose that contains both words but
// points the reference somewhere else is not an instruction — and an
// accident here closes somebody's ticket.
func TestProseIsNotAnInstruction(t *testing.T) {
	for _, text := range []string{
		"this closes the gap that cafb1f21be describes",
		"closes the door",
		"a landing that closes",
		"see cafb1f21be for why this closes badly",
		"the ticket cafb1f21be says it closes on merge",
	} {
		if got := closing(t, text); len(got) != 0 {
			t.Errorf("FAIL: %q closed %v", text, got)
		}
	}
}

// Every spelling of a reference works, because the grammar is the same
// one the renderer links with: a reference that acts is one a reader
// can click.
func TestEverySpellingOfAReferenceCloses(t *testing.T) {
	for _, text := range []string{
		"closes cafb1f21be",
		"closes ticket/cafb1f21be",
		"closes [cafb1f21be]",
		"closes /r/quarry/ticket/cafb1f21be",
		"closes https://zeitforge.app/r/quarry/ticket/cafb1f21be",
	} {
		if got := closing(t, text); len(got) != 1 {
			t.Errorf("FAIL: %q gave %v, want one reference", text, got)
		}
	}
}

// Several tickets in one landing, each once however often it is named.
func TestManyTicketsAndNoDuplicates(t *testing.T) {
	got := closing(t, "closes cafb1f21be, fixes 8d5aa739f8 and closes cafb1f21be again")
	if len(got) != 2 {
		t.Fatalf("FAIL: got %v, want two distinct references", got)
	}
}

// A person parses as a token and is never a thing to close. Refused
// here rather than left for the caller to notice.
func TestAPersonIsNotClosable(t *testing.T) {
	if got := closing(t, "closes @dmestas"); len(got) != 0 {
		t.Errorf("FAIL: %q closed %v", "closes @dmestas", got)
	}
}

// A bare "#412" after a closing verb is the ticket numbered 412, as on a
// pull request, trailing punctuation and all. Elsewhere it reads as a
// chat line; a chat line is never a thing to close.
func TestAHashNumberClosesThatTicket(t *testing.T) {
	for _, text := range []string{"closes #412", "Closes #412.", "fixes: #412,"} {
		got := closing(t, text)
		if len(got) != 1 || got[0] != "ticket/412" {
			t.Errorf("FAIL: %q gave %v, want ticket/412", text, got)
		}
	}
}

// ^N is a chat message (#309), and a message is never a thing to close.
func TestACaretNumberClosesNothing(t *testing.T) {
	for _, text := range []string{"closes ^412", "fixes sqlite:^412."} {
		if got := closing(t, text); len(got) != 0 {
			t.Errorf("FAIL: %q closed %v", text, got)
		}
	}
}

// Saying nothing closes nothing — the ordinary case for most landings.
func TestAnOrdinaryMessageClosesNothing(t *testing.T) {
	if got := closing(t, "csp: allow the page to state its own address"); len(got) != 0 {
		t.Errorf("FAIL: an ordinary message closed %v", got)
	}
	if got := closing(t, ""); len(got) != 0 {
		t.Errorf("FAIL: an empty message closed %v", got)
	}
}