package autolink import ( "strings" "testing" ) // fakeResolver knows issue 4 and MR 2 in krz/gitbay, issue 7 in cmc/tools, // and users alice and krz. type fakeResolver struct{} func (fakeResolver) RefURL(owner, name string, kind byte, n int64) string { switch { case owner == "krz" && name == "gitbay" && kind == '#' && n == 4: return IssueURL(owner, name, n) case owner == "krz" && name == "gitbay" && kind == '!' && n == 2: return MRURL(owner, name, n) case owner == "cmc" && name == "tools" && kind == '#' && n == 7: return IssueURL(owner, name, n) } return "" } func (fakeResolver) UserURL(name string) string { if name == "alice" || name == "krz" { return "/" + name } return "" } func rw(t *testing.T, in string) string { t.Helper() return Rewrite(in, "krz", "gitbay", fakeResolver{}) } func TestRewrite(t *testing.T) { cases := []struct { name, in string want []string // substrings that must appear wantNot []string }{ {"bare issue ref", "

see #4 for details

", []string{`#4`}, nil}, {"bare mr ref", "

fixed in !2.

", []string{`!2`}, nil}, {"cross-repo ref", "

tracked at cmc/tools#7 upstream

", []string{`cmc/tools#7`}, nil}, {"mention", "

ping @alice about it

", []string{`@alice`}, nil}, {"org mention", "

@krz owns this

", []string{`@krz`}, nil}, {"nonexistent issue stays text", "

see #999

", []string{"

see #999

"}, []string{"hi @nobody

", []string{"

hi @nobody

"}, []string{"run git show #4 now

", []string{"git show #4"}, []string{`issues/4`}}, {"pre blocks untouched", "
#4 !2 @alice
", []string{"
#4 !2 @alice
"}, []string{"#4`, []string{`#4`}, []string{"issues/4"}}, {"mid-word hash not a ref", "

sha a1b2#4 is odd

", nil, []string{"mail me@alice.example ok

", nil, []string{"#4 and !2 and @alice

", []string{"issues/4", "mrs/2", `href="/alice"`}, nil}, {"nested markup", "
  • fixes #4
  • see !2
", []string{"issues/4", "mrs/2"}, nil}, {"punctuation after ref", "

(#4), and #4.

", []string{`class="xref">#4),`}, nil}, {"mention with trailing period", "

ask @alice.

", []string{`class="xref">@alice.`}, nil}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { got := rw(t, tc.in) for _, w := range tc.want { if !strings.Contains(got, w) { t.Errorf("missing %q in:\n%s", w, got) } } for _, w := range tc.wantNot { if strings.Contains(got, w) { t.Errorf("unexpected %q in:\n%s", w, got) } } }) } } func TestRewriteEscaping(t *testing.T) { // Text around references must stay properly escaped after the // parse/render round trip. got := rw(t, "

x <script> #4 & done

") if !strings.Contains(got, "<script>") || !strings.Contains(got, "& done") { t.Fatalf("escaping lost:\n%s", got) } if !strings.Contains(got, "issues/4") { t.Fatalf("ref not linked:\n%s", got) } }