Example #1
0
func createSortTestPages(num int) Pages {
	pages := make(Pages, num)

	info := newSiteInfo(siteBuilderCfg{baseURL: "http://base", language: helpers.NewDefaultLanguage()})

	for i := 0; i < num; i++ {
		pages[i] = &Page{
			Node: Node{
				URLPath: URLPath{
					Section: "z",
					URL:     fmt.Sprintf("http://base/x/y/p%d.html", i),
				},
				Site: &info,
			},
			Source: Source{File: *source.NewFile(filepath.FromSlash(fmt.Sprintf("/x/y/p%d.md", i)))},
		}
		w := 5
		if i%2 == 0 {
			w = 10
		}
		pages[i].fuzzyWordCount = i
		pages[i].Weight = w
		pages[i].Description = "initial"
	}

	return pages
}
Example #2
0
func TestPageCount(t *testing.T) {
	testCommonResetState()
	hugofs.InitMemFs()

	viper.Set("uglyURLs", false)
	viper.Set("paginate", 10)
	s := &Site{
		Source:   &source.InMemorySource{ByteSource: urlFakeSource},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s, "indexes/blue.html", indexTemplate); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}
	_, err := hugofs.Destination().Open("public/blue")
	if err != nil {
		t.Errorf("No indexed rendered.")
	}

	for _, s := range []string{
		"public/sd1/foo/index.html",
		"public/sd2/index.html",
		"public/sd3/index.html",
		"public/sd4.html",
	} {
		if _, err := hugofs.Destination().Open(filepath.FromSlash(s)); err != nil {
			t.Errorf("No alias rendered: %s", s)
		}
	}
}
Example #3
0
func TestRobotsTXTOutput(t *testing.T) {
	testCommonResetState()

	hugofs.InitMemFs()

	viper.Set("baseurl", "http://auth/bub/")
	viper.Set("enableRobotsTXT", true)

	s := &Site{
		Source:   &source.InMemorySource{ByteSource: weightedSources},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s, "robots.txt", robotTxtTemplate); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	robotsFile, err := hugofs.Destination().Open("public/robots.txt")

	if err != nil {
		t.Fatalf("Unable to locate: robots.txt")
	}

	robots := helpers.ReaderToBytes(robotsFile)
	if !bytes.HasPrefix(robots, []byte("User-agent: Googlebot")) {
		t.Errorf("Robots file should start with 'User-agentL Googlebot'. %s", robots)
	}
}
Example #4
0
func TestSkipRender(t *testing.T) {
	testCommonResetState()

	hugofs.InitMemFs()
	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc1.html"), Content: []byte("---\nmarkup: markdown\n---\n# title\nsome *content*")},
		{Name: filepath.FromSlash("sect/doc2.html"), Content: []byte("<!doctype html><html><body>more content</body></html>")},
		{Name: filepath.FromSlash("sect/doc3.md"), Content: []byte("# doc3\n*some* content")},
		{Name: filepath.FromSlash("sect/doc4.md"), Content: []byte("---\ntitle: doc4\n---\n# doc4\n*some content*")},
		{Name: filepath.FromSlash("sect/doc5.html"), Content: []byte("<!doctype html><html>{{ template \"head\" }}<body>body5</body></html>")},
		{Name: filepath.FromSlash("sect/doc6.html"), Content: []byte("<!doctype html><html>{{ template \"head_abs\" }}<body>body5</body></html>")},
		{Name: filepath.FromSlash("doc7.html"), Content: []byte("<html><body>doc7 content</body></html>")},
		{Name: filepath.FromSlash("sect/doc8.html"), Content: []byte("---\nmarkup: md\n---\n# title\nsome *content*")},
	}

	viper.Set("defaultExtension", "html")
	viper.Set("verbose", true)
	viper.Set("canonifyURLs", true)
	viper.Set("baseURL", "http://auth/bub")
	s := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		targets:  targetList{page: &target.PagePub{UglyURLs: true}},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s,
		"_default/single.html", "{{.Content}}",
		"head", "<head><script src=\"script.js\"></script></head>",
		"head_abs", "<head><script src=\"/script.js\"></script></head>"); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	tests := []struct {
		doc      string
		expected string
	}{
		{filepath.FromSlash("sect/doc1.html"), "\n\n<h1 id=\"title\">title</h1>\n\n<p>some <em>content</em></p>\n"},
		{filepath.FromSlash("sect/doc2.html"), "<!doctype html><html><body>more content</body></html>"},
		{filepath.FromSlash("sect/doc3.html"), "\n\n<h1 id=\"doc3\">doc3</h1>\n\n<p><em>some</em> content</p>\n"},
		{filepath.FromSlash("sect/doc4.html"), "\n\n<h1 id=\"doc4\">doc4</h1>\n\n<p><em>some content</em></p>\n"},
		{filepath.FromSlash("sect/doc5.html"), "<!doctype html><html><head><script src=\"script.js\"></script></head><body>body5</body></html>"},
		{filepath.FromSlash("sect/doc6.html"), "<!doctype html><html><head><script src=\"http://auth/bub/script.js\"></script></head><body>body5</body></html>"},
		{filepath.FromSlash("doc7.html"), "<html><body>doc7 content</body></html>"},
		{filepath.FromSlash("sect/doc8.html"), "\n\n<h1 id=\"title\">title</h1>\n\n<p>some <em>content</em></p>\n"},
	}

	for _, test := range tests {
		file, err := hugofs.Destination().Open(test.doc)
		if err != nil {
			t.Fatalf("Did not find %s in target.", test.doc)
		}

		content := helpers.ReaderToString(file)

		if content != test.expected {
			t.Errorf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content)
		}
	}
}
Example #5
0
func TestDraftAndFutureRender(t *testing.T) {
	testCommonResetState()

	hugofs.InitMemFs()
	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc1.md"), Content: []byte("---\ntitle: doc1\ndraft: true\npublishdate: \"2414-05-29\"\n---\n# doc1\n*some content*")},
		{Name: filepath.FromSlash("sect/doc2.md"), Content: []byte("---\ntitle: doc2\ndraft: true\npublishdate: \"2012-05-29\"\n---\n# doc2\n*some content*")},
		{Name: filepath.FromSlash("sect/doc3.md"), Content: []byte("---\ntitle: doc3\ndraft: false\npublishdate: \"2414-05-29\"\n---\n# doc3\n*some content*")},
		{Name: filepath.FromSlash("sect/doc4.md"), Content: []byte("---\ntitle: doc4\ndraft: false\npublishdate: \"2012-05-29\"\n---\n# doc4\n*some content*")},
	}

	siteSetup := func(t *testing.T) *Site {
		s := &Site{
			Source:   &source.InMemorySource{ByteSource: sources},
			Language: helpers.NewDefaultLanguage(),
		}

		if err := buildSiteSkipRender(s); err != nil {
			t.Fatalf("Failed to build site: %s", err)
		}

		return s
	}

	viper.Set("baseURL", "http://auth/bub")

	// Testing Defaults.. Only draft:true and publishDate in the past should be rendered
	s := siteSetup(t)
	if len(s.AllPages) != 1 {
		t.Fatal("Draft or Future dated content published unexpectedly")
	}

	// only publishDate in the past should be rendered
	viper.Set("buildDrafts", true)
	s = siteSetup(t)
	if len(s.AllPages) != 2 {
		t.Fatal("Future Dated Posts published unexpectedly")
	}

	//  drafts should not be rendered, but all dates should
	viper.Set("buildDrafts", false)
	viper.Set("buildFuture", true)
	s = siteSetup(t)
	if len(s.AllPages) != 2 {
		t.Fatal("Draft posts published unexpectedly")
	}

	// all 4 should be included
	viper.Set("buildDrafts", true)
	viper.Set("buildFuture", true)
	s = siteSetup(t)
	if len(s.AllPages) != 4 {
		t.Fatal("Drafts or Future posts not included as expected")
	}

	//setting defaults back
	viper.Set("buildDrafts", false)
	viper.Set("buildFuture", false)
}
Example #6
0
func TestAbsURLify(t *testing.T) {
	testCommonResetState()

	viper.Set("defaultExtension", "html")

	hugofs.InitMemFs()
	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc1.html"), Content: []byte("<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>")},
		{Name: filepath.FromSlash("blue/doc2.html"), Content: []byte("---\nf: t\n---\n<!doctype html><html><body>more content</body></html>")},
	}
	for _, baseURL := range []string{"http://auth/bub", "http://base", "//base"} {
		for _, canonify := range []bool{true, false} {
			viper.Set("canonifyURLs", canonify)
			viper.Set("baseURL", baseURL)
			s := &Site{
				Source:   &source.InMemorySource{ByteSource: sources},
				targets:  targetList{page: &target.PagePub{UglyURLs: true}},
				Language: helpers.NewDefaultLanguage(),
			}
			t.Logf("Rendering with baseURL %q and canonifyURLs set %v", viper.GetString("baseURL"), canonify)

			if err := buildAndRenderSite(s, "blue/single.html", templateWithURLAbs); err != nil {
				t.Fatalf("Failed to build site: %s", err)
			}

			tests := []struct {
				file, expected string
			}{
				{"blue/doc2.html", "<a href=\"%s/foobar.jpg\">Going</a>"},
				{"sect/doc1.html", "<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>"},
			}

			for _, test := range tests {

				file, err := hugofs.Destination().Open(filepath.FromSlash(test.file))
				if err != nil {
					t.Fatalf("Unable to locate rendered content: %s", test.file)
				}

				content := helpers.ReaderToString(file)

				expected := test.expected

				if strings.Contains(expected, "%s") {
					expected = fmt.Sprintf(expected, baseURL)
				}

				if !canonify {
					expected = strings.Replace(expected, baseURL, "", -1)
				}

				if content != expected {
					t.Errorf("AbsURLify with baseURL %q content expected:\n%q\ngot\n%q", baseURL, expected, content)
				}
			}
		}
	}
}
Example #7
0
func createTestSite(pageSources []source.ByteSource) *Site {
	hugofs.InitMemFs()

	return &Site{
		Source:   &source.InMemorySource{ByteSource: pageSources},
		Language: helpers.NewDefaultLanguage(),
	}

}
Example #8
0
func loadDefaultSettings() {
	viper.SetDefault("cleanDestinationDir", false)
	viper.SetDefault("watch", false)
	viper.SetDefault("metaDataFormat", "toml")
	viper.SetDefault("disable404", false)
	viper.SetDefault("disableRSS", false)
	viper.SetDefault("disableSitemap", false)
	viper.SetDefault("disableRobotsTXT", false)
	viper.SetDefault("contentDir", "content")
	viper.SetDefault("layoutDir", "layouts")
	viper.SetDefault("staticDir", "static")
	viper.SetDefault("archetypeDir", "archetypes")
	viper.SetDefault("publishDir", "public")
	viper.SetDefault("dataDir", "data")
	viper.SetDefault("i18nDir", "i18n")
	viper.SetDefault("themesDir", "themes")
	viper.SetDefault("defaultLayout", "post")
	viper.SetDefault("buildDrafts", false)
	viper.SetDefault("buildFuture", false)
	viper.SetDefault("buildExpired", false)
	viper.SetDefault("uglyURLs", false)
	viper.SetDefault("verbose", false)
	viper.SetDefault("ignoreCache", false)
	viper.SetDefault("canonifyURLs", false)
	viper.SetDefault("relativeURLs", false)
	viper.SetDefault("removePathAccents", false)
	viper.SetDefault("taxonomies", map[string]string{"tag": "tags", "category": "categories"})
	viper.SetDefault("permalinks", make(PermalinkOverrides, 0))
	viper.SetDefault("sitemap", Sitemap{Priority: -1, Filename: "sitemap.xml"})
	viper.SetDefault("defaultExtension", "html")
	viper.SetDefault("pygmentsStyle", "monokai")
	viper.SetDefault("pygmentsUseClasses", false)
	viper.SetDefault("pygmentsCodeFences", false)
	viper.SetDefault("pygmentsOptions", "")
	viper.SetDefault("disableLiveReload", false)
	viper.SetDefault("pluralizeListTitles", true)
	viper.SetDefault("preserveTaxonomyNames", false)
	viper.SetDefault("forceSyncStatic", false)
	viper.SetDefault("footnoteAnchorPrefix", "")
	viper.SetDefault("footnoteReturnLinkContents", "")
	viper.SetDefault("newContentEditor", "")
	viper.SetDefault("paginate", 10)
	viper.SetDefault("paginatePath", "page")
	viper.SetDefault("blackfriday", helpers.NewBlackfriday(viper.GetViper()))
	viper.SetDefault("rSSUri", "index.xml")
	viper.SetDefault("sectionPagesMenu", "")
	viper.SetDefault("disablePathToLower", false)
	viper.SetDefault("hasCJKLanguage", false)
	viper.SetDefault("enableEmoji", false)
	viper.SetDefault("pygmentsCodeFencesGuessSyntax", false)
	viper.SetDefault("useModTimeAsFallback", false)
	viper.SetDefault("currentContentLanguage", helpers.NewDefaultLanguage())
	viper.SetDefault("defaultContentLanguage", "en")
	viper.SetDefault("defaultContentLanguageInSubdir", false)
	viper.SetDefault("enableMissingTranslationPlaceholders", false)
	viper.SetDefault("enableGitInfo", false)
}
Example #9
0
func TestOrderedPages(t *testing.T) {
	testCommonResetState()

	hugofs.InitMemFs()

	viper.Set("baseURL", "http://auth/bub")
	s := &Site{
		Source:   &source.InMemorySource{ByteSource: weightedSources},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildSiteSkipRender(s); err != nil {
		t.Fatalf("Failed to process site: %s", err)
	}

	if s.Sections["sect"][0].Weight != 2 || s.Sections["sect"][3].Weight != 6 {
		t.Errorf("Pages in unexpected order. First should be '%d', got '%d'", 2, s.Sections["sect"][0].Weight)
	}

	if s.Sections["sect"][1].Page.Title != "Three" || s.Sections["sect"][2].Page.Title != "Four" {
		t.Errorf("Pages in unexpected order. Second should be '%s', got '%s'", "Three", s.Sections["sect"][1].Page.Title)
	}

	bydate := s.Pages.ByDate()

	if bydate[0].Title != "One" {
		t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "One", bydate[0].Title)
	}

	rev := bydate.Reverse()
	if rev[0].Title != "Three" {
		t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "Three", rev[0].Title)
	}

	bypubdate := s.Pages.ByPublishDate()

	if bypubdate[0].Title != "One" {
		t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "One", bypubdate[0].Title)
	}

	rbypubdate := bypubdate.Reverse()
	if rbypubdate[0].Title != "Three" {
		t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "Three", rbypubdate[0].Title)
	}

	bylength := s.Pages.ByLength()
	if bylength[0].Title != "One" {
		t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "One", bylength[0].Title)
	}

	rbylength := bylength.Reverse()
	if rbylength[0].Title != "Four" {
		t.Errorf("Pages in unexpected order. First should be '%s', got '%s'", "Four", rbylength[0].Title)
	}
}
Example #10
0
func newMultiLingualFromSites(sites ...*Site) (*Multilingual, error) {
	languages := make(helpers.Languages, len(sites))

	for i, s := range sites {
		if s.Language == nil {
			return nil, errors.New("Missing language for site")
		}
		languages[i] = s.Language
	}

	return &Multilingual{Languages: languages, DefaultLang: helpers.NewDefaultLanguage()}, nil

}
Example #11
0
func setupLinkingMockSite(t *testing.T) *Site {
	hugofs.InitMemFs()
	sources := []source.ByteSource{
		{Name: filepath.FromSlash("index.md"), Content: []byte("")},
		{Name: filepath.FromSlash("rootfile.md"), Content: []byte("")},
		{Name: filepath.FromSlash("root-image.png"), Content: []byte("")},

		{Name: filepath.FromSlash("level2/2-root.md"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/index.md"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/common.md"), Content: []byte("")},

		//		{Name: filepath.FromSlash("level2b/2b-root.md"), Content: []byte("")},
		//		{Name: filepath.FromSlash("level2b/index.md"), Content: []byte("")},
		//		{Name: filepath.FromSlash("level2b/common.md"), Content: []byte("")},

		{Name: filepath.FromSlash("level2/2-image.png"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/common.png"), Content: []byte("")},

		{Name: filepath.FromSlash("level2/level3/3-root.md"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/level3/index.md"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/level3/common.md"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/level3/3-image.png"), Content: []byte("")},
		{Name: filepath.FromSlash("level2/level3/common.png"), Content: []byte("")},
	}

	viper.Set("baseurl", "http://auth/")
	viper.Set("DefaultExtension", "html")
	viper.Set("UglyURLs", false)
	viper.Set("PluralizeListTitles", false)
	viper.Set("CanonifyURLs", false)
	viper.Set("blackfriday",
		// TODO(bep) see https://github.com/spf13/viper/issues/261
		map[string]interface{}{
			strings.ToLower("sourceRelativeLinksProjectFolder"): "/docs"})

	site := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildSiteSkipRender(site); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	return site
}
Example #12
0
func TestPagePaths(t *testing.T) {
	testCommonResetState()

	viper.Set("defaultExtension", "html")
	siteParmalinksSetting := PermalinkOverrides{
		"post": ":year/:month/:day/:title/",
	}

	tests := []struct {
		content      string
		path         string
		hasPermalink bool
		expected     string
	}{
		{simplePage, "content/post/x.md", false, "content/post/x.html"},
		{simplePageWithURL, "content/post/x.md", false, "simple/url/index.html"},
		{simplePageWithSlug, "content/post/x.md", false, "content/post/simple-slug.html"},
		{simplePageWithDate, "content/post/x.md", true, "2013/10/15/simple/index.html"},
		{UTF8Page, "content/post/x.md", false, "content/post/x.html"},
		{UTF8PageWithURL, "content/post/x.md", false, "ラーメン/url/index.html"},
		{UTF8PageWithSlug, "content/post/x.md", false, "content/post/ラーメン-slug.html"},
		{UTF8PageWithDate, "content/post/x.md", true, "2013/10/15/ラーメン/index.html"},
	}

	for _, test := range tests {
		p, _ := NewPageFrom(strings.NewReader(test.content), filepath.FromSlash(test.path))
		info := newSiteInfo(siteBuilderCfg{language: helpers.NewDefaultLanguage()})
		p.Node.Site = &info

		if test.hasPermalink {
			p.Node.Site.Permalinks = siteParmalinksSetting
		}

		expectedTargetPath := filepath.FromSlash(test.expected)
		expectedFullFilePath := filepath.FromSlash(test.path)

		if p.TargetPath() != expectedTargetPath {
			t.Errorf("%s => TargetPath  expected: '%s', got: '%s'", test.content, expectedTargetPath, p.TargetPath())
		}

		if p.FullFilePath() != expectedFullFilePath {
			t.Errorf("%s => FullFilePath  expected: '%s', got: '%s'", test.content, expectedFullFilePath, p.FullFilePath())
		}
	}
}
Example #13
0
func TestSitemapOutput(t *testing.T) {
	testCommonResetState()

	viper.Set("baseurl", "http://auth/bub/")

	s := &Site{
		Source:   &source.InMemorySource{ByteSource: weightedSources},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s, "sitemap.xml", SITEMAP_TEMPLATE); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	sitemapContent := readDestination(t, "public/sitemap.xml")

	if !strings.HasPrefix(sitemapContent, "<?xml") {
		t.Errorf("Sitemap file should start with <?xml. %s", sitemapContent)
	}
}
Example #14
0
func TestFutureExpirationRender(t *testing.T) {
	testCommonResetState()

	hugofs.InitMemFs()
	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc3.md"), Content: []byte("---\ntitle: doc1\nexpirydate: \"2400-05-29\"\n---\n# doc1\n*some content*")},
		{Name: filepath.FromSlash("sect/doc4.md"), Content: []byte("---\ntitle: doc2\nexpirydate: \"2000-05-29\"\n---\n# doc2\n*some content*")},
	}

	siteSetup := func(t *testing.T) *Site {
		s := &Site{
			Source:   &source.InMemorySource{ByteSource: sources},
			Language: helpers.NewDefaultLanguage(),
		}

		if err := buildSiteSkipRender(s); err != nil {
			t.Fatalf("Failed to build site: %s", err)
		}

		return s
	}

	viper.Set("baseURL", "http://auth/bub")

	s := siteSetup(t)

	if len(s.AllPages) != 1 {
		if len(s.AllPages) > 1 {
			t.Fatal("Expired content published unexpectedly")
		}

		if len(s.AllPages) < 1 {
			t.Fatal("Valid content expired unexpectedly")
		}
	}

	if s.AllPages[0].Title == "doc2" {
		t.Fatal("Expired content published unexpectedly")
	}
}
Example #15
0
func TestPermalinkExpansion(t *testing.T) {
	page, err := NewPageFrom(strings.NewReader(simplePageJSON), "blue/test-page.md")
	info := newSiteInfo(siteBuilderCfg{language: helpers.NewDefaultLanguage()})
	page.Site = &info
	if err != nil {
		t.Fatalf("failed before we began, could not parse SIMPLE_PAGE_JSON: %s", err)
	}
	for _, item := range testdataPermalinks {
		if !item.valid {
			continue
		}
		pp := pathPattern(item.spec)
		result, err := pp.Expand(page)
		if err != nil {
			t.Errorf("failed to expand page: %s", err)
			continue
		}
		if result != item.expandsTo {
			t.Errorf("expansion mismatch!\n\tExpected: %q\n\tReceived: %q", item.expandsTo, result)
		}
	}
}
Example #16
0
func TestWeightedTaxonomies(t *testing.T) {
	testCommonResetState()

	hugofs.InitMemFs()
	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc1.md"), Content: pageWithWeightedTaxonomies2},
		{Name: filepath.FromSlash("sect/doc2.md"), Content: pageWithWeightedTaxonomies1},
		{Name: filepath.FromSlash("sect/doc3.md"), Content: pageWithWeightedTaxonomies3},
	}
	taxonomies := make(map[string]string)

	taxonomies["tag"] = "tags"
	taxonomies["category"] = "categories"

	viper.Set("baseURL", "http://auth/bub")
	viper.Set("taxonomies", taxonomies)
	s := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildSiteSkipRender(s); err != nil {
		t.Fatalf("Failed to process site: %s", err)
	}

	if s.Taxonomies["tags"]["a"][0].Page.Title != "foo" {
		t.Errorf("Pages in unexpected order, 'foo' expected first, got '%v'", s.Taxonomies["tags"]["a"][0].Page.Title)
	}

	if s.Taxonomies["categories"]["d"][0].Page.Title != "bar" {
		t.Errorf("Pages in unexpected order, 'bar' expected first, got '%v'", s.Taxonomies["categories"]["d"][0].Page.Title)
	}

	if s.Taxonomies["categories"]["e"][0].Page.Title != "bza" {
		t.Errorf("Pages in unexpected order, 'bza' expected first, got '%v'", s.Taxonomies["categories"]["e"][0].Page.Title)
	}
}
Example #17
0
func _TestPageTargetUgly(t *testing.T) {
	testCommonResetState()

	viper.Set("DefaultExtension", "html")
	viper.Set("UglyURLs", true)

	s := &Site{
		targets:  targetList{page: &target.PagePub{UglyURLs: true, PublishDir: "public"}},
		Source:   &source.InMemorySource{ByteSource: fakeSource},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	expected := "foo/bar/file.md (renderer: markdown)\n canonical => public/foo/bar/file.html\n\n" +
		"alias/test/file1.md (renderer: markdown)\n" +
		" canonical => public/alias/test/file1.html\n" +
		" alias1/ => public/alias1/index.html\n" +
		" alias-2/ => public/alias-2/index.html\n\n" +
		"public/section/somecontent.html (renderer: n/a)\n canonical => public/section/somecontent.html\n\n"
	checkShowPlanExpected(t, s, expected)
}
Example #18
0
func createSitesFromConfig() ([]*Site, error) {
	var sites []*Site
	multilingual := viper.GetStringMap("Languages")
	if len(multilingual) == 0 {
		sites = append(sites, newSite(helpers.NewDefaultLanguage()))
	}

	if len(multilingual) > 0 {
		var err error

		languages, err := toSortedLanguages(multilingual)

		if err != nil {
			return nil, fmt.Errorf("Failed to parse multilingual config: %s", err)
		}

		for _, lang := range languages {
			sites = append(sites, newSite(lang))
		}

	}

	return sites, nil
}
Example #19
0
func newMultiLingualDefaultLanguage() *Multilingual {
	return newMultiLingualForLanguage(helpers.NewDefaultLanguage())
}
Example #20
0
func doTestCrossrefs(t *testing.T, relative, uglyURLs bool) {
	testCommonResetState()

	baseURL := "http://foo/bar"
	viper.Set("defaultExtension", "html")
	viper.Set("baseURL", baseURL)
	viper.Set("uglyURLs", uglyURLs)
	viper.Set("verbose", true)

	var refShortcode string
	var expectedBase string
	var expectedURLSuffix string
	var expectedPathSuffix string

	if relative {
		refShortcode = "relref"
		expectedBase = "/bar"
	} else {
		refShortcode = "ref"
		expectedBase = baseURL
	}

	if uglyURLs {
		expectedURLSuffix = ".html"
		expectedPathSuffix = ".html"
	} else {
		expectedURLSuffix = "/"
		expectedPathSuffix = "/index.html"
	}

	sources := []source.ByteSource{
		{
			Name:    filepath.FromSlash("sect/doc1.md"),
			Content: []byte(fmt.Sprintf(`Ref 2: {{< %s "sect/doc2.md" >}}`, refShortcode)),
		},
		// Issue #1148: Make sure that no P-tags is added around shortcodes.
		{
			Name: filepath.FromSlash("sect/doc2.md"),
			Content: []byte(fmt.Sprintf(`**Ref 1:**

{{< %s "sect/doc1.md" >}}

THE END.`, refShortcode)),
		},
		// Issue #1753: Should not add a trailing newline after shortcode.
		{
			Name:    filepath.FromSlash("sect/doc3.md"),
			Content: []byte(fmt.Sprintf(`**Ref 1:**{{< %s "sect/doc3.md" >}}.`, refShortcode)),
		},
	}

	s := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		targets:  targetList{page: &target.PagePub{UglyURLs: uglyURLs}},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s, "_default/single.html", "{{.Content}}"); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	if len(s.AllPages) != 3 {
		t.Fatalf("Expected 3 got %d pages", len(s.AllPages))
	}

	tests := []struct {
		doc      string
		expected string
	}{
		{filepath.FromSlash(fmt.Sprintf("sect/doc1%s", expectedPathSuffix)), fmt.Sprintf("<p>Ref 2: %s/sect/doc2%s</p>\n", expectedBase, expectedURLSuffix)},
		{filepath.FromSlash(fmt.Sprintf("sect/doc2%s", expectedPathSuffix)), fmt.Sprintf("<p><strong>Ref 1:</strong></p>\n\n%s/sect/doc1%s\n\n<p>THE END.</p>\n", expectedBase, expectedURLSuffix)},
		{filepath.FromSlash(fmt.Sprintf("sect/doc3%s", expectedPathSuffix)), fmt.Sprintf("<p><strong>Ref 1:</strong>%s/sect/doc3%s.</p>\n", expectedBase, expectedURLSuffix)},
	}

	for _, test := range tests {
		file, err := hugofs.Destination().Open(test.doc)

		if err != nil {
			t.Fatalf("Did not find %s in target: %s", test.doc, err)
		}

		content := helpers.ReaderToString(file)

		if content != test.expected {
			t.Fatalf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content)
		}
	}

}
Example #21
0
func doTestShouldAlwaysHaveUglyURLs(t *testing.T, uglyURLs bool) {
	testCommonResetState()

	viper.Set("defaultExtension", "html")
	viper.Set("verbose", true)
	viper.Set("baseURL", "http://auth/bub")
	viper.Set("disableSitemap", false)
	viper.Set("disableRSS", false)
	viper.Set("rssURI", "index.xml")
	viper.Set("blackfriday",
		map[string]interface{}{
			"plainIDAnchors": true})

	viper.Set("uglyURLs", uglyURLs)

	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc1.md"), Content: []byte("---\nmarkup: markdown\n---\n# title\nsome *content*")},
		{Name: filepath.FromSlash("sect/doc2.md"), Content: []byte("---\nurl: /ugly.html\nmarkup: markdown\n---\n# title\ndoc2 *content*")},
	}

	s := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		targets:  targetList{page: &target.PagePub{UglyURLs: uglyURLs, PublishDir: "public"}},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s,
		"index.html", "Home Sweet {{ if.IsHome  }}Home{{ end }}.",
		"_default/single.html", "{{.Content}}{{ if.IsHome  }}This is not home!{{ end }}",
		"404.html", "Page Not Found.{{ if.IsHome  }}This is not home!{{ end }}",
		"rss.xml", "<root>RSS</root>",
		"sitemap.xml", "<root>SITEMAP</root>"); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	var expectedPagePath string
	if uglyURLs {
		expectedPagePath = "public/sect/doc1.html"
	} else {
		expectedPagePath = "public/sect/doc1/index.html"
	}

	tests := []struct {
		doc      string
		expected string
	}{
		{filepath.FromSlash("public/index.html"), "Home Sweet Home."},
		{filepath.FromSlash(expectedPagePath), "\n\n<h1 id=\"title\">title</h1>\n\n<p>some <em>content</em></p>\n"},
		{filepath.FromSlash("public/404.html"), "Page Not Found."},
		{filepath.FromSlash("public/index.xml"), "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n<root>RSS</root>"},
		{filepath.FromSlash("public/sitemap.xml"), "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n<root>SITEMAP</root>"},
		// Issue #1923
		{filepath.FromSlash("public/ugly.html"), "\n\n<h1 id=\"title\">title</h1>\n\n<p>doc2 <em>content</em></p>\n"},
	}

	for _, p := range s.Pages {
		assert.False(t, p.IsHome)
	}

	for _, test := range tests {
		content := readDestination(t, test.doc)

		if content != test.expected {
			t.Errorf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content)
		}
	}

}
Example #22
0
func newHugoSitesDefaultLanguage() (*HugoSites, error) {
	return newHugoSitesFromSourceAndLanguages(nil, helpers.Languages{helpers.NewDefaultLanguage()})
}
Example #23
0
func doTestSectionNaming(t *testing.T, canonify, uglify, pluralize bool) {
	hugofs.InitMemFs()
	testCommonResetState()

	viper.Set("baseURL", "http://auth/sub/")
	viper.Set("defaultExtension", "html")
	viper.Set("uglyURLs", uglify)
	viper.Set("pluralizeListTitles", pluralize)
	viper.Set("canonifyURLs", canonify)

	var expectedPathSuffix string

	if uglify {
		expectedPathSuffix = ".html"
	} else {
		expectedPathSuffix = "/index.html"
	}

	sources := []source.ByteSource{
		{Name: filepath.FromSlash("sect/doc1.html"), Content: []byte("doc1")},
		{Name: filepath.FromSlash("Fish and Chips/doc2.html"), Content: []byte("doc2")},
		{Name: filepath.FromSlash("ラーメン/doc3.html"), Content: []byte("doc3")},
	}

	s := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		targets:  targetList{page: &target.PagePub{UglyURLs: uglify}},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildAndRenderSite(s,
		"_default/single.html", "{{.Content}}",
		"_default/list.html", "{{ .Title }}"); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	tests := []struct {
		doc         string
		pluralAware bool
		expected    string
	}{
		{filepath.FromSlash(fmt.Sprintf("sect/doc1%s", expectedPathSuffix)), false, "doc1"},
		{filepath.FromSlash(fmt.Sprintf("sect%s", expectedPathSuffix)), true, "Sect"},
		{filepath.FromSlash(fmt.Sprintf("fish-and-chips/doc2%s", expectedPathSuffix)), false, "doc2"},
		{filepath.FromSlash(fmt.Sprintf("fish-and-chips%s", expectedPathSuffix)), true, "Fish and Chips"},
		{filepath.FromSlash(fmt.Sprintf("ラーメン/doc3%s", expectedPathSuffix)), false, "doc3"},
		{filepath.FromSlash(fmt.Sprintf("ラーメン%s", expectedPathSuffix)), true, "ラーメン"},
	}

	for _, test := range tests {
		file, err := hugofs.Destination().Open(test.doc)
		if err != nil {
			t.Fatalf("Did not find %s in target: %s", test.doc, err)
		}

		content := helpers.ReaderToString(file)

		if test.pluralAware && pluralize {
			test.expected = inflect.Pluralize(test.expected)
		}

		if content != test.expected {
			t.Errorf("%s content expected:\n%q\ngot:\n%q", test.doc, test.expected, content)
		}
	}

}
Example #24
0
func TestShortcodesInSite(t *testing.T) {
	testCommonResetState()

	baseURL := "http://foo/bar"
	viper.Set("DefaultExtension", "html")
	viper.Set("DefaultContentLanguage", "en")
	viper.Set("baseurl", baseURL)
	viper.Set("UglyURLs", false)
	viper.Set("verbose", true)

	viper.Set("pygmentsuseclasses", true)
	viper.Set("pygmentscodefences", true)

	tests := []struct {
		contentPath string
		content     string
		outFile     string
		expected    string
	}{
		{"sect/doc1.md", `a{{< b >}}c`,
			filepath.FromSlash("sect/doc1/index.html"), "<p>abc</p>\n"},
		// Issue #1642: Multiple shortcodes wrapped in P
		// Deliberately forced to pass even if they maybe shouldn't.
		{"sect/doc2.md", `a

{{< b >}}		
{{< c >}}
{{< d >}}

e`,
			filepath.FromSlash("sect/doc2/index.html"),
			"<p>a</p>\n\n<p>b<br />\nc\nd</p>\n\n<p>e</p>\n"},
		{"sect/doc3.md", `a

{{< b >}}		
{{< c >}}

{{< d >}}

e`,
			filepath.FromSlash("sect/doc3/index.html"),
			"<p>a</p>\n\n<p>b<br />\nc</p>\n\nd\n\n<p>e</p>\n"},
		{"sect/doc4.md", `a
{{< b >}}
{{< b >}}
{{< b >}}
{{< b >}}
{{< b >}}










`,
			filepath.FromSlash("sect/doc4/index.html"),
			"<p>a\nb\nb\nb\nb\nb</p>\n"},
		// #2192 #2209: Shortcodes in markdown headers
		{"sect/doc5.md", `# {{< b >}}	
## {{% c %}}`,
			filepath.FromSlash("sect/doc5/index.html"), "\n\n<h1 id=\"hahahugoshortcode-1hbhb\">b</h1>\n\n<h2 id=\"hahahugoshortcode-2hbhb\">c</h2>\n"},
		// #2223 pygments
		{"sect/doc6.md", "\n```bash\nb: {{< b >}} c: {{% c %}}\n```\n",
			filepath.FromSlash("sect/doc6/index.html"),
			"b: b c: c\n</code></pre></div>\n"},
		// #2249
		{"sect/doc7.ad", `_Shortcodes:_ *b: {{< b >}} c: {{% c %}}*`,
			filepath.FromSlash("sect/doc7/index.html"),
			"<div class=\"paragraph\">\n<p><em>Shortcodes:</em> <strong>b: b c: c</strong></p>\n</div>\n"},
		{"sect/doc8.rst", `**Shortcodes:** *b: {{< b >}} c: {{% c %}}*`,
			filepath.FromSlash("sect/doc8/index.html"),
			"<div class=\"document\">\n\n\n<p><strong>Shortcodes:</strong> <em>b: b c: c</em></p>\n</div>"},
		{"sect/doc9.mmark", `
---
menu:
  main:
    parent: 'parent'
---
**Shortcodes:** *b: {{< b >}} c: {{% c %}}*`,
			filepath.FromSlash("sect/doc9/index.html"),
			"<p><strong>Shortcodes:</strong> <em>b: b c: c</em></p>\n"},
		// Issue #1229: Menus not available in shortcode.
		{"sect/doc10.md", `---
menu:
  main:
    identifier: 'parent'
tags:
- Menu
---
**Menus:** {{< menu >}}`,
			filepath.FromSlash("sect/doc10/index.html"),
			"<p><strong>Menus:</strong> 1</p>\n"},
		// Issue #2323: Taxonomies not available in shortcode.
		{"sect/doc11.md", `---
tags:
- Bugs
---
**Tags:** {{< tags >}}`,
			filepath.FromSlash("sect/doc11/index.html"),
			"<p><strong>Tags:</strong> 2</p>\n"},
	}

	sources := make([]source.ByteSource, len(tests))

	for i, test := range tests {
		sources[i] = source.ByteSource{Name: filepath.FromSlash(test.contentPath), Content: []byte(test.content)}
	}

	s := &Site{
		Source:   &source.InMemorySource{ByteSource: sources},
		targets:  targetList{page: &target.PagePub{UglyURLs: false}},
		Language: helpers.NewDefaultLanguage(),
	}

	addTemplates := func(templ tpl.Template) error {
		templ.AddTemplate("_default/single.html", "{{.Content}}")

		templ.AddInternalShortcode("b.html", `b`)
		templ.AddInternalShortcode("c.html", `c`)
		templ.AddInternalShortcode("d.html", `d`)
		templ.AddInternalShortcode("menu.html", `{{ len (index .Page.Menus "main").Children }}`)
		templ.AddInternalShortcode("tags.html", `{{ len .Page.Site.Taxonomies.tags }}`)

		return nil

	}

	sites, err := newHugoSites(s)

	if err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	if err = sites.Build(BuildCfg{withTemplate: addTemplates}); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	for _, test := range tests {
		if strings.HasSuffix(test.contentPath, ".ad") && !helpers.HasAsciidoc() {
			fmt.Println("Skip Asciidoc test case as no Asciidoc present.")
			continue
		} else if strings.HasSuffix(test.contentPath, ".rst") && !helpers.HasRst() {
			fmt.Println("Skip Rst test case as no rst2html present.")
			continue
		} else if strings.Contains(test.expected, "code") && !helpers.HasPygments() {
			fmt.Println("Skip Pygments test case as no pygments present.")
			continue
		}

		file, err := hugofs.Destination().Open(test.outFile)

		if err != nil {
			t.Fatalf("Did not find %s in target: %s", test.outFile, err)
		}

		content := helpers.ReaderToString(file)

		if !strings.Contains(content, test.expected) {
			t.Fatalf("%s content expected:\n%q\ngot:\n%q", test.outFile, test.expected, content)
		}
	}

}
Example #25
0
func TestGroupedPages(t *testing.T) {
	testCommonResetState()

	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered in f", r)
		}
	}()

	hugofs.InitMemFs()

	viper.Set("baseURL", "http://auth/bub")
	s := &Site{
		Source:   &source.InMemorySource{ByteSource: groupedSources},
		Language: helpers.NewDefaultLanguage(),
	}

	if err := buildSiteSkipRender(s); err != nil {
		t.Fatalf("Failed to build site: %s", err)
	}

	rbysection, err := s.Pages.GroupBy("Section", "desc")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if rbysection[0].Key != "sect3" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "sect3", rbysection[0].Key)
	}
	if rbysection[1].Key != "sect2" {
		t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "sect2", rbysection[1].Key)
	}
	if rbysection[2].Key != "sect1" {
		t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "sect1", rbysection[2].Key)
	}
	if rbysection[0].Pages[0].Title != "Four" {
		t.Errorf("PageGroup has an unexpected page. First group's pages should have '%s', got '%s'", "Four", rbysection[0].Pages[0].Title)
	}
	if len(rbysection[2].Pages) != 2 {
		t.Errorf("PageGroup has unexpected number of pages. Third group should have '%d' pages, got '%d' pages", 2, len(rbysection[2].Pages))
	}

	bytype, err := s.Pages.GroupBy("Type", "asc")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if bytype[0].Key != "sect1" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "sect1", bytype[0].Key)
	}
	if bytype[1].Key != "sect2" {
		t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "sect2", bytype[1].Key)
	}
	if bytype[2].Key != "sect3" {
		t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "sect3", bytype[2].Key)
	}
	if bytype[2].Pages[0].Title != "Four" {
		t.Errorf("PageGroup has an unexpected page. Third group's data should have '%s', got '%s'", "Four", bytype[0].Pages[0].Title)
	}
	if len(bytype[0].Pages) != 2 {
		t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(bytype[2].Pages))
	}

	bydate, err := s.Pages.GroupByDate("2006-01", "asc")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if bydate[0].Key != "0001-01" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "0001-01", bydate[0].Key)
	}
	if bydate[1].Key != "2012-01" {
		t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "2012-01", bydate[1].Key)
	}
	if bydate[2].Key != "2012-04" {
		t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "2012-04", bydate[2].Key)
	}
	if bydate[2].Pages[0].Title != "Three" {
		t.Errorf("PageGroup has an unexpected page. Third group's pages should have '%s', got '%s'", "Three", bydate[2].Pages[0].Title)
	}
	if len(bydate[0].Pages) != 2 {
		t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(bydate[2].Pages))
	}

	bypubdate, err := s.Pages.GroupByPublishDate("2006")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if bypubdate[0].Key != "2012" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "2012", bypubdate[0].Key)
	}
	if bypubdate[1].Key != "0001" {
		t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "0001", bypubdate[1].Key)
	}
	if bypubdate[0].Pages[0].Title != "Three" {
		t.Errorf("PageGroup has an unexpected page. Third group's pages should have '%s', got '%s'", "Three", bypubdate[0].Pages[0].Title)
	}
	if len(bypubdate[0].Pages) != 3 {
		t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 3, len(bypubdate[0].Pages))
	}

	byparam, err := s.Pages.GroupByParam("my_param", "desc")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if byparam[0].Key != "foo" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "foo", byparam[0].Key)
	}
	if byparam[1].Key != "baz" {
		t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "baz", byparam[1].Key)
	}
	if byparam[2].Key != "bar" {
		t.Errorf("PageGroup array in unexpected order. Third group key should be '%s', got '%s'", "bar", byparam[2].Key)
	}
	if byparam[2].Pages[0].Title != "Three" {
		t.Errorf("PageGroup has an unexpected page. Third group's pages should have '%s', got '%s'", "Three", byparam[2].Pages[0].Title)
	}
	if len(byparam[0].Pages) != 2 {
		t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(byparam[0].Pages))
	}

	_, err = s.Pages.GroupByParam("not_exist")
	if err == nil {
		t.Errorf("GroupByParam didn't return an expected error")
	}

	byOnlyOneParam, err := s.Pages.GroupByParam("only_one")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if len(byOnlyOneParam) != 1 {
		t.Errorf("PageGroup array has unexpected elements. Group length should be '%d', got '%d'", 1, len(byOnlyOneParam))
	}
	if byOnlyOneParam[0].Key != "yes" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "yes", byOnlyOneParam[0].Key)
	}

	byParamDate, err := s.Pages.GroupByParamDate("my_date", "2006-01")
	if err != nil {
		t.Fatalf("Unable to make PageGroup array: %s", err)
	}
	if byParamDate[0].Key != "2010-05" {
		t.Errorf("PageGroup array in unexpected order. First group key should be '%s', got '%s'", "2010-05", byParamDate[0].Key)
	}
	if byParamDate[1].Key != "1979-05" {
		t.Errorf("PageGroup array in unexpected order. Second group key should be '%s', got '%s'", "1979-05", byParamDate[1].Key)
	}
	if byParamDate[1].Pages[0].Title != "One" {
		t.Errorf("PageGroup has an unexpected page. Second group's pages should have '%s', got '%s'", "One", byParamDate[1].Pages[0].Title)
	}
	if len(byParamDate[0].Pages) != 2 {
		t.Errorf("PageGroup has unexpected number of pages. First group should have '%d' pages, got '%d' pages", 2, len(byParamDate[2].Pages))
	}
}
func TestPermalink(t *testing.T) {
	testCommonResetState()

	tests := []struct {
		file         string
		base         template.URL
		slug         string
		url          string
		uglyURLs     bool
		canonifyURLs bool
		expectedAbs  string
		expectedRel  string
	}{
		{"x/y/z/boofar.md", "", "", "", false, false, "/x/y/z/boofar/", "/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "", "", "", false, false, "/x/y/z/boofar/", "/x/y/z/boofar/"},
		// Issue #1174
		{"x/y/z/boofar.md", "http://gopher.com/", "", "", false, true, "http://gopher.com/x/y/z/boofar/", "/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "http://gopher.com/", "", "", true, true, "http://gopher.com/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "", "boofar", "", false, false, "/x/y/z/boofar/", "/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "http://barnew/", "", "", false, false, "http://barnew/x/y/z/boofar/", "/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "http://barnew/", "boofar", "", false, false, "http://barnew/x/y/z/boofar/", "/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "", "", "", true, false, "/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "", "", "", true, false, "/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "", "boofar", "", true, false, "/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "http://barnew/", "", "", true, false, "http://barnew/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "http://barnew/", "boofar", "", true, false, "http://barnew/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", true, false, "http://barnew/boo/x/y/z/boofar.html", "/boo/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", false, true, "http://barnew/boo/x/y/z/boofar/", "/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", false, false, "http://barnew/boo/x/y/z/boofar/", "/boo/x/y/z/boofar/"},
		{"x/y/z/boofar.md", "http://barnew/boo/", "boofar", "", true, true, "http://barnew/boo/x/y/z/boofar.html", "/x/y/z/boofar.html"},
		{"x/y/z/boofar.md", "http://barnew/boo", "boofar", "", true, true, "http://barnew/boo/x/y/z/boofar.html", "/x/y/z/boofar.html"},

		// test URL overrides
		{"x/y/z/boofar.md", "", "", "/z/y/q/", false, false, "/z/y/q/", "/z/y/q/"},
	}

	viper.Set("defaultExtension", "html")
	for i, test := range tests {
		viper.Set("uglyURLs", test.uglyURLs)
		viper.Set("canonifyURLs", test.canonifyURLs)
		info := newSiteInfo(siteBuilderCfg{baseURL: string(test.base), language: helpers.NewDefaultLanguage()})

		p := &Page{
			Node: Node{
				URLPath: URLPath{
					Section: "z",
					URL:     test.url,
				},
				Site: &info,
			},
			Source: Source{File: *source.NewFile(filepath.FromSlash(test.file))},
		}

		if test.slug != "" {
			p.update(map[string]interface{}{
				"slug": test.slug,
			})
		}

		u, err := p.Permalink()
		if err != nil {
			t.Errorf("Test %d: Unable to process permalink: %s", i, err)
		}

		expected := test.expectedAbs
		if u != expected {
			t.Errorf("Test %d: Expected abs url: %s, got: %s", i, expected, u)
		}

		u, err = p.RelPermalink()
		if err != nil {
			t.Errorf("Test %d: Unable to process permalink: %s", i, err)
		}

		expected = test.expectedRel
		if u != expected {
			t.Errorf("Test %d: Expected rel url: %s, got: %s", i, expected, u)
		}
	}
}