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{"rungit 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", "(#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) } } func TestMentions(t *testing.T) { got := Mentions("cc @alice and (@bob) — @alice again; mail@example.org is not one, @carol.") want := []string{"alice", "bob", "carol."} if len(got) != len(want) { t.Fatalf("Mentions = %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("Mentions = %v, want %v", got, want) } } }