diff --git a/internal/godoc/codec/generate_test.go b/internal/godoc/codec/generate_test.go index 37b1b3bd2..23df54813 100644 --- a/internal/godoc/codec/generate_test.go +++ b/internal/godoc/codec/generate_test.go @@ -10,12 +10,11 @@ import ( "go/ast" "go/token" "io" - "io/ioutil" - "path/filepath" "reflect" "testing" "github.com/google/go-cmp/cmp" + "golang.org/x/pkgsite/internal/testing/testhelper" ) var update = flag.Bool("update", false, "update goldens instead of checking against them") @@ -57,30 +56,7 @@ func testGenerate(t *testing.T, name string, x interface{}) { t.Fatal(err) } got := buf.String() - if *update { - writeGolden(t, name, got) - } else { - want := readGolden(t, name) - if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("%s: mismatch (-want, +got):\n%s", name, diff) - } - } -} - -func writeGolden(t *testing.T, name string, data string) { - filename := filepath.Join("testdata", name+".go") - if err := ioutil.WriteFile(filename, []byte(data), 0644); err != nil { - t.Fatal(err) - } - t.Logf("wrote %s", filename) -} - -func readGolden(t *testing.T, name string) string { - data, err := ioutil.ReadFile(filepath.Join("testdata", name+".go")) - if err != nil { - t.Fatal(err) - } - return string(data) + testhelper.CompareWithGolden(t, got, name+".go", *update) } func TestExportedFields(t *testing.T) { diff --git a/internal/godoc/dochtml/dochtml_test.go b/internal/godoc/dochtml/dochtml_test.go index 991e68a4b..c38a2f458 100644 --- a/internal/godoc/dochtml/dochtml_test.go +++ b/internal/godoc/dochtml/dochtml_test.go @@ -7,6 +7,9 @@ package dochtml import ( "bytes" "context" + "flag" + "fmt" + "go/ast" "go/parser" "go/token" @@ -22,10 +25,13 @@ import ( "golang.org/x/pkgsite/internal/godoc/dochtml/internal/render" "golang.org/x/pkgsite/internal/godoc/internal/doc" "golang.org/x/pkgsite/internal/testing/htmlcheck" + "golang.org/x/pkgsite/internal/testing/testhelper" ) var templateSource = template.TrustedSourceFromConstant("../../../content/static/html/doc") +var update = flag.Bool("update", false, "update goldens instead of checking against them") + var ( in = htmlcheck.In hasAttr = htmlcheck.HasAttr @@ -41,27 +47,28 @@ var testRenderOptions = RenderOptions{ } func TestRenderParts(t *testing.T) { + ctx := context.Background() LoadTemplates(templateSource) - fset, d := mustLoadPackage("everydecl") - ctx := context.Background() + fset, d := mustLoadPackage("everydecl") parts, err := Render(ctx, fset, d, testRenderOptions) if err != nil { t.Fatal(err) } - bodyDoc, err := html.Parse(strings.NewReader(parts.Body.String())) - if err != nil { - t.Fatal(err) - } + compareWithGolden(t, parts, "everydecl", *update) - sidenavDoc, err := html.Parse(strings.NewReader(parts.Outline.String())) + fset2, d2 := mustLoadPackage("deprecated") + parts2, err := Render(ctx, fset2, d2, testRenderOptions) if err != nil { t.Fatal(err) } - mobileDoc, err := html.Parse(strings.NewReader(parts.MobileOutline.String())) + compareWithGolden(t, parts2, "deprecated", *update) + + bodyDoc, err := html.Parse(strings.NewReader(parts.Body.String())) if err != nil { t.Fatal(err) } + // Check that there are no duplicate id attributes. t.Run("duplicate ids", func(t *testing.T) { testDuplicateIDs(t, bodyDoc) @@ -71,31 +78,6 @@ func TestRenderParts(t *testing.T) { testIDsAndKinds(t, bodyDoc) }) - checker := in(".Documentation-note", - in("h3", hasAttr("id", "pkg-note-BUG"), hasExactText("Bugs ¶")), - in("a", hasHref("#pkg-note-BUG"))) - if err := checker(bodyDoc); err != nil { - t.Errorf("note check: %v", err) - } - - checker = in(".Documentation-index", - in(".Documentation-indexNote", in("a", hasHref("#pkg-note-BUG"), hasExactText("Bugs")))) - if err := checker(bodyDoc); err != nil { - t.Errorf("note check: %v", err) - } - - checker = in(".DocNav-notes", - in("#nav-group-notes", in("li", in("a", hasHref("#pkg-note-BUG"), hasText("Bugs"))))) - if err := checker(sidenavDoc); err != nil { - t.Errorf("note check: %v", err) - } - - checker = in("", - in("optgroup[label=Notes]", in("option", hasAttr("value", "pkg-note-BUG"), hasExactText("Bugs")))) - if err := checker(mobileDoc); err != nil { - t.Errorf("note check: %v", err) - } - wantLinks := []render.Link{ {Href: "https://go.googlesource.com/pkgsite", Text: "pkgsite repo"}, {Href: "https://play-with-go.dev", Text: "Play with Go"}, @@ -105,6 +87,11 @@ func TestRenderParts(t *testing.T) { } } +func compareWithGolden(t *testing.T, parts *Parts, name string, update bool) { + got := fmt.Sprintf("%s\n----\n%s\n----\n%s\n", parts.Body, parts.Outline, parts.MobileOutline) + testhelper.CompareWithGolden(t, got, name+".golden", update) +} + func TestExampleRender(t *testing.T) { LoadTemplates(templateSource) ctx := context.Background() @@ -353,33 +340,6 @@ func TestVersionedPkgPath(t *testing.T) { } } -func TestDeprecated(t *testing.T) { - LoadTemplates(templateSource) - ctx := context.Background() - fset, d := mustLoadPackage("deprecated") - parts, err := Render(ctx, fset, d, testRenderOptions) - if err != nil { - t.Fatal(err) - } - // In package deprecated, all non-deprecated symbols begin with "Good" and - // all deprecated ones begin with "Bad". - // There is one const, var, func and type of each. - - // The outline only has functions and types, so we should see two "Good"s and no "Bad"s. - outlineString := parts.Outline.String() - for _, want := range []string{"GoodF()", "type GoodT", "GoodM", "NewGoodTGood()"} { - if !strings.Contains(outlineString, want) { - t.Errorf("outline does not have %q but should", want) - } - } - for _, notWant := range []string{"BadF()", "type BadT", "BadM()", "NewGoodTBad()"} { - if strings.Contains(outlineString, notWant) { - t.Errorf("outline has %q but shouldn't", notWant) - } - } - -} - func testDuplicateIDs(t *testing.T, htmlDoc *html.Node) { idCounts := map[string]int{} walk(htmlDoc, func(n *html.Node) { diff --git a/internal/godoc/dochtml/testdata/deprecated.golden b/internal/godoc/dochtml/testdata/deprecated.golden new file mode 100644 index 000000000..7c2ff778b --- /dev/null +++ b/internal/godoc/dochtml/testdata/deprecated.golden @@ -0,0 +1,330 @@ + +
Package deprecated has some deprecated symbols. +
+const BadC = 2
+ BadC is bad. +Deprecated: use GoodC. +
+ +const GoodC = 1
+ var BadV = 2 // Deprecated: use GoodV.
+
+ var GoodV = 1
+ type BadT int+
BadT is bad. +Deprecated: use GoodT. +Don't use this. +
+type GoodT int+
func NewGoodTBad() GoodT+
NewGoodTBad is bad. +Deprecated: use NewGoodTGood. +
+func NewGoodTGood() GoodT+
Package everydecl has every form of declaration known to dochtml. +It is designed to test that the generated HTML has the right id and data-kind +attributes. +
+const C = 1
+ const +
+var V = 2
+ var +
+type I2 interface { + I1 // embedded interface; should not have an id + M2() +}+
this verifies that notes are rendered +