github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/hugolib/hugo_smoke_test.go (about)

     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 }}|{{ .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  }