Files
ReleaseKit/internal/validation/markdown_test.go

125 lines
4.2 KiB
Go

package validation
import (
"context"
"strings"
"testing"
)
func TestParseMarkdownLinksAndSourceLocations(t *testing.T) {
source := []byte("" +
"é [inline](docs/a\\(b\\).md \"inline title\").\n" +
"![chart](<images/chart one.svg> 'image title')\n" +
"[ref][target] then [ref][target].\n" +
"[collapsed][] and [shortcut].\n" +
"![logo][badge]\n" +
"\n" +
"[target]: docs/target.md \"reference title\"\n" +
"[collapsed]: child.md\n" +
"[shortcut]: short.md\n" +
"[badge]: badge.png\n" +
"Inline example: `[fake](fake.md)`.\n" +
"```md\n[also fake](fenced.md)\n```\n" +
"[undefined]\n" +
"Autolink <https://example.invalid>.\n" +
"<a href=\"raw.html\">HTML</a>\n")
document := parseMarkdown(source)
want := []markdownLink{
{Destination: "docs/a(b).md", Title: "inline title", Location: markdownLocation{Line: 1, Column: 4}},
{Destination: "images/chart one.svg", Title: "image title", Image: true, Location: markdownLocation{Line: 2, Column: 1}},
{Destination: "docs/target.md", Title: "reference title", Reference: true, Location: markdownLocation{Line: 3, Column: 1}},
{Destination: "docs/target.md", Title: "reference title", Reference: true, Location: markdownLocation{Line: 3, Column: 20}},
{Destination: "child.md", Reference: true, Location: markdownLocation{Line: 4, Column: 1}},
{Destination: "short.md", Reference: true, Location: markdownLocation{Line: 4, Column: 19}},
{Destination: "badge.png", Image: true, Reference: true, Location: markdownLocation{Line: 5, Column: 1}},
{Destination: "https://example.invalid", Location: markdownLocation{Line: 16, Column: 10}},
}
if len(document.links) != len(want) {
t.Fatalf("found %d links, want %d: %#v", len(document.links), len(want), document.links)
}
for index := range want {
if got := document.links[index]; got != want[index] {
t.Errorf("link %d = %#v, want %#v", index, got, want[index])
}
}
}
func TestParseMarkdownDecodesEntitiesInDestinations(t *testing.T) {
document := parseMarkdown([]byte("[entity](<a&amp;b.md>)\n"))
if len(document.links) != 1 || document.links[0].Destination != "a&b.md" {
t.Fatalf("parsed links = %#v, want decoded destination a&b.md", document.links)
}
}
func TestParseMarkdownHeadingAnchors(t *testing.T) {
source := []byte("" +
"# Caf&eacute; &amp; 東京 `Code Here` <em>Bold</em>!\n" +
"Setext **Heading**\n" +
"---\n" +
"# Foo\n" +
"# Foo\n" +
"# Foo-1\n" +
"# Foo\n" +
"# Foo-1\n" +
"# <https://example.invalid>\n" +
"# <maintainer@example.invalid>\n" +
"# Contact <maintainer@example.invalid> Today\n")
document := parseMarkdown(source)
for _, anchor := range []string{
"café--東京-code-here-bold",
"setext-heading",
"foo",
"foo-1",
"foo-1-1",
"foo-2",
"foo-1-2",
"httpsexampleinvalid",
"maintainerexampleinvalid",
"contact-maintainerexampleinvalid-today",
} {
if _, ok := document.anchors[anchor]; !ok {
t.Errorf("missing anchor %q in %#v", anchor, document.anchors)
}
}
if len(document.anchors) != 10 {
t.Fatalf("found %d anchors, want 10: %#v", len(document.anchors), document.anchors)
}
}
func TestMarkdownCacheKeepsParsedDocumentsPerCandidatePath(t *testing.T) {
repository := newTreeRepository(t)
writeTreeFile(t, repository, "guide.md", []byte("# Guide\n[other](other.md)\n"))
writeTreeFile(t, repository, "other.md", []byte("# Other\n"))
gitTree(t, repository, "add", "guide.md", "other.md")
gitTree(t, repository, "commit", "-m", "add markdown files")
commit := strings.TrimSpace(gitTree(t, repository, "rev-parse", "HEAD"))
tree, err := ReadCandidateTree(context.Background(), repository, commit)
if err != nil {
t.Fatal(err)
}
cache := newMarkdownCache(tree)
first, err := cache.document(context.Background(), "guide.md")
if err != nil {
t.Fatal(err)
}
second, err := cache.document(context.Background(), "guide.md")
if err != nil {
t.Fatal(err)
}
if first != second {
t.Fatal("repeated document lookup returned a different parsed document")
}
other, err := cache.document(context.Background(), "other.md")
if err != nil {
t.Fatal(err)
}
if other == first {
t.Fatal("different candidate paths shared a parsed document")
}
if _, ok := other.anchors["other"]; !ok {
t.Fatalf("other document anchors = %#v", other.anchors)
}
}