quarry  Artifact [6f8c17b8fe]

Artifact 6f8c17b8fee4ef4f6d0bd113bbfc88b9a2305b946ae09dc48743482a3d9e8fb4:


package markup

import (
	"strings"
	"testing"
)

// ticketResolver knows two tickets, one of them local, and one check-in.
type ticketResolver struct{ fakeResolver }

func (ticketResolver) ResolveHash(p string) string {
	if strings.HasPrefix("c0ffee0000c0ffee", p) {
		return "/r/q/checkin/c0ffee0000c0ffee"
	}
	return ""
}

func (ticketResolver) DescribeTicket(t RefToken) (TicketRef, bool) {
	switch {
	case strings.HasPrefix("54dc6a414800aa", t.ID):
		return TicketRef{URL: "/r/q/ticket/54dc6a414800aa", Number: 231, State: "closed", Status: "Fixed", Local: true}, true
	case strings.HasPrefix("508fd44ab000bb", t.ID):
		return TicketRef{URL: "/r/q/ticket/508fd44ab000bb", Number: 232, State: "open", Status: "Open"}, true
	}
	return TicketRef{}, false
}

func renderT(t *testing.T, src string) string {
	t.Helper()
	out, err := Render([]byte(src), ticketResolver{})
	if err != nil {
		t.Fatal(err)
	}
	return string(out)
}

// A ticket named in prose reads as its number with its state beside it,
// whether the author typed the bare id or linked the ticket's page.
func TestATicketReferenceShowsItsNumberAndState(t *testing.T) {
	for _, src := range []string{
		"see 54dc6a4148 for the crash",
		"see [54dc6a4148](/r/dmestas/q/ticket/54dc6a4148) for the crash",
		"see [54dc6a4148](https://zeitforge.app/r/q/ticket/54dc6a4148) for the crash",
	} {
		html := renderT(t, src)
		if !strings.Contains(html, `/ticket/54dc6a414800aa"`) && !strings.Contains(html, `/ticket/54dc6a4148"`) {
			t.Errorf("FAIL: %q: no link to the ticket: %s", src, html)
		}
		if !strings.Contains(html, `class="tref`) || !strings.Contains(html, ">#231</a>") {
			t.Errorf("FAIL: %q: the reference does not read as #231: %s", src, html)
		}
		if !strings.Contains(html, `class="tref-state tref-closed"`) {
			t.Errorf("FAIL: %q: no closed state beside it: %s", src, html)
		}
		if !strings.Contains(html, `class="tref-local"`) {
			t.Errorf("FAIL: %q: a local ticket is not marked local: %s", src, html)
		}
	}
	if !t.Failed() {
		t.Log("ok: bare ids and links both read #231 with state and local mark")
	}
}

// An author's own link text is theirs; only a bare id is relabelled.
func TestALinkWithItsOwnWordsKeepsThem(t *testing.T) {
	html := renderT(t, "[the goroutine leak](/r/q/ticket/508fd44ab0)")
	if !strings.Contains(html, ">the goroutine leak</a>") || !strings.Contains(html, `tref-open`) {
		t.Errorf("FAIL: the author's words or the state are lost: %s", html)
	}
	if strings.Contains(html, "tref-local") {
		t.Errorf("FAIL: an ordinary ticket is marked local: %s", html)
	}
}

// A hash that names a check-in is not described as a ticket.
func TestACheckinHashIsNotATicket(t *testing.T) {
	html := renderT(t, "landed in c0ffee0000")
	if strings.Contains(html, "tref") || !strings.Contains(html, "/checkin/") {
		t.Errorf("FAIL: a check-in reference changed: %s", html)
	}
}

// A caller building its own markup gets the same anchor and pills.
func TestTicketRefHTMLMatchesTheRenderer(t *testing.T) {
	got := TicketRefHTML("54dc6a4148", TicketRef{URL: "/r/q/ticket/54dc", Number: 231, State: "closed", Status: "Fixed", Local: true})
	for _, want := range []string{`href="/r/q/ticket/54dc"`, `class="tref"`, ">#231</a>", `tref-state tref-closed`, `tref-local`} {
		if !strings.Contains(got, want) {
			t.Errorf("FAIL: missing %s in %s", want, got)
		}
	}
}