internal/pagecheck: add checks for overview pages

Change-Id: I643e59f9eb13f9b9abbf8c30daedb2264a3a65e3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/discovery/+/602822
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Jonathan Amsterdam 2019-11-20 13:32:39 -05:00 коммит произвёл Julie Qiu
Родитель cfef41cecc
Коммит c77f28bf03
4 изменённых файлов: 101 добавлений и 49 удалений

Просмотреть файл

@ -17,7 +17,7 @@ import (
"golang.org/x/discovery/internal"
"golang.org/x/discovery/internal/middleware"
"golang.org/x/discovery/internal/postgres"
"golang.org/x/discovery/internal/stdlib"
"golang.org/x/discovery/internal/source"
"golang.org/x/discovery/internal/testing/htmlcheck"
"golang.org/x/discovery/internal/testing/pagecheck"
"golang.org/x/discovery/internal/testing/sample"
@ -47,6 +47,18 @@ func TestHTMLInjection(t *testing.T) {
}
}
// TestServer checks the contents of served pages by looking for
// strings and elements in the parsed HTML response body.
//
// Other than search and static content, our pages vary along five dimensions:
//
// 1. module / package / directory
// 2. stdlib / other (since the standard library is a special case in several ways)
// 3. redistributable / non-redistributable
// 4. versioned / unversioned URL (whether the URL for the page contains "@version")
// 5. the tab (overview / doc / imports / ...)
//
// We aim to test all combinations of these.
func TestServer(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
@ -58,6 +70,7 @@ func TestServer(t *testing.T) {
v.ModulePath = modulePath
v.Version = version
v.Packages = pkgs
v.SourceInfo = source.NewGitHubInfo(sample.RepositoryURL, "", version)
if err := testDB.InsertVersion(ctx, v); err != nil {
t.Fatal(err)
}
@ -88,7 +101,7 @@ func TestServer(t *testing.T) {
pkgCmdGo := sample.Package()
pkgCmdGo.Name = "main"
pkgCmdGo.Path = "cmd/go"
mustInsertVersion(stdlib.ModulePath, "v1.13.0", []*internal.Package{pkgCmdGo})
mustInsertVersion("std", "v1.13.0", []*internal.Package{pkgCmdGo})
s, err := NewServer(testDB, nil, "../../content/static", false)
if err != nil {
@ -338,11 +351,14 @@ func TestServer(t *testing.T) {
wantStatusCode: http.StatusOK,
want: in("",
pagecheck.PackageHeader(pkgV100, versioned),
in(".Overview-sourceCodeLink a",
href("github.com/valid_module_name"),
text("github.com/valid_module_name")),
in(".Overview-readmeContent", text("readme")),
in(".Overview-readmeSource", text("Source: github.com/valid_module_name@v1.0.0/README.md"))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: "/mod/github.com/valid_module_name@v1.0.0",
ModuleLinkText: pkgV100.ModulePath,
RepoURL: "https://github.com/valid_module_name",
PackageURL: "https://github.com/valid_module_name/tree/v1.0.0/foo",
ReadmeContent: "readme",
ReadmeSource: "github.com/valid_module_name@v1.0.0/README.md",
})),
},
{
name: "package@version readme tab nonredistributable",
@ -436,19 +452,13 @@ func TestServer(t *testing.T) {
wantStatusCode: http.StatusOK,
want: in("",
pagecheck.DirectoryHeader(dir, unversioned),
in(".Overview-module",
text("Module"),
in("a",
href("/mod/github.com/valid_module_name"),
text("github.com/valid_module_name"))),
in(".Overview-sourceCodeLink",
text("Repository"),
in("a",
href("github.com/valid_module_name"),
attr("target", "_blank"),
text("github.com/valid_module_name"))),
in(".Overview-readmeContent", text("readme")),
in(".Overview-readmeSource", text("Source: github.com/valid_module_name@v1.0.0/README.md"))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: "/mod/github.com/valid_module_name",
ModuleLinkText: dir.ModulePath,
RepoURL: "https://github.com/valid_module_name",
ReadmeContent: "readme",
ReadmeSource: "github.com/valid_module_name@v1.0.0/README.md",
})),
},
{
name: "directory licenses",
@ -481,21 +491,13 @@ func TestServer(t *testing.T) {
wantStatusCode: http.StatusOK,
want: in("",
pagecheck.DirectoryHeader(dirCmd, versioned),
in(".Overview-module",
text("Standard Library"),
in("a",
href("/std@go1.13"),
text("Standard Library"))),
in(".Overview-sourceCodeLink",
text("Repository"),
in("a",
href("github.com/valid_module_name"),
attr("target", "_blank"),
text("github.com/valid_module_name"))),
in(".Overview-readmeContent", text("readme")),
in(".Overview-readmeSource",
text(`^Source: go.googlesource.com/go/\+/refs/tags/go1.13/README.md$`))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: "/std@go1.13",
ModuleLinkText: "Standard Library",
ReadmeContent: "readme",
RepoURL: "https://github.com/valid_module_name", // wrong, but hard to change
ReadmeSource: "go.googlesource.com/go/+/refs/tags/go1.13/README.md",
})),
},
{
name: "stdlib directory licenses",
@ -513,7 +515,13 @@ func TestServer(t *testing.T) {
// Fall back to the latest version, show readme tab by default.
want: in("",
pagecheck.ModuleHeader(mod, unversioned),
in(".Overview-readmeContent", text(`readme`))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: "/mod/" + sample.ModulePath,
ModuleLinkText: sample.ModulePath,
ReadmeContent: "readme",
RepoURL: "https://github.com/valid_module_name",
ReadmeSource: "github.com/valid_module_name@v1.0.0/README.md",
})),
},
{
name: "module overview",
@ -523,10 +531,13 @@ func TestServer(t *testing.T) {
// Fall back to the latest version, show readme tab by default.
want: in("",
pagecheck.ModuleHeader(mod, unversioned),
in(".Overview-module a",
href("/mod/"+sample.ModulePath),
text("^"+sample.ModulePath+"$")),
in(".Overview-readmeContent", text(`readme`))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: "/mod/" + sample.ModulePath,
ModuleLinkText: sample.ModulePath,
ReadmeContent: "readme",
RepoURL: "https://github.com/valid_module_name",
ReadmeSource: "github.com/valid_module_name@v1.0.0/README.md",
})),
},
{
name: "module overview pseudoversion latest",
@ -558,10 +569,13 @@ func TestServer(t *testing.T) {
wantStatusCode: http.StatusOK,
want: in("",
pagecheck.ModuleHeader(mod, versioned),
in(".Overview-module a",
href(fmt.Sprintf("/mod/%s@%s", sample.ModulePath, sample.VersionString)),
text("^"+sample.ModulePath+"$")),
in(".Overview-readmeContent", text(`readme`))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: fmt.Sprintf("/mod/%s@%s", sample.ModulePath, sample.VersionString),
ModuleLinkText: sample.ModulePath,
ReadmeContent: "readme",
RepoURL: "https://github.com/valid_module_name",
ReadmeSource: "github.com/valid_module_name@v1.0.0/README.md",
})),
},
{
name: "module@version overview tab, pseudoversion",
@ -569,10 +583,13 @@ func TestServer(t *testing.T) {
wantStatusCode: http.StatusOK,
want: in("",
pagecheck.ModuleHeader(modPseudo, versioned),
in(".Overview-module a",
href(fmt.Sprintf("/mod/%s@%s", sample.ModulePath, pseudoVersion)),
text("^"+sample.ModulePath+"$")),
in(".Overview-readmeContent", text(`readme`))),
pagecheck.OverviewDetails(&pagecheck.Overview{
ModuleLink: fmt.Sprintf("/mod/%s@%s", sample.ModulePath, pseudoVersion),
ModuleLinkText: sample.ModulePath,
ReadmeContent: "readme",
RepoURL: "https://github.com/valid_module_name",
ReadmeSource: "github.com/valid_module_name@" + pseudoVersion + "/README.md",
})),
},
{
name: "module@version packages tab",

Просмотреть файл

@ -24,6 +24,8 @@ type Checker func(*html.Node) error
//
// Calling In(selector), with no checkers, just checks for the presence of
// a node matching the selector. (For the negation, see NotIn.)
//
// A nil Checker is valid and always succeeds.
func In(selector string, checkers ...Checker) Checker {
sel := mustParseSelector(selector)
return func(n *html.Node) error {
@ -103,6 +105,9 @@ func NotIn(selector string) Checker {
// check calls all the Checkers on n, returning the error of the first one to fail.
func check(n *html.Node, Checkers []Checker) error {
for _, m := range Checkers {
if m == nil {
continue
}
if err := m(n); err != nil {
return err
}

Просмотреть файл

@ -30,6 +30,16 @@ type Page struct {
ModuleURL string // the relative module URL
}
// Overview describes the contents of the overview tab.
type Overview struct {
ModuleLink string // relative link to module page
ModuleLinkText string
RepoURL string
PackageURL string
ReadmeContent string
ReadmeSource string
}
var (
in = htmlcheck.In
inAt = htmlcheck.InAt
@ -108,6 +118,26 @@ func LicenseDetails(ltype, bodySubstring, source string) htmlcheck.Checker {
exactText("Source: "+source)))
}
// OverviewDetails checks the details section of an overview tab.
func OverviewDetails(ov *Overview) htmlcheck.Checker {
var pkg htmlcheck.Checker
if ov.PackageURL != "" {
pkg = inAt(".Overview-sourceCodeLink a", 1,
href(ov.PackageURL),
exactText(ov.PackageURL))
}
return in("",
in("div.Overview-module > a",
href(ov.ModuleLink),
exactText(ov.ModuleLinkText)),
inAt(".Overview-sourceCodeLink a", 0,
href(ov.RepoURL),
exactText(ov.RepoURL)),
pkg,
in(".Overview-readmeContent", text(ov.ReadmeContent)),
in(".Overview-readmeSource", exactText("Source: "+ov.ReadmeSource)))
}
// versionBadge checks the latest-version badge on a header.
func versionBadge(p *Page) htmlcheck.Checker {
class := "DetailsHeader-"

Просмотреть файл

@ -22,7 +22,7 @@ import (
// These sample values can be used to construct test cases.
var (
ModulePath = "github.com/valid_module_name"
RepositoryURL = "github.com/valid_module_name"
RepositoryURL = "https://github.com/valid_module_name"
VersionString = "v1.0.0"
CommitTime = NowTruncated()
LicenseMetadata = []*license.Metadata{