diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2016-11-11 11:35:55 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2016-11-22 09:57:03 +0100 |
commit | 487b210fb8a31b3636030ea960f6565b9e6b3c54 (patch) | |
tree | abe25d8832000e9ff75e1d017bfac2ac9793631f /hugolib/hugo_sites_build_test.go | |
parent | c80308e6b3f3f4f6879ee6b7301575f162ac9209 (diff) |
node to page: Handle Date and Lastmod
Updates #2297
Diffstat (limited to 'hugolib/hugo_sites_build_test.go')
-rw-r--r-- | hugolib/hugo_sites_build_test.go | 1265 |
1 files changed, 1265 insertions, 0 deletions
diff --git a/hugolib/hugo_sites_build_test.go b/hugolib/hugo_sites_build_test.go new file mode 100644 index 000000000..05743a804 --- /dev/null +++ b/hugolib/hugo_sites_build_test.go @@ -0,0 +1,1265 @@ +package hugolib + +import ( + "bytes" + "fmt" + "regexp" + "strings" + "testing" + + "os" + "path/filepath" + "text/template" + + "github.com/fortytw2/leaktest" + "github.com/fsnotify/fsnotify" + "github.com/spf13/afero" + "github.com/spf13/hugo/helpers" + "github.com/spf13/hugo/hugofs" + "github.com/spf13/hugo/source" + // jww "github.com/spf13/jwalterweatherman" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type testSiteConfig struct { + DefaultContentLanguage string +} + +func init() { + testCommonResetState() +} + +func testCommonResetState() { + hugofs.InitMemFs() + viper.Reset() + viper.SetFs(hugofs.Source()) + helpers.ResetConfigProvider() + loadDefaultSettings() + + // Default is false, but true is easier to use as default in tests + viper.Set("defaultContentLanguageInSubdir", true) + + if err := hugofs.Source().Mkdir("content", 0755); err != nil { + panic("Content folder creation failed.") + } + +} + +func TestMultiSitesMainLangInRoot(t *testing.T) { + //jww.SetStdoutThreshold(jww.LevelDebug) + + for _, b := range []bool{true, false} { + doTestMultiSitesMainLangInRoot(t, b) + } +} + +func doTestMultiSitesMainLangInRoot(t *testing.T, defaultInSubDir bool) { + testCommonResetState() + viper.Set("defaultContentLanguageInSubdir", defaultInSubDir) + siteConfig := testSiteConfig{DefaultContentLanguage: "fr"} + + sites := createMultiTestSites(t, siteConfig, multiSiteTOMLConfigTemplate) + + err := sites.Build(BuildCfg{}) + + if err != nil { + t.Fatalf("Failed to build sites: %s", err) + } + + require.Len(t, sites.Sites, 4) + + enSite := sites.Sites[0] + frSite := sites.Sites[1] + + require.Equal(t, "/en", enSite.Info.LanguagePrefix) + + if defaultInSubDir { + require.Equal(t, "/fr", frSite.Info.LanguagePrefix) + } else { + require.Equal(t, "", frSite.Info.LanguagePrefix) + } + + require.Equal(t, "/blog/en/foo", enSite.Info.pathSpec.RelURL("foo", true)) + + doc1en := enSite.regularPages[0] + doc1fr := frSite.regularPages[0] + + enPerm, _ := doc1en.Permalink() + enRelPerm, _ := doc1en.RelPermalink() + require.Equal(t, "http://example.com/blog/en/sect/doc1-slug/", enPerm) + require.Equal(t, "/blog/en/sect/doc1-slug/", enRelPerm) + + frPerm, _ := doc1fr.Permalink() + frRelPerm, _ := doc1fr.RelPermalink() + // Main language in root + require.Equal(t, replaceDefaultContentLanguageValue("http://example.com/blog/fr/sect/doc1/", defaultInSubDir), frPerm) + require.Equal(t, replaceDefaultContentLanguageValue("/blog/fr/sect/doc1/", defaultInSubDir), frRelPerm) + + assertFileContent(t, "public/fr/sect/doc1/index.html", defaultInSubDir, "Single", "Bonjour") + assertFileContent(t, "public/en/sect/doc1-slug/index.html", defaultInSubDir, "Single", "Hello") + + // Check home + if defaultInSubDir { + // should have a redirect on top level. + assertFileContent(t, "public/index.html", true, `<meta http-equiv="refresh" content="0; url=http://example.com/blog/fr" />`) + } else { + // should have redirect back to root + assertFileContent(t, "public/fr/index.html", true, `<meta http-equiv="refresh" content="0; url=http://example.com/blog" />`) + } + assertFileContent(t, "public/fr/index.html", defaultInSubDir, "Home", "Bonjour") + assertFileContent(t, "public/en/index.html", defaultInSubDir, "Home", "Hello") + + // Check list pages + assertFileContent(t, "public/fr/sect/index.html", defaultInSubDir, "List", "Bonjour") + assertFileContent(t, "public/en/sect/index.html", defaultInSubDir, "List", "Hello") + assertFileContent(t, "public/fr/plaques/frtag1/index.html", defaultInSubDir, "List", "Bonjour") + assertFileContent(t, "public/en/tags/tag1/index.html", defaultInSubDir, "List", "Hello") + + // Check sitemaps + // Sitemaps behaves different: In a multilanguage setup there will always be a index file and + // one sitemap in each lang folder. + assertFileContent(t, "public/sitemap.xml", true, + "<loc>http://example.com/blog/en/sitemap.xml</loc>", + "<loc>http://example.com/blog/fr/sitemap.xml</loc>") + + if defaultInSubDir { + assertFileContent(t, "public/fr/sitemap.xml", true, "<loc>http://example.com/blog/fr/</loc>") + } else { + assertFileContent(t, "public/fr/sitemap.xml", true, "<loc>http://example.com/blog/</loc>") + } + assertFileContent(t, "public/en/sitemap.xml", true, "<loc>http://example.com/blog/en/</loc>") + + // Check rss + assertFileContent(t, "public/fr/index.xml", defaultInSubDir, `<atom:link href="http://example.com/blog/fr/index.xml"`) + assertFileContent(t, "public/en/index.xml", defaultInSubDir, `<atom:link href="http://example.com/blog/en/index.xml"`) + assertFileContent(t, "public/fr/sect/index.xml", defaultInSubDir, `<atom:link href="http://example.com/blog/fr/sect/index.xml"`) + assertFileContent(t, "public/en/sect/index.xml", defaultInSubDir, `<atom:link href="http://example.com/blog/en/sect/index.xml"`) + assertFileContent(t, "public/fr/plaques/frtag1/index.xml", defaultInSubDir, `<atom:link href="http://example.com/blog/fr/plaques/frtag1/index.xml"`) + assertFileContent(t, "public/en/tags/tag1/index.xml", defaultInSubDir, `<atom:link href="http://example.com/blog/en/tags/tag1/index.xml"`) + + // Check paginators + assertFileContent(t, "public/fr/page/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/fr/"`) + assertFileContent(t, "public/en/page/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/en/"`) + assertFileContent(t, "public/fr/page/2/index.html", defaultInSubDir, "Home Page 2", "Bonjour", "http://example.com/blog/fr/") + assertFileContent(t, "public/en/page/2/index.html", defaultInSubDir, "Home Page 2", "Hello", "http://example.com/blog/en/") + assertFileContent(t, "public/fr/sect/page/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/fr/sect/"`) + assertFileContent(t, "public/en/sect/page/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/en/sect/"`) + assertFileContent(t, "public/fr/sect/page/2/index.html", defaultInSubDir, "List Page 2", "Bonjour", "http://example.com/blog/fr/sect/") + assertFileContent(t, "public/en/sect/page/2/index.html", defaultInSubDir, "List Page 2", "Hello", "http://example.com/blog/en/sect/") + assertFileContent(t, "public/fr/plaques/frtag1/page/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/fr/plaques/frtag1/"`) + assertFileContent(t, "public/en/tags/tag1/page/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/en/tags/tag1/"`) + assertFileContent(t, "public/fr/plaques/frtag1/page/2/index.html", defaultInSubDir, "List Page 2", "Bonjour", "http://example.com/blog/fr/plaques/frtag1/") + assertFileContent(t, "public/en/tags/tag1/page/2/index.html", defaultInSubDir, "List Page 2", "Hello", "http://example.com/blog/en/tags/tag1/") + // nn (Nynorsk) and nb (Bokmål) have custom pagePath: side ("page" in Norwegian) + assertFileContent(t, "public/nn/side/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/nn/"`) + assertFileContent(t, "public/nb/side/1/index.html", defaultInSubDir, `refresh" content="0; url=http://example.com/blog/nb/"`) +} + +func replaceDefaultContentLanguageValue(value string, defaultInSubDir bool) string { + replace := viper.GetString("defaultContentLanguage") + "/" + if !defaultInSubDir { + value = strings.Replace(value, replace, "", 1) + + } + return value + +} + +func assertFileContent(t *testing.T, filename string, defaultInSubDir bool, matches ...string) { + filename = replaceDefaultContentLanguageValue(filename, defaultInSubDir) + content := readDestination(t, filename) + for _, match := range matches { + match = replaceDefaultContentLanguageValue(match, defaultInSubDir) + require.True(t, strings.Contains(content, match), fmt.Sprintf("File no match for\n%q in\n%q:\n%s", match, filename, content)) + } +} + +func assertFileContentRegexp(t *testing.T, filename string, defaultInSubDir bool, matches ...string) { + filename = replaceDefaultContentLanguageValue(filename, defaultInSubDir) + content := readDestination(t, filename) + for _, match := range matches { + match = replaceDefaultContentLanguageValue(match, defaultInSubDir) + r := regexp.MustCompile(match) + require.True(t, r.MatchString(content), fmt.Sprintf("File no match for\n%q in\n%q:\n%s", match, filename, content)) + } +} + +// +func TestMultiSitesBuild(t *testing.T) { + for _, config := range []struct { + content string + suffix string + }{ + {multiSiteTOMLConfigTemplate, "toml"}, + {multiSiteYAMLConfig, "yml"}, + {multiSiteJSONConfig, "json"}, + } { + doTestMultiSitesBuild(t, config.content, config.suffix) + } +} + +func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) { + defer leaktest.Check(t)() + testCommonResetState() + siteConfig := testSiteConfig{DefaultContentLanguage: "fr"} + sites := createMultiTestSitesForConfig(t, siteConfig, configTemplate, configSuffix) + + err := sites.Build(BuildCfg{}) + + if err != nil { + t.Fatalf("Failed to build sites: %s", err) + } + + enSite := sites.Sites[0] + + assert.Equal(t, "en", enSite.Language.Lang) + + if len(enSite.regularPages) != 4 { + t.Fatal("Expected 4 english pages") + } + assert.Len(t, enSite.Source.Files(), 14, "should have 13 source files") + assert.Len(t, enSite.AllPages, 28, "should have 28 total pages (including translations and index types)") + + doc1en := enSite.regularPages[0] + permalink, err := doc1en.Permalink() + assert.NoError(t, err, "permalink call failed") + assert.Equal(t, "http://example.com/blog/en/sect/doc1-slug/", permalink, "invalid doc1.en permalink") + assert.Len(t, doc1en.Translations(), 1, "doc1-en should have one translation, excluding itself") + + doc2 := enSite.regularPages[1] + permalink, err = doc2.Permalink() + assert.NoError(t, err, "permalink call failed") + assert.Equal(t, "http://example.com/blog/en/sect/doc2/", permalink, "invalid doc2 permalink") + + doc3 := enSite.regularPages[2] + permalink, err = doc3.Permalink() + assert.NoError(t, err, "permalink call failed") + // Note that /superbob is a custom URL set in frontmatter. + // We respect that URL literally (it can be /search.json) + // and do no not do any language code prefixing. + assert.Equal(t, "http://example.com/blog/superbob", permalink, "invalid doc3 permalink") + + assert.Equal(t, "/superbob", doc3.URL(), "invalid url, was specified on doc3") + assertFileContent(t, "public/superbob/index.html", true, "doc3|Hello|en") + assert.Equal(t, doc2.Next, doc3, "doc3 should follow doc2, in .Next") + + doc1fr := doc1en.Translations()[0] + permalink, err = doc1fr.Permalink() + assert.NoError(t, err, "permalink call failed") + assert.Equal(t, "http://example.com/blog/fr/sect/doc1/", permalink, "invalid doc1fr permalink") + + assert.Equal(t, doc1en.Translations()[0], doc1fr, "doc1-en should have doc1-fr as translation") + assert.Equal(t, doc1fr.Translations()[0], doc1en, "doc1-fr should have doc1-en as translation") + assert.Equal(t, "fr", doc1fr.Language().Lang) + + doc4 := enSite.AllPages[4] + permalink, err = doc4.Permalink() + assert.NoError(t, err, "permalink call failed") + assert.Equal(t, "http://example.com/blog/fr/sect/doc4/", permalink, "invalid doc4 permalink") + assert.Equal(t, "/blog/fr/sect/doc4/", doc4.URL()) + + assert.Len(t, doc4.Translations(), 0, "found translations for doc4") + + doc5 := enSite.AllPages[5] + permalink, err = doc5.Permalink() + assert.NoError(t, err, "permalink call failed") + assert.Equal(t, "http://example.com/blog/fr/somewhere/else/doc5", permalink, "invalid doc5 permalink") + + // Taxonomies and their URLs + assert.Len(t, enSite.Taxonomies, 1, "should have 1 taxonomy") + tags := enSite.Taxonomies["tags"] + assert.Len(t, tags, 2, "should have 2 different tags") + assert.Equal(t, tags["tag1"][0].Page, doc1en, "first tag1 page should be doc1") + + frSite := sites.Sites[1] + + assert.Equal(t, "fr", frSite.Language.Lang) + assert.Len(t, frSite.regularPages, 3, "should have 3 pages") + assert.Len(t, frSite.AllPages, 28, "should have 28 total pages (including translations and nodes)") + + for _, frenchPage := range frSite.regularPages { + assert.Equal(t, "fr", frenchPage.Lang()) + } + + // Check redirect to main language, French + languageRedirect := readDestination(t, "public/index.html") + require.True(t, strings.Contains(languageRedirect, "0; url=http://example.com/blog/fr"), languageRedirect) + + // check home page content (including data files rendering) + assertFileContent(t, "public/en/index.html", true, "Home Page 1", "Hello", "Hugo Rocks!") + assertFileContent(t, "public/fr/index.html", true, "Home Page 1", "Bonjour", "Hugo Rocks!") + + // check single page content + assertFileContent(t, "public/fr/sect/doc1/index.html", true, "Single", "Shortcode: Bonjour") + assertFileContent(t, "public/en/sect/doc1-slug/index.html", true, "Single", "Shortcode: Hello") + + // Check node translations + homeEn := enSite.getPage(PageHome) + require.NotNil(t, homeEn) + require.Len(t, homeEn.Translations(), 3) + require.Equal(t, "fr", homeEn.Translations()[0].Lang()) + require.Equal(t, "nn", homeEn.Translations()[1].Lang()) + require.Equal(t, "På nynorsk", homeEn.Translations()[1].Title) + require.Equal(t, "nb", homeEn.Translations()[2].Lang()) + require.Equal(t, "På bokmål", homeEn.Translations()[2].Title, configSuffix) + require.Equal(t, "Bokmål", homeEn.Translations()[2].Language().LanguageName, configSuffix) + + sectFr := frSite.getPage(PageSection, "sect") + require.NotNil(t, sectFr) + + require.Equal(t, "fr", sectFr.Lang()) + require.Len(t, sectFr.Translations(), 1) + require.Equal(t, "en", sectFr.Translations()[0].Lang()) + require.Equal(t, "Sects", sectFr.Translations()[0].Title) + + nnSite := sites.Sites[2] + require.Equal(t, "nn", nnSite.Language.Lang) + taxNn := nnSite.getPage(PageTaxonomyTerm, "lag") + require.NotNil(t, taxNn) + require.Len(t, taxNn.Translations(), 1) + require.Equal(t, "nb", taxNn.Translations()[0].Lang()) + + taxTermNn := nnSite.getPage(PageTaxonomy, "lag", "sogndal") + require.NotNil(t, taxTermNn) + require.Len(t, taxTermNn.Translations(), 1) + require.Equal(t, "nb", taxTermNn.Translations()[0].Lang()) + + // Check sitemap(s) + sitemapIndex := readDestination(t, "public/sitemap.xml") + require.True(t, strings.Contains(sitemapIndex, "<loc>http://example.com/blog/en/sitemap.xml</loc>"), sitemapIndex) + require.True(t, strings.Contains(sitemapIndex, "<loc>http://example.com/blog/fr/sitemap.xml</loc>"), sitemapIndex) + sitemapEn := readDestination(t, "public/en/sitemap.xml") + sitemapFr := readDestination(t, "public/fr/sitemap.xml") + require.True(t, strings.Contains(sitemapEn, "http://example.com/blog/en/sect/doc2/"), sitemapEn) + require.True(t, strings.Contains(sitemapFr, "http://example.com/blog/fr/sect/doc1/"), sitemapFr) + + // Check taxonomies + enTags := enSite.Taxonomies["tags"] + frTags := frSite.Taxonomies["plaques"] + require.Len(t, enTags, 2, fmt.Sprintf("Tags in en: %v", enTags)) + require.Len(t, frTags, 2, fmt.Sprintf("Tags in fr: %v", frTags)) + require.NotNil(t, enTags["tag1"]) + require.NotNil(t, frTags["frtag1"]) + readDestination(t, "public/fr/plaques/frtag1/index.html") + readDestination(t, "public/en/tags/tag1/index.html") + + // Check Blackfriday config + assert.True(t, strings.Contains(string(doc1fr.Content), "«"), string(doc1fr.Content)) + assert.False(t, strings.Contains(string(doc1en.Content), "«"), string(doc1en.Content)) + assert.True(t, strings.Contains(string(doc1en.Content), "“"), string(doc1en.Content)) + + // Check that the drafts etc. are not built/processed/rendered. + assertShouldNotBuild(t, sites) + + // en and nn have custom site menus + require.Len(t, frSite.Menus, 0, "fr: "+configSuffix) + require.Len(t, enSite.Menus, 1, "en: "+configSuffix) + require.Len(t, nnSite.Menus, 1, "nn: "+configSuffix) + + require.Equal(t, "Home", enSite.Menus["main"].ByName()[0].Name) + require.Equal(t, "Heim", nnSite.Menus["main"].ByName()[0].Name) + +} + +func TestMultiSitesRebuild(t *testing.T) { + + defer leaktest.Check(t)() + testCommonResetState() + siteConfig := testSiteConfig{DefaultContentLanguage: "fr"} + sites := createMultiTestSites(t, siteConfig, multiSiteTOMLConfigTemplate) + cfg := BuildCfg{Watching: true} + + err := sites.Build(cfg) + + if err != nil { + t.Fatalf("Failed to build sites: %s", err) + } + + _, err = hugofs.Destination().Open("public/en/sect/doc2/index.html") + + if err != nil { + t.Fatalf("Unable to locate file") + } + + enSite := sites.Sites[0] + frSite := sites.Sites[1] + + require.Len(t, enSite.regularPages, 4) + require.Len(t, frSite.regularPages, 3) + + // Verify translations + assertFileContent(t, "public/en/sect/doc1-slug/index.html", true, "Hello") + assertFileContent(t, "public/fr/sect/doc1/index.html", true, "Bonjour") + + // check single page content + assertFileContent(t, "public/fr/sect/doc1/index.html", true, "Single", "Shortcode: Bonjour") + assertFileContent(t, "public/en/sect/doc1-slug/index.html", true, "Single", "Shortcode: Hello") + + for i, this := range []struct { + preFunc func(t *testing.T) + events []fsnotify.Event + assertFunc func(t *testing.T) + }{ + // * Remove doc + // * Add docs existing languages + // (Add doc new language: TODO(bep) we should load config.toml as part of these so we can add languages). + // * Rename file + // * Change doc + // * Change a template + // * Change language file + { + nil, + []fsnotify.Event{{Name: "content/sect/doc2.en.md", Op: fsnotify.Remove}}, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 3, "1 en removed") + + // Check build stats + require.Equal(t, 1, enSite.draftCount, "Draft") + require.Equal(t, 1, enSite.futureCount, "Future") + require.Equal(t, 1, enSite.expiredCount, "Expired") + require.Equal(t, 0, frSite.draftCount, "Draft") + require.Equal(t, 1, frSite.futureCount, "Future") + require.Equal(t, 1, frSite.expiredCount, "Expired") + }, + }, + { + func(t *testing.T) { + writeNewContentFile(t, "new_en_1", "2016-07-31", "content/new1.en.md", -5) + writeNewContentFile(t, "new_en_2", "1989-07-30", "content/new2.en.md", -10) + writeNewContentFile(t, "new_fr_1", "2016-07-30", "content/new1.fr.md", 10) + }, + []fsnotify.Event{ + {Name: "content/new1.en.md", Op: fsnotify.Create}, + {Name: "content/new2.en.md", Op: fsnotify.Create}, + {Name: "content/new1.fr.md", Op: fsnotify.Create}, + }, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 5) + require.Len(t, enSite.AllPages, 30) + require.Len(t, frSite.regularPages, 4) + require.Equal(t, "new_fr_1", frSite.regularPages[3].Title) + require.Equal(t, "new_en_2", enSite.regularPages[0].Title) + require.Equal(t, "new_en_1", enSite.regularPages[1].Title) + + rendered := readDestination(t, "public/en/new1/index.html") + require.True(t, strings.Contains(rendered, "new_en_1"), rendered) + }, + }, + { + func(t *testing.T) { + p := "content/sect/doc1.en.md" + doc1 := readSource(t, p) + doc1 += "CHANGED" + writeSource(t, p, doc1) + }, + []fsnotify.Event{{Name: "content/sect/doc1.en.md", Op: fsnotify.Write}}, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 5) + doc1 := readDestination(t, "public/en/sect/doc1-slug/index.html") + require.True(t, strings.Contains(doc1, "CHANGED"), doc1) + + }, + }, + // Rename a file + { + func(t *testing.T) { + if err := hugofs.Source().Rename("content/new1.en.md", "content/new1renamed.en.md"); err != nil { + t.Fatalf("Rename failed: %s", err) + } + }, + []fsnotify.Event{ + {Name: "content/new1renamed.en.md", Op: fsnotify.Rename}, + {Name: "content/new1.en.md", Op: fsnotify.Rename}, + }, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 5, "Rename") + require.Equal(t, "new_en_1", enSite.regularPages[1].Title) + rendered := readDestination(t, "public/en/new1renamed/index.html") + require.True(t, strings.Contains(rendered, "new_en_1"), rendered) + }}, + { + // Change a template + func(t *testing.T) { + template := "layouts/_default/single.html" + templateContent := readSource(t, template) + templateContent += "{{ print \"Template Changed\"}}" + writeSource(t, template, templateContent) + }, + []fsnotify.Event{{Name: "layouts/_default/single.html", Op: fsnotify.Write}}, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 5) + require.Len(t, enSite.AllPages, 30) + require.Len(t, frSite.regularPages, 4) + doc1 := readDestination(t, "public/en/sect/doc1-slug/index.html") + require.True(t, strings.Contains(doc1, "Template Changed"), doc1) + }, + }, + { + // Change a language file + func(t *testing.T) { + languageFile := "i18n/fr.yaml" + langContent := readSource(t, languageFile) + langContent = strings.Replace(langContent, "Bonjour", "Salut", 1) + writeSource(t, languageFile, langContent) + }, + []fsnotify.Event{{Name: "i18n/fr.yaml", Op: fsnotify.Write}}, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 5) + require.Len(t, enSite.AllPages, 30) + require.Len(t, frSite.regularPages, 4) + docEn := readDestination(t, "public/en/sect/doc1-slug/index.html") + require.True(t, strings.Contains(docEn, "Hello"), "No Hello") + docFr := readDestination(t, "public/fr/sect/doc1/index.html") + require.True(t, strings.Contains(docFr, "Salut"), "No Salut") + + homeEn := enSite.getPage(PageHome) + require.NotNil(t, homeEn) + require.Len(t, homeEn.Translations(), 3) + require.Equal(t, "fr", homeEn.Translations()[0].Lang()) + + }, + }, + // Change a shortcode + { + func(t *testing.T) { + writeSource(t, "layouts/shortcodes/shortcode.html", "Modified Shortcode: {{ i18n \"hello\" }}") + }, + []fsnotify.Event{ + {Name: "layouts/shortcodes/shortcode.html", Op: fsnotify.Write}, + }, + func(t *testing.T) { + require.Len(t, enSite.regularPages, 5) + require.Len(t, enSite.AllPages, 30) + require.Len(t, frSite.regularPages, 4) + assertFileContent(t, "public/fr/sect/doc1/index.html", true, "Single", "Modified Shortcode: Salut") + assertFileContent(t, "public/en/sect/doc1-slug/index.html", true, "Single", "Modified Shortcode: Hello") + }, + }, + } { + + if this.preFunc != nil { + this.preFunc(t) + } + + err = sites.Build(cfg, this.events...) + + if err != nil { + t.Fatalf("[%d] Failed to rebuild sites: %s", i, err) + } + + this.assertFunc(t) + } + + // Check that the drafts etc. are not built/processed/rendered. + assertShouldNotBuild(t, sites) + +} + +func assertShouldNotBuild(t *testing.T, sites *HugoSites) { + s := sites.Sites[0] + + for _, p := range s.rawAllPages { + // No HTML when not processed + require.Equal(t, p.shouldBuild(), bytes.Contains(p.rawContent, []byte("</")), p.BaseFileName()+": "+string(p.rawContent)) + require.Equal(t, p.shouldBuild(), p.Content != "", p.BaseFileName()) + + require.Equal(t, p.shouldBuild(), p.Content != "", p.BaseFileName()) + + filename := filepath.Join("public", p.TargetPath()) + if strings.HasSuffix(filename, ".html") { + // TODO(bep) the end result is correct, but it is weird that we cannot use targetPath directly here. + filename = strings.Replace(filename, ".html", "/index.html", 1) + } + + require.Equal(t, p.shouldBuild(), destinationExists(filename), filename) + } +} + +func TestAddNewLanguage(t *testing.T) { + testCommonResetState() + siteConfig := testSiteConfig{DefaultContentLanguage: "fr"} + + sites := createMultiTestSites(t, siteConfig, multiSiteTOMLConfigTemplate) + cfg := BuildCfg{} + + err := sites.Build(cfg) + + if err != nil { + t.Fatalf("Failed to build sites: %s", err) + } + + newConfig := multiSiteTOMLConfigTemplate + ` + +[Languages.sv] +weight = 15 +title = "Svenska" +` + + newConfig = createConfig(t, siteConfig, newConfig) + + writeNewContentFile(t, "Swedish Contentfile", "2016-01-01", "content/sect/doc1.sv.md", 10) + // replace the config + writeSource(t, "multilangconfig.toml", newConfig) + + // Watching does not work with in-memory fs, so we trigger a reload manually + require.NoError(t, viper.ReadInConfig()) + err = sites.Build(BuildCfg{CreateSitesFromConfig: true}) + + if err != nil { + t.Fatalf("Failed to rebuild sites: %s", err) + } + + require.Len(t, sites.Sites, 5, fmt.Sprintf("Len %d", len(sites.Sites))) + + // The Swedish site should be put in the middle (language weight=15) + enSite := sites.Sites[0] + svSite := sites.Sites[1] + frSite := sites.Sites[2] + require.True(t, enSite.Language.Lang == "en", enSite.Language.Lang) + require.True(t, svSite.Language.Lang == "sv", svSite.Language.Lang) + require.True(t, frSite.Language.Lang == "fr", frSite.Language.Lang) + + homeEn := enSite.getPage(PageHome) + require.NotNil(t, homeEn) + require.Len(t, homeEn.Translations(), 4) + require.Equal(t, "sv", homeEn.Translations()[0].Lang()) + + require.Len(t, enSite.regularPages, 4) + require.Len(t, frSite.regularPages, 3) + + // Veriy Swedish site + require.Len(t, svSite.regularPages, 1) + svPage := svSite.regularPages[0] + require.Equal(t, "Swedish Contentfile", svPage.Title) + require.Equal(t, "sv", svPage.Lang()) + require.Len(t, svPage.Translations(), 2) + require.Len(t, svPage.AllTranslations(), 3) + require.Equal(t, "en", svPage.Translations()[0].Lang()) + +} + +func TestChangeDefaultLanguage(t *testing.T) { + testCommonResetState() + viper.Set("defaultContentLanguageInSubdir", false) + + sites := createMultiTestSites(t, testSiteConfig{DefaultContentLanguage: "fr"}, multiSiteTOMLConfigTemplate) + cfg := BuildCfg{} + + err := sites.Build(cfg) + + if err != nil { + t.Fatalf("Failed to build sites: %s", err) + } + + assertFileContent(t, "public/sect/doc1/index.html", true, "Single", "Bonjour") + assertFileContent(t, "public/en/sect/doc2/index.html", true, "Single", "Hello") + + newConfig := createConfig(t, testSiteConfig{DefaultContentLanguage: "en"}, multiSiteTOMLConfigTemplate) + + // replace the config + writeSource(t, "multilangconfig.toml", newConfig) + + // Watching does not work with in-memory fs, so we trigger a reload manually + require.NoError(t, viper.ReadInConfig()) + err = sites.Build(BuildCfg{CreateSitesFromConfig: true}) + + if err != nil { + t.Fatalf("Failed to rebuild sites: %s", err) + } + + // Default language is now en, so that should now be the "root" language + assertFileContent(t, "public/fr/sect/doc1/index.html", true, "Single", "Bonjour") + assertFileContent(t, "public/sect/doc2/index.html", true, "Single", "Hello") +} + +func TestTableOfContentsInShortcodes(t *testing.T) { + testCommonResetState() + + sites := createMultiTestSites(t, testSiteConfig{DefaultContentLanguage: "en"}, multiSiteTOMLConfigTemplate) + + writeSource(t, "layouts/shortcodes/toc.html", tocShortcode) + writeSource(t, "content/post/simple.en.md", tocPageSimple) + writeSource(t, "content/post/withSCInHeading.en.md", tocPageWithShortcodesInHeadings) + + cfg := BuildCfg{} + + err := sites.Build(cfg) + + if err != nil { + t.Fatalf("Failed to build sites: %s", err) + } + + assertFileContent(t, "public/en/post/simple/index.html", true, tocPageSimpleExpected) + assertFileContent(t, "public/en/post/withSCInHeading/index.html", true, tocPageWithShortcodesInHeadingsExpected) +} + +var tocShortcode = ` +{{ .Page.TableOfContents }} +` + +var tocPageSimple = `--- +title: tocTest +publishdate: "2000-01-01" +--- + +{{< toc >}} + +# Heading 1 {#1} + +Some text. + +## Subheading 1.1 {#1-1} + +Some more text. + +# Heading 2 {#2} + +Even more text. + +## Subheading 2.1 {#2-1} + +Lorem ipsum... +` + +var tocPageSimpleExpected = `<nav id="TableOfContents"> +<ul> +<li><a href="#1">Heading 1</a> +<ul> +<li><a href="#1-1">Subheading 1.1</a></li> +</ul></li> +<li><a href="#2">Heading 2</a> +<ul> +<li><a href="#2-1">Subheading 2.1</a></li> +</ul></li> +</ul> +</nav>` + +var tocPageWithShortcodesInHeadings = `--- +title: tocTest +publishdate: "2000-01-01" +--- + +{{< toc >}} + +# Heading 1 {#1} + +Some text. + +## Subheading 1.1 {{< shortcode >}} {#1-1} + +Some more text. + +# Heading 2 {{% shortcode %}} {#2} + +Even more text. + +## Subheading 2.1 {#2-1} + +Lorem ipsum... +` + +var tocPageWithShortcodesInHeadingsExpected = `<nav id="TableOfContents"> +<ul> +<li><a href="#1">Heading 1</a> +<ul> +<li><a href="#1-1">Subheading 1.1 Shortcode: Hello</a></li> +</ul></li> +<li><a href="#2">Heading 2 Shortcode: Hello</a> +<ul> +<li><a href="#2-1">Subheading 2.1</a></li> +</ul></li> +</ul> +</nav>` + +var multiSiteTOMLConfigTemplate = ` +defaultExtension = "html" +baseURL = "http://example.com/blog" +disableSitemap = false +disableRSS = false +rssURI = "index.xml" + +paginate = 1 +defaultContentLanguage = "{{ .DefaultContentLanguage }}" + +[permalinks] +other = "/somewhere/else/:filename" + +[blackfriday] +angledQuotes = true + +[Taxonomies] +tag = "tags" + +[Languages] +[Languages.en] +weight = 10 +title = "In English" +languageName = "English" +[Languages.en.blackfriday] +angledQuotes = false +[[Languages.en.menu.main]] +url = "/" +name = "Home" +weight = 0 + +[Languages.fr] +weight = 20 +title = "Le Français" +languageName = "Français" +[Languages.fr.Taxonomies] +plaque = "plaques" + +[Languages.nn] +weight = 30 +title = "På nynorsk" +languageName = "Nynorsk" +paginatePath = "side" +[Languages.nn.Taxonomies] +lag = "lag" +[[Languages.nn.menu.main]] +url = "/" +name = "Heim" +weight = 1 + +[Languages.nb] +weight = 40 +title = "På bokmål" +languageName = "Bokmål" +paginatePath = "side" +[Languages.nb.Taxonomies] +lag = "lag" +` |