hugo_smoke_test.go (9562B)
1 // Copyright 2019 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package hugolib
15
16 import (
17 "fmt"
18 "strings"
19 "testing"
20
21 qt "github.com/frankban/quicktest"
22 )
23
24 // The most basic build test.
25 func TestHello(t *testing.T) {
26 t.Parallel()
27 b := newTestSitesBuilder(t)
28 b.WithConfigFile("toml", `
29 baseURL="https://example.org"
30 disableKinds = ["term", "taxonomy", "section", "page"]
31 `)
32 b.WithContent("p1", `
33 ---
34 title: Page
35 ---
36
37 `)
38 b.WithTemplates("index.html", `Site: {{ .Site.Language.Lang | upper }}`)
39
40 b.Build(BuildCfg{})
41
42 b.AssertFileContent("public/index.html", `Site: EN`)
43 }
44
45 func TestSmoke(t *testing.T) {
46 t.Parallel()
47
48 c := qt.New(t)
49
50 const configFile = `
51 baseURL = "https://example.com"
52 title = "Simple Site"
53 rssLimit = 3
54 defaultContentLanguage = "en"
55 enableRobotsTXT = true
56
57 [languages]
58 [languages.en]
59 weight = 1
60 title = "In English"
61 [languages.no]
62 weight = 2
63 title = "På norsk"
64
65 [params]
66 hugo = "Rules!"
67
68 [outputs]
69 home = ["HTML", "JSON", "CSV", "RSS"]
70
71 `
72
73 const pageContentAndSummaryDivider = `---
74 title: Page with outputs
75 hugo: "Rocks!"
76 outputs: ["HTML", "JSON"]
77 tags: [ "hugo" ]
78 aliases: [ "/a/b/c" ]
79 ---
80
81 This is summary.
82
83 <!--more-->
84
85 This is content with some shortcodes.
86
87 Shortcode 1: {{< sc >}}.
88 Shortcode 2: {{< sc >}}.
89
90 `
91
92 const pageContentWithMarkdownShortcodes = `---
93 title: Page with markdown shortcode
94 hugo: "Rocks!"
95 outputs: ["HTML", "JSON"]
96 ---
97
98 This is summary.
99
100 <!--more-->
101
102 This is content[^a].
103
104 # Header above
105
106 {{% markdown-shortcode %}}
107 # Header inside
108
109 Some **markdown**.[^b]
110
111 {{% /markdown-shortcode %}}
112
113 # Heder below
114
115 Some more content[^c].
116
117 Footnotes:
118
119 [^a]: Fn 1
120 [^b]: Fn 2
121 [^c]: Fn 3
122
123 `
124
125 pageContentAutoSummary := strings.Replace(pageContentAndSummaryDivider, "<!--more-->", "", 1)
126
127 b := newTestSitesBuilder(t).WithConfigFile("toml", configFile)
128 b.WithTemplatesAdded("shortcodes/markdown-shortcode.html", `
129 Some **Markdown** in shortcode.
130
131 {{ .Inner }}
132
133
134
135 `)
136
137 b.WithTemplatesAdded("shortcodes/markdown-shortcode.json", `
138 Some **Markdown** in JSON shortcode.
139 {{ .Inner }}
140
141 `)
142
143 for i := 1; i <= 11; i++ {
144 if i%2 == 0 {
145 b.WithContent(fmt.Sprintf("blog/page%d.md", i), pageContentAndSummaryDivider)
146 b.WithContent(fmt.Sprintf("blog/page%d.no.md", i), pageContentAndSummaryDivider)
147 } else {
148 b.WithContent(fmt.Sprintf("blog/page%d.md", i), pageContentAutoSummary)
149 }
150 }
151
152 for i := 1; i <= 5; i++ {
153 // Root section pages
154 b.WithContent(fmt.Sprintf("root%d.md", i), pageContentAutoSummary)
155 }
156
157 // https://github.com/gohugoio/hugo/issues/4695
158 b.WithContent("blog/markyshort.md", pageContentWithMarkdownShortcodes)
159
160 // Add one bundle
161 b.WithContent("blog/mybundle/index.md", pageContentAndSummaryDivider)
162 b.WithContent("blog/mybundle/mydata.csv", "Bundled CSV")
163
164 const (
165 commonPageTemplate = `|{{ .Kind }}|{{ .Title }}|{{ .File.Path }}|{{ .Summary }}|{{ .Content }}|RelPermalink: {{ .RelPermalink }}|WordCount: {{ .WordCount }}|Pages: {{ .Pages }}|Data Pages: Pages({{ len .Data.Pages }})|Resources: {{ len .Resources }}|Summary: {{ .Summary }}`
166 commonPaginatorTemplate = `|Paginator: {{ with .Paginator }}{{ .PageNumber }}{{ else }}NIL{{ end }}`
167 commonListTemplateNoPaginator = `|{{ $pages := .Pages }}{{ if .IsHome }}{{ $pages = .Site.RegularPages }}{{ end }}{{ range $i, $e := ($pages | first 1) }}|Render {{ $i }}: {{ .Kind }}|{{ .Render "li" }}|{{ end }}|Site params: {{ $.Site.Params.hugo }}|RelPermalink: {{ .RelPermalink }}`
168 commonListTemplate = commonPaginatorTemplate + `|{{ $pages := .Pages }}{{ if .IsHome }}{{ $pages = .Site.RegularPages }}{{ end }}{{ range $i, $e := ($pages | first 1) }}|Render {{ $i }}: {{ .Kind }}|{{ .Render "li" }}|{{ end }}|Site params: {{ $.Site.Params.hugo }}|RelPermalink: {{ .RelPermalink }}`
169 commonShortcodeTemplate = `|{{ .Name }}|{{ .Ordinal }}|{{ .Page.Summary }}|{{ .Page.Content }}|WordCount: {{ .Page.WordCount }}`
170 prevNextTemplate = `|Prev: {{ with .Prev }}{{ .RelPermalink }}{{ end }}|Next: {{ with .Next }}{{ .RelPermalink }}{{ end }}`
171 prevNextInSectionTemplate = `|PrevInSection: {{ with .PrevInSection }}{{ .RelPermalink }}{{ end }}|NextInSection: {{ with .NextInSection }}{{ .RelPermalink }}{{ end }}`
172 paramsTemplate = `|Params: {{ .Params.hugo }}`
173 treeNavTemplate = `|CurrentSection: {{ .CurrentSection }}`
174 )
175
176 b.WithTemplates(
177 "_default/list.html", "HTML: List"+commonPageTemplate+commonListTemplate+"|First Site: {{ .Sites.First.Title }}",
178 "_default/list.json", "JSON: List"+commonPageTemplate+commonListTemplateNoPaginator,
179 "_default/list.csv", "CSV: List"+commonPageTemplate+commonListTemplateNoPaginator,
180 "_default/single.html", "HTML: Single"+commonPageTemplate+prevNextTemplate+prevNextInSectionTemplate+treeNavTemplate,
181 "_default/single.json", "JSON: Single"+commonPageTemplate,
182
183 // For .Render test
184 "_default/li.html", `HTML: LI|{{ strings.Contains .Content "HTML: Shortcode: sc" }}`+paramsTemplate,
185 "_default/li.json", `JSON: LI|{{ strings.Contains .Content "JSON: Shortcode: sc" }}`+paramsTemplate,
186 "_default/li.csv", `CSV: LI|{{ strings.Contains .Content "CSV: Shortcode: sc" }}`+paramsTemplate,
187
188 "404.html", "{{ .Kind }}|{{ .Title }}|Page not found",
189
190 "shortcodes/sc.html", "HTML: Shortcode: "+commonShortcodeTemplate,
191 "shortcodes/sc.json", "JSON: Shortcode: "+commonShortcodeTemplate,
192 "shortcodes/sc.csv", "CSV: Shortcode: "+commonShortcodeTemplate,
193 )
194
195 b.CreateSites().Build(BuildCfg{})
196
197 b.AssertFileContent("public/blog/page1/index.html",
198 "This is content with some shortcodes.",
199 "Page with outputs",
200 "Pages: Pages(0)",
201 "RelPermalink: /blog/page1/|",
202 "Shortcode 1: HTML: Shortcode: |sc|0|||WordCount: 0.",
203 "Shortcode 2: HTML: Shortcode: |sc|1|||WordCount: 0.",
204 "Prev: /blog/page10/|Next: /blog/mybundle/",
205 "PrevInSection: /blog/page10/|NextInSection: /blog/mybundle/",
206 "Summary: This is summary.",
207 "CurrentSection: Page(/blog)",
208 )
209
210 b.AssertFileContent("public/blog/page1/index.json",
211 "JSON: Single|page|Page with outputs|",
212 "SON: Shortcode: |sc|0||")
213
214 b.AssertFileContent("public/index.html",
215 "home|In English",
216 "Site params: Rules",
217 "Pages: Pages(6)|Data Pages: Pages(6)",
218 "Paginator: 1",
219 "First Site: In English",
220 "RelPermalink: /",
221 )
222
223 b.AssertFileContent("public/no/index.html", "home|På norsk", "RelPermalink: /no/")
224
225 // Check RSS
226 rssHome := b.FileContent("public/index.xml")
227 c.Assert(rssHome, qt.Contains, `<atom:link href="https://example.com/index.xml" rel="self" type="application/rss+xml" />`)
228 c.Assert(strings.Count(rssHome, "<item>"), qt.Equals, 3) // rssLimit = 3
229
230 // .Render should use template/content from the current output format
231 // even if that output format isn't configured for that page.
232 b.AssertFileContent(
233 "public/index.json",
234 "Render 0: page|JSON: LI|false|Params: Rocks!",
235 )
236
237 b.AssertFileContent(
238 "public/index.html",
239 "Render 0: page|HTML: LI|false|Params: Rocks!|",
240 )
241
242 b.AssertFileContent(
243 "public/index.csv",
244 "Render 0: page|CSV: LI|false|Params: Rocks!|",
245 )
246
247 // Check bundled resources
248 b.AssertFileContent(
249 "public/blog/mybundle/index.html",
250 "Resources: 1",
251 )
252
253 // Check pages in root section
254 b.AssertFileContent(
255 "public/root3/index.html",
256 "Single|page|Page with outputs|root3.md|",
257 "Prev: /root4/|Next: /root2/|PrevInSection: /root4/|NextInSection: /root2/",
258 )
259
260 b.AssertFileContent(
261 "public/root3/index.json", "Shortcode 1: JSON:")
262
263 // Paginators
264 b.AssertFileContent("public/page/1/index.html", `rel="canonical" href="https://example.com/"`)
265 b.AssertFileContent("public/page/2/index.html", "HTML: List|home|In English|", "Paginator: 2")
266
267 // 404
268 b.AssertFileContent("public/404.html", "404|404 Page not found")
269
270 // Sitemaps
271 b.AssertFileContent("public/en/sitemap.xml", "<loc>https://example.com/blog/</loc>")
272 b.AssertFileContent("public/no/sitemap.xml", `hreflang="no"`)
273
274 b.AssertFileContent("public/sitemap.xml", "<loc>https://example.com/en/sitemap.xml</loc>", "<loc>https://example.com/no/sitemap.xml</loc>")
275
276 // robots.txt
277 b.AssertFileContent("public/robots.txt", `User-agent: *`)
278
279 // Aliases
280 b.AssertFileContent("public/a/b/c/index.html", `refresh`)
281
282 // Markdown vs shortcodes
283 // Check that all footnotes are grouped (even those from inside the shortcode)
284 b.AssertFileContentRe("public/blog/markyshort/index.html", `Footnotes:.*<ol>.*Fn 1.*Fn 2.*Fn 3.*</ol>`)
285 }
286
287 // https://github.com/golang/go/issues/30286
288 func TestDataRace(t *testing.T) {
289 const page = `
290 ---
291 title: "The Page"
292 outputs: ["HTML", "JSON"]
293 ---
294
295 The content.
296
297
298 `
299
300 b := newTestSitesBuilder(t).WithSimpleConfigFile()
301 for i := 1; i <= 50; i++ {
302 b.WithContent(fmt.Sprintf("blog/page%d.md", i), page)
303 }
304
305 b.WithContent("_index.md", `
306 ---
307 title: "The Home"
308 outputs: ["HTML", "JSON", "CSV", "RSS"]
309 ---
310
311 The content.
312
313
314 `)
315
316 commonTemplate := `{{ .Data.Pages }}`
317
318 b.WithTemplatesAdded("_default/single.html", "HTML Single: "+commonTemplate)
319 b.WithTemplatesAdded("_default/list.html", "HTML List: "+commonTemplate)
320
321 b.CreateSites().Build(BuildCfg{})
322 }