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 }