Skip to content

Commit c63424d

Browse files
committed
internal: move templatecheck tests to their own package
The new package the templatecheck tests are in is not a transitive dependency of cmd/pkgsite, so that cmd/pkgsite no longer has a transitive test dependency on github.com/jba/templatecheck. To make this work we had to expose the templates from the internal/frontend and internal/godoc packages for the tests to use. For golang/go#61399 Change-Id: I1290ec24b53af77a82671c8fc068867e12857ce3 Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/550936 LUCI-TryBot-Result: Go LUCI <[email protected]> Run-TryBot: Michael Matloob <[email protected]> TryBot-Result: Gopher Robot <[email protected]> kokoro-CI: kokoro <[email protected]> Reviewed-by: Jonathan Amsterdam <[email protected]>
1 parent b2a01f8 commit c63424d

File tree

10 files changed

+226
-184
lines changed

10 files changed

+226
-184
lines changed

internal/frontend/badge.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"golang.org/x/pkgsite/internal/frontend/page"
1212
)
1313

14-
type badgePage struct {
14+
type BadgePage struct {
1515
page.BasePage
1616
// LinkPath is the URL path of the badge will link to.
1717
LinkPath string
@@ -36,7 +36,7 @@ func (s *Server) badgeHandler(w http.ResponseWriter, r *http.Request) {
3636
path = path[urlSchemeIdx+3:]
3737
}
3838

39-
page := badgePage{
39+
page := BadgePage{
4040
BasePage: s.newBasePage(r, "Badge"),
4141
LinkPath: path,
4242
BadgePath: "badge/" + path + ".svg",

internal/frontend/frontend_test.go

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ import (
1414
"time"
1515

1616
"github.com/google/safehtml/template"
17-
"github.com/jba/templatecheck"
1817
"golang.org/x/pkgsite/internal"
19-
"golang.org/x/pkgsite/internal/frontend/page"
20-
"golang.org/x/pkgsite/internal/frontend/versions"
2118
"golang.org/x/pkgsite/internal/testing/fakedatasource"
2219
"golang.org/x/pkgsite/static"
2320
thirdparty "golang.org/x/pkgsite/third_party"
@@ -132,84 +129,6 @@ func TestTagRoute(t *testing.T) {
132129
}
133130
}
134131

135-
func TestCheckTemplates(t *testing.T) {
136-
// Perform additional checks on parsed templates.
137-
staticFS := template.TrustedFSFromEmbed(static.FS)
138-
templates, err := parsePageTemplates(staticFS)
139-
if err != nil {
140-
t.Fatal(err)
141-
}
142-
for _, c := range []struct {
143-
name string
144-
subs []string
145-
typeval any
146-
}{
147-
{"badge", nil, badgePage{}},
148-
// error.tmpl omitted because relies on an associated "message" template
149-
// that's parsed on demand; see renderErrorPage above.
150-
{"fetch", nil, page.ErrorPage{}},
151-
{"homepage", nil, homepage{}},
152-
{"license-policy", nil, licensePolicyPage{}},
153-
{"search", nil, SearchPage{}},
154-
{"search-help", nil, page.BasePage{}},
155-
{"unit/main", nil, UnitPage{}},
156-
{
157-
"unit/main",
158-
[]string{"unit-outline", "unit-readme", "unit-doc", "unit-files", "unit-directories"},
159-
MainDetails{},
160-
},
161-
{"unit/importedby", nil, UnitPage{}},
162-
{"unit/importedby", []string{"importedby"}, ImportedByDetails{}},
163-
{"unit/imports", nil, UnitPage{}},
164-
{"unit/imports", []string{"imports"}, ImportsDetails{}},
165-
{"unit/licenses", nil, UnitPage{}},
166-
{"unit/licenses", []string{"licenses"}, LicensesDetails{}},
167-
{"unit/versions", nil, UnitPage{}},
168-
{"unit/versions", []string{"versions"}, versions.VersionsDetails{}},
169-
{"vuln", nil, page.BasePage{}},
170-
{"vuln/list", nil, VulnListPage{}},
171-
{"vuln/entry", nil, VulnEntryPage{}},
172-
} {
173-
t.Run(c.name, func(t *testing.T) {
174-
tm := templates[c.name]
175-
if tm == nil {
176-
t.Fatalf("no template %q", c.name)
177-
}
178-
if c.subs == nil {
179-
if err := templatecheck.CheckSafe(tm, c.typeval); err != nil {
180-
t.Fatal(err)
181-
}
182-
} else {
183-
for _, n := range c.subs {
184-
s := tm.Lookup(n)
185-
if s == nil {
186-
t.Fatalf("no sub-template %q of %q", n, c.name)
187-
}
188-
if err := templatecheck.CheckSafe(s, c.typeval); err != nil {
189-
t.Fatalf("%s: %v", n, err)
190-
}
191-
}
192-
}
193-
})
194-
}
195-
}
196-
197-
func TestStripScheme(t *testing.T) {
198-
for _, test := range []struct {
199-
url, want string
200-
}{
201-
{"http://github.com", "github.com"},
202-
{"https://github.com/path/to/something", "github.com/path/to/something"},
203-
{"example.com", "example.com"},
204-
{"chrome-extension://abcd", "abcd"},
205-
{"nonwellformed.com/path?://query=1", "query=1"},
206-
} {
207-
if got := stripScheme(test.url); got != test.want {
208-
t.Errorf("%q: got %q, want %q", test.url, got, test.want)
209-
}
210-
}
211-
}
212-
213132
func TestInstallFS(t *testing.T) {
214133
s, handler := newTestServer(t, nil)
215134
s.InstallFS("/dir", os.DirFS("."))

internal/frontend/homepage.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ var searchTips = []searchTip{
3939
}
4040

4141
// Homepage contains fields used in rendering the homepage template.
42-
type homepage struct {
42+
type Homepage struct {
4343
page.BasePage
4444

4545
// TipIndex is the index of the initial search tip to render.
@@ -62,7 +62,7 @@ type LocalModule struct {
6262
}
6363

6464
func (s *Server) serveHomepage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
65-
s.servePage(ctx, w, "homepage", homepage{
65+
s.servePage(ctx, w, "homepage", Homepage{
6666
BasePage: s.newBasePage(r, "Go Packages"),
6767
SearchTips: searchTips,
6868
TipIndex: rand.Intn(len(searchTips)),

internal/frontend/server.go

Lines changed: 6 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ import (
1414
"io/fs"
1515
"net/http"
1616
hpprof "net/http/pprof"
17-
"net/url"
1817
"os"
19-
"path"
2018
"strings"
2119
"sync"
2220
"time"
@@ -28,6 +26,7 @@ import (
2826
"golang.org/x/pkgsite/internal/experiment"
2927
pagepkg "golang.org/x/pkgsite/internal/frontend/page"
3028
"golang.org/x/pkgsite/internal/frontend/serrors"
29+
"golang.org/x/pkgsite/internal/frontend/templates"
3130
"golang.org/x/pkgsite/internal/frontend/urlinfo"
3231
"golang.org/x/pkgsite/internal/godoc/dochtml"
3332
"golang.org/x/pkgsite/internal/licenses"
@@ -37,8 +36,6 @@ import (
3736
"golang.org/x/pkgsite/internal/queue"
3837
"golang.org/x/pkgsite/internal/version"
3938
"golang.org/x/pkgsite/internal/vuln"
40-
"golang.org/x/text/cases"
41-
"golang.org/x/text/language"
4239
)
4340

4441
// Server can be installed to serve the go discovery frontend.
@@ -102,7 +99,7 @@ type ServerConfig struct {
10299
// NewServer creates a new Server for the given database and template directory.
103100
func NewServer(scfg ServerConfig) (_ *Server, err error) {
104101
defer derrors.Wrap(&err, "NewServer(...)")
105-
ts, err := parsePageTemplates(scfg.TemplateFS)
102+
ts, err := templates.ParsePageTemplates(scfg.TemplateFS)
106103
if err != nil {
107104
return nil, fmt.Errorf("error parsing templates: %v", err)
108105
}
@@ -434,8 +431,8 @@ func (s *Server) staticPageHandler(templateName, title string) http.HandlerFunc
434431
}
435432
}
436433

437-
// licensePolicyPage is used to generate the static license policy page.
438-
type licensePolicyPage struct {
434+
// LicensePolicyPage is used to generate the static license policy page.
435+
type LicensePolicyPage struct {
439436
pagepkg.BasePage
440437
LicenseFileNames []string
441438
LicenseTypes []licenses.AcceptedLicenseInfo
@@ -444,7 +441,7 @@ type licensePolicyPage struct {
444441
func (s *Server) licensePolicyHandler() http.HandlerFunc {
445442
lics := licenses.AcceptedLicenses()
446443
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
447-
page := licensePolicyPage{
444+
page := LicensePolicyPage{
448445
BasePage: s.newBasePage(r, "License Policy"),
449446
LicenseFileNames: licenses.FileNames,
450447
LicenseTypes: lics,
@@ -645,7 +642,7 @@ func (s *Server) findTemplate(templateName string) (*template.Template, error) {
645642
s.mu.Lock()
646643
defer s.mu.Unlock()
647644
var err error
648-
s.templates, err = parsePageTemplates(s.templateFS)
645+
s.templates, err = templates.ParsePageTemplates(s.templateFS)
649646
if err != nil {
650647
return nil, fmt.Errorf("error parsing templates: %v", err)
651648
}
@@ -666,82 +663,6 @@ func executeTemplate(ctx context.Context, templateName string, tmpl *template.Te
666663
return buf.Bytes(), nil
667664
}
668665

669-
var templateFuncs = template.FuncMap{
670-
"add": func(i, j int) int { return i + j },
671-
"subtract": func(i, j int) int { return i - j },
672-
"pluralize": func(i int, s string) string {
673-
if i == 1 {
674-
return s
675-
}
676-
return s + "s"
677-
},
678-
"commaseparate": func(s []string) string {
679-
return strings.Join(s, ", ")
680-
},
681-
"stripscheme": stripScheme,
682-
"capitalize": cases.Title(language.Und).String,
683-
"queryescape": url.QueryEscape,
684-
}
685-
686-
func stripScheme(url string) string {
687-
if i := strings.Index(url, "://"); i > 0 {
688-
return url[i+len("://"):]
689-
}
690-
return url
691-
}
692-
693-
// parsePageTemplates parses html templates contained in the given filesystem in
694-
// order to generate a map of Name->*template.Template.
695-
//
696-
// Separate templates are used so that certain contextual functions (e.g.
697-
// templateName) can be bound independently for each page.
698-
//
699-
// Templates in directories prefixed with an underscore are considered helper
700-
// templates and parsed together with the files in each base directory.
701-
func parsePageTemplates(fsys template.TrustedFS) (map[string]*template.Template, error) {
702-
templates := make(map[string]*template.Template)
703-
htmlSets := [][]string{
704-
{"about"},
705-
{"badge"},
706-
{"error"},
707-
{"fetch"},
708-
{"homepage"},
709-
{"license-policy"},
710-
{"search"},
711-
{"search-help"},
712-
{"styleguide"},
713-
{"subrepo"},
714-
{"unit/importedby", "unit"},
715-
{"unit/imports", "unit"},
716-
{"unit/licenses", "unit"},
717-
{"unit/main", "unit"},
718-
{"unit/versions", "unit"},
719-
{"vuln"},
720-
{"vuln/main", "vuln"},
721-
{"vuln/list", "vuln"},
722-
{"vuln/entry", "vuln"},
723-
}
724-
725-
for _, set := range htmlSets {
726-
t, err := template.New("frontend.tmpl").Funcs(templateFuncs).ParseFS(fsys, "frontend/*.tmpl")
727-
if err != nil {
728-
return nil, fmt.Errorf("ParseFS: %v", err)
729-
}
730-
helperGlob := "shared/*/*.tmpl"
731-
if _, err := t.ParseFS(fsys, helperGlob); err != nil {
732-
return nil, fmt.Errorf("ParseFS(%q): %v", helperGlob, err)
733-
}
734-
for _, f := range set {
735-
if _, err := t.ParseFS(fsys, path.Join("frontend", f, "*.tmpl")); err != nil {
736-
return nil, fmt.Errorf("ParseFS(%v): %v", f, err)
737-
}
738-
}
739-
templates[set[0]] = t
740-
}
741-
742-
return templates, nil
743-
}
744-
745666
func (s *Server) staticHandler() http.Handler {
746667
return http.StripPrefix("/static/", http.FileServer(http.FS(s.staticFS)))
747668
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package templates
6+
7+
import (
8+
"fmt"
9+
"net/url"
10+
"path"
11+
"strings"
12+
13+
"github.com/google/safehtml/template"
14+
"golang.org/x/text/cases"
15+
"golang.org/x/text/language"
16+
)
17+
18+
var templateFuncs = template.FuncMap{
19+
"add": func(i, j int) int { return i + j },
20+
"subtract": func(i, j int) int { return i - j },
21+
"pluralize": func(i int, s string) string {
22+
if i == 1 {
23+
return s
24+
}
25+
return s + "s"
26+
},
27+
"commaseparate": func(s []string) string {
28+
return strings.Join(s, ", ")
29+
},
30+
"stripscheme": stripScheme,
31+
"capitalize": cases.Title(language.Und).String,
32+
"queryescape": url.QueryEscape,
33+
}
34+
35+
func stripScheme(url string) string {
36+
if i := strings.Index(url, "://"); i > 0 {
37+
return url[i+len("://"):]
38+
}
39+
return url
40+
}
41+
42+
// ParsePageTemplates parses html templates contained in the given filesystem in
43+
// order to generate a map of Name->*template.Template.
44+
//
45+
// Separate templates are used so that certain contextual functions (e.g.
46+
// templateName) can be bound independently for each page.
47+
//
48+
// Templates in directories prefixed with an underscore are considered helper
49+
// templates and parsed together with the files in each base directory.
50+
func ParsePageTemplates(fsys template.TrustedFS) (map[string]*template.Template, error) {
51+
templates := make(map[string]*template.Template)
52+
htmlSets := [][]string{
53+
{"about"},
54+
{"badge"},
55+
{"error"},
56+
{"fetch"},
57+
{"homepage"},
58+
{"license-policy"},
59+
{"search"},
60+
{"search-help"},
61+
{"styleguide"},
62+
{"subrepo"},
63+
{"unit/importedby", "unit"},
64+
{"unit/imports", "unit"},
65+
{"unit/licenses", "unit"},
66+
{"unit/main", "unit"},
67+
{"unit/versions", "unit"},
68+
{"vuln"},
69+
{"vuln/main", "vuln"},
70+
{"vuln/list", "vuln"},
71+
{"vuln/entry", "vuln"},
72+
}
73+
74+
for _, set := range htmlSets {
75+
t, err := template.New("frontend.tmpl").Funcs(templateFuncs).ParseFS(fsys, "frontend/*.tmpl")
76+
if err != nil {
77+
return nil, fmt.Errorf("ParseFS: %v", err)
78+
}
79+
helperGlob := "shared/*/*.tmpl"
80+
if _, err := t.ParseFS(fsys, helperGlob); err != nil {
81+
return nil, fmt.Errorf("ParseFS(%q): %v", helperGlob, err)
82+
}
83+
for _, f := range set {
84+
if _, err := t.ParseFS(fsys, path.Join("frontend", f, "*.tmpl")); err != nil {
85+
return nil, fmt.Errorf("ParseFS(%v): %v", f, err)
86+
}
87+
}
88+
templates[set[0]] = t
89+
}
90+
91+
return templates, nil
92+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package templates
6+
7+
import (
8+
"testing"
9+
)
10+
11+
func TestStripScheme(t *testing.T) {
12+
for _, test := range []struct {
13+
url, want string
14+
}{
15+
{"http://github.com", "github.com"},
16+
{"https://github.com/path/to/something", "github.com/path/to/something"},
17+
{"example.com", "example.com"},
18+
{"chrome-extension://abcd", "abcd"},
19+
{"nonwellformed.com/path?://query=1", "query=1"},
20+
} {
21+
if got := stripScheme(test.url); got != test.want {
22+
t.Errorf("%q: got %q, want %q", test.url, got, test.want)
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)