2016-07-28 03:30:58 -04:00
package hugolib
import (
2016-08-08 03:05:16 -04:00
"bytes"
2016-07-28 03:30:58 -04:00
"fmt"
2016-10-24 08:40:57 -04:00
"regexp"
2016-07-28 03:30:58 -04:00
"strings"
"testing"
"os"
2016-09-21 08:09:41 -04:00
"path/filepath"
"text/template"
2016-07-28 03:30:58 -04:00
2016-09-23 13:04:19 -04:00
"github.com/fortytw2/leaktest"
2016-07-28 03:30:58 -04:00
"github.com/fsnotify/fsnotify"
"github.com/spf13/afero"
2017-01-10 04:55:03 -05:00
"github.com/spf13/hugo/deps"
2016-07-28 03:30:58 -04:00
"github.com/spf13/hugo/helpers"
"github.com/spf13/hugo/hugofs"
"github.com/spf13/hugo/source"
2016-11-07 14:24:37 -05:00
// jww "github.com/spf13/jwalterweatherman"
2016-07-28 03:30:58 -04:00
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
2016-08-04 14:41:30 -04:00
"github.com/stretchr/testify/require"
2016-07-28 03:30:58 -04:00
)
2016-09-21 08:09:41 -04:00
type testSiteConfig struct {
DefaultContentLanguage string
2017-01-10 04:55:03 -05:00
Fs * hugofs . Fs
2016-09-21 08:09:41 -04:00
}
2016-07-28 03:30:58 -04:00
func init ( ) {
testCommonResetState ( )
}
func testCommonResetState ( ) {
viper . Reset ( )
2017-01-10 04:55:03 -05:00
// TODO(bep) globals viper viper.SetFs(hugofs.Source())
viper . Set ( "currentContentLanguage" , helpers . NewLanguage ( "en" ) )
2016-10-24 07:45:30 -04:00
helpers . ResetConfigProvider ( )
2016-08-05 05:04:52 -04:00
loadDefaultSettings ( )
2016-08-01 17:04:44 -04:00
2016-08-08 07:55:18 -04:00
// Default is false, but true is easier to use as default in tests
2016-10-24 14:56:00 -04:00
viper . Set ( "defaultContentLanguageInSubdir" , true )
2016-08-08 07:55:18 -04:00
2016-07-28 03:30:58 -04:00
}
2017-01-10 04:55:03 -05:00
// TODO(bep) globals this currently fails because of a configuration dependency that will be resolved when we get rid of the global Viper.
func _TestMultiSitesMainLangInRoot ( t * testing . T ) {
2016-11-07 14:24:37 -05:00
2016-11-09 03:58:18 -05:00
for _ , b := range [ ] bool { true , false } {
2016-08-08 07:55:18 -04:00
doTestMultiSitesMainLangInRoot ( t , b )
}
}
func doTestMultiSitesMainLangInRoot ( t * testing . T , defaultInSubDir bool ) {
testCommonResetState ( )
2016-10-24 14:56:00 -04:00
viper . Set ( "defaultContentLanguageInSubdir" , defaultInSubDir )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
siteConfig := testSiteConfig { DefaultContentLanguage : "fr" , Fs : fs }
2016-08-08 07:55:18 -04:00
2016-09-21 08:09:41 -04:00
sites := createMultiTestSites ( t , siteConfig , multiSiteTOMLConfigTemplate )
2016-08-08 07:55:18 -04:00
err := sites . Build ( BuildCfg { } )
if err != nil {
t . Fatalf ( "Failed to build sites: %s" , err )
}
2016-08-09 14:06:15 -04:00
require . Len ( t , sites . Sites , 4 )
2016-08-08 07:55:18 -04:00
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 )
}
2017-01-10 04:55:03 -05:00
fmt . Println ( ">>>" , enSite . PathSpec )
require . Equal ( t , "/blog/en/foo" , enSite . PathSpec . RelURL ( "foo" , true ) )
2016-11-07 15:16:55 -05:00
2016-11-13 08:27:10 -05:00
doc1en := enSite . RegularPages [ 0 ]
doc1fr := frSite . RegularPages [ 0 ]
2016-08-08 07:55:18 -04:00
2016-11-15 04:43:49 -05:00
enPerm := doc1en . Permalink ( )
enRelPerm := doc1en . RelPermalink ( )
2016-08-08 07:55:18 -04:00
require . Equal ( t , "http://example.com/blog/en/sect/doc1-slug/" , enPerm )
require . Equal ( t , "/blog/en/sect/doc1-slug/" , enRelPerm )
2016-11-15 04:43:49 -05:00
frPerm := doc1fr . Permalink ( )
frRelPerm := doc1fr . RelPermalink ( )
2016-08-08 07:55:18 -04:00
// 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 )
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sect/doc1/index.html" , defaultInSubDir , "Single" , "Bonjour" )
assertFileContent ( t , fs , "public/en/sect/doc1-slug/index.html" , defaultInSubDir , "Single" , "Hello" )
2016-08-08 07:55:18 -04:00
// Check home
if defaultInSubDir {
// should have a redirect on top level.
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/index.html" , true , ` <meta http-equiv="refresh" content="0; url=http://example.com/blog/fr" /> ` )
2016-09-09 11:40:56 -04:00
} else {
// should have redirect back to root
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/index.html" , true , ` <meta http-equiv="refresh" content="0; url=http://example.com/blog" /> ` )
2016-08-08 07:55:18 -04:00
}
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/index.html" , defaultInSubDir , "Home" , "Bonjour" )
assertFileContent ( t , fs , "public/en/index.html" , defaultInSubDir , "Home" , "Hello" )
2016-08-08 07:55:18 -04:00
// Check list pages
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sect/index.html" , defaultInSubDir , "List" , "Bonjour" )
assertFileContent ( t , fs , "public/en/sect/index.html" , defaultInSubDir , "List" , "Hello" )
assertFileContent ( t , fs , "public/fr/plaques/frtag1/index.html" , defaultInSubDir , "List" , "Bonjour" )
assertFileContent ( t , fs , "public/en/tags/tag1/index.html" , defaultInSubDir , "List" , "Hello" )
2016-08-08 07:55:18 -04:00
// Check sitemaps
// Sitemaps behaves different: In a multilanguage setup there will always be a index file and
// one sitemap in each lang folder.
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/sitemap.xml" , true ,
2016-09-30 10:24:09 -04:00
"<loc>http://example.com/blog/en/sitemap.xml</loc>" ,
"<loc>http://example.com/blog/fr/sitemap.xml</loc>" )
2016-08-08 07:55:18 -04:00
if defaultInSubDir {
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sitemap.xml" , true , "<loc>http://example.com/blog/fr/</loc>" )
2016-08-08 07:55:18 -04:00
} else {
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sitemap.xml" , true , "<loc>http://example.com/blog/</loc>" )
2016-08-08 07:55:18 -04:00
}
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/en/sitemap.xml" , true , "<loc>http://example.com/blog/en/</loc>" )
2016-08-08 07:55:18 -04:00
// Check rss
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/index.xml" , defaultInSubDir , ` <atom:link href="http://example.com/blog/fr/index.xml" ` )
assertFileContent ( t , fs , "public/en/index.xml" , defaultInSubDir , ` <atom:link href="http://example.com/blog/en/index.xml" ` )
assertFileContent ( t , fs , "public/fr/sect/index.xml" , defaultInSubDir , ` <atom:link href="http://example.com/blog/fr/sect/index.xml" ` )
assertFileContent ( t , fs , "public/en/sect/index.xml" , defaultInSubDir , ` <atom:link href="http://example.com/blog/en/sect/index.xml" ` )
assertFileContent ( t , fs , "public/fr/plaques/frtag1/index.xml" , defaultInSubDir , ` <atom:link href="http://example.com/blog/fr/plaques/frtag1/index.xml" ` )
assertFileContent ( t , fs , "public/en/tags/tag1/index.xml" , defaultInSubDir , ` <atom:link href="http://example.com/blog/en/tags/tag1/index.xml" ` )
2016-08-08 07:55:18 -04:00
// Check paginators
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/page/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/fr/" ` )
assertFileContent ( t , fs , "public/en/page/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/en/" ` )
assertFileContent ( t , fs , "public/fr/page/2/index.html" , defaultInSubDir , "Home Page 2" , "Bonjour" , "http://example.com/blog/fr/" )
assertFileContent ( t , fs , "public/en/page/2/index.html" , defaultInSubDir , "Home Page 2" , "Hello" , "http://example.com/blog/en/" )
assertFileContent ( t , fs , "public/fr/sect/page/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/fr/sect/" ` )
assertFileContent ( t , fs , "public/en/sect/page/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/en/sect/" ` )
assertFileContent ( t , fs , "public/fr/sect/page/2/index.html" , defaultInSubDir , "List Page 2" , "Bonjour" , "http://example.com/blog/fr/sect/" )
assertFileContent ( t , fs , "public/en/sect/page/2/index.html" , defaultInSubDir , "List Page 2" , "Hello" , "http://example.com/blog/en/sect/" )
assertFileContent ( t , fs , "public/fr/plaques/frtag1/page/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/fr/plaques/frtag1/" ` )
assertFileContent ( t , fs , "public/en/tags/tag1/page/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/en/tags/tag1/" ` )
assertFileContent ( t , fs , "public/fr/plaques/frtag1/page/2/index.html" , defaultInSubDir , "List Page 2" , "Bonjour" , "http://example.com/blog/fr/plaques/frtag1/" )
assertFileContent ( t , fs , "public/en/tags/tag1/page/2/index.html" , defaultInSubDir , "List Page 2" , "Hello" , "http://example.com/blog/en/tags/tag1/" )
2016-09-15 03:32:52 -04:00
// nn (Nynorsk) and nb (Bokmål) have custom pagePath: side ("page" in Norwegian)
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/nn/side/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/nn/" ` )
assertFileContent ( t , fs , "public/nb/side/1/index.html" , defaultInSubDir , ` refresh" content="0; url=http://example.com/blog/nb/" ` )
2016-08-08 07:55:18 -04:00
}
func replaceDefaultContentLanguageValue ( value string , defaultInSubDir bool ) string {
2016-10-24 14:56:00 -04:00
replace := viper . GetString ( "defaultContentLanguage" ) + "/"
2016-08-08 07:55:18 -04:00
if ! defaultInSubDir {
value = strings . Replace ( value , replace , "" , 1 )
}
return value
}
2017-01-10 04:55:03 -05:00
func assertFileContent ( t * testing . T , fs * hugofs . Fs , filename string , defaultInSubDir bool , matches ... string ) {
2016-08-08 07:55:18 -04:00
filename = replaceDefaultContentLanguageValue ( filename , defaultInSubDir )
2017-01-10 04:55:03 -05:00
content := readDestination ( t , fs , filename )
2016-08-08 07:55:18 -04:00
for _ , match := range matches {
match = replaceDefaultContentLanguageValue ( match , defaultInSubDir )
2017-01-08 10:54:05 -05:00
require . True ( t , strings . Contains ( content , match ) , fmt . Sprintf ( "File no match for\n%q in\n%q:\n%s" , strings . Replace ( match , "%" , "%%" , - 1 ) , filename , strings . Replace ( content , "%" , "%%" , - 1 ) ) )
2016-08-08 07:55:18 -04:00
}
}
2017-01-10 04:55:03 -05:00
func assertFileContentRegexp ( t * testing . T , fs * hugofs . Fs , filename string , defaultInSubDir bool , matches ... string ) {
2016-10-24 08:40:57 -04:00
filename = replaceDefaultContentLanguageValue ( filename , defaultInSubDir )
2017-01-10 04:55:03 -05:00
content := readDestination ( t , fs , filename )
2016-10-24 08:40:57 -04:00
for _ , match := range matches {
match = replaceDefaultContentLanguageValue ( match , defaultInSubDir )
r := regexp . MustCompile ( match )
2016-11-07 14:24:37 -05:00
require . True ( t , r . MatchString ( content ) , fmt . Sprintf ( "File no match for\n%q in\n%q:\n%s" , match , filename , content ) )
2016-10-24 08:40:57 -04:00
}
}
2016-12-23 03:52:05 -05:00
func TestMultiSitesWithTwoLanguages ( t * testing . T ) {
testCommonResetState ( )
viper . Set ( "defaultContentLanguage" , "nn" )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
depsCfg := deps . DepsCfg { Fs : fs }
viper . SetFs ( depsCfg . Fs . Source )
writeSource ( t , depsCfg . Fs , "config.toml" , `
2016-12-23 03:52:05 -05:00
[ languages ]
[ languages . nn ]
languageName = "Nynorsk"
weight = 1
title = "Tittel på Nynorsk"
[ languages . en ]
title = "Title in English"
languageName = "English"
weight = 2
` ,
)
if err := LoadGlobalConfig ( "" , "config.toml" ) ; err != nil {
t . Fatalf ( "Failed to load config: %s" , err )
}
2017-01-10 04:55:03 -05:00
sites , err := NewHugoSitesFromConfiguration ( depsCfg )
2016-12-23 03:52:05 -05:00
if err != nil {
t . Fatalf ( "Failed to create sites: %s" , err )
}
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , filepath . Join ( "content" , "foo.md" ) , "foo" )
// Add some data
writeSource ( t , fs , filepath . Join ( "data" , "hugo.toml" ) , "slogan = \"Hugo Rocks!\"" )
2016-12-23 03:52:05 -05:00
require . NoError ( t , sites . Build ( BuildCfg { } ) )
require . Len ( t , sites . Sites , 2 )
nnSite := sites . Sites [ 0 ]
nnSiteHome := nnSite . getPage ( KindHome )
require . Len ( t , nnSiteHome . AllTranslations ( ) , 2 )
require . Len ( t , nnSiteHome . Translations ( ) , 1 )
require . True ( t , nnSiteHome . IsTranslated ( ) )
}
2016-08-10 16:46:02 -04:00
//
2016-08-05 07:10:58 -04:00
func TestMultiSitesBuild ( t * testing . T ) {
2016-08-10 16:46:02 -04:00
for _ , config := range [ ] struct {
content string
suffix string
} {
2016-09-21 08:09:41 -04:00
{ multiSiteTOMLConfigTemplate , "toml" } ,
2016-08-10 16:46:02 -04:00
{ multiSiteYAMLConfig , "yml" } ,
2016-08-10 17:57:10 -04:00
{ multiSiteJSONConfig , "json" } ,
2016-08-10 16:46:02 -04:00
} {
doTestMultiSitesBuild ( t , config . content , config . suffix )
}
}
2016-09-21 08:09:41 -04:00
func doTestMultiSitesBuild ( t * testing . T , configTemplate , configSuffix string ) {
2016-09-23 13:04:19 -04:00
defer leaktest . Check ( t ) ( )
2016-08-05 07:10:58 -04:00
testCommonResetState ( )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
siteConfig := testSiteConfig { DefaultContentLanguage : "fr" , Fs : fs }
2016-09-21 08:09:41 -04:00
sites := createMultiTestSitesForConfig ( t , siteConfig , configTemplate , configSuffix )
2016-07-28 03:30:58 -04:00
2016-08-04 14:41:30 -04:00
err := sites . Build ( BuildCfg { } )
2016-07-28 03:30:58 -04:00
if err != nil {
t . Fatalf ( "Failed to build sites: %s" , err )
}
enSite := sites . Sites [ 0 ]
2016-12-21 04:17:05 -05:00
enSiteHome := enSite . getPage ( KindHome )
require . True ( t , enSiteHome . IsTranslated ( ) )
2016-07-28 03:30:58 -04:00
assert . Equal ( t , "en" , enSite . Language . Lang )
2016-11-13 08:27:10 -05:00
if len ( enSite . RegularPages ) != 4 {
2016-11-09 05:09:16 -05:00
t . Fatal ( "Expected 4 english pages" )
2016-07-28 03:30:58 -04:00
}
2016-11-09 05:09:16 -05:00
assert . Len ( t , enSite . Source . Files ( ) , 14 , "should have 13 source files" )
2016-11-11 03:01:47 -05:00
assert . Len ( t , enSite . AllPages , 28 , "should have 28 total pages (including translations and index types)" )
2016-07-28 03:30:58 -04:00
2016-11-13 08:27:10 -05:00
doc1en := enSite . RegularPages [ 0 ]
2016-11-15 04:43:49 -05:00
permalink := doc1en . Permalink ( )
2016-07-28 03:30:58 -04:00
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" )
2016-11-13 08:27:10 -05:00
doc2 := enSite . RegularPages [ 1 ]
2016-11-15 04:43:49 -05:00
permalink = doc2 . Permalink ( )
2016-07-28 03:30:58 -04:00
assert . NoError ( t , err , "permalink call failed" )
assert . Equal ( t , "http://example.com/blog/en/sect/doc2/" , permalink , "invalid doc2 permalink" )
2016-11-13 08:27:10 -05:00
doc3 := enSite . RegularPages [ 2 ]
2016-11-15 04:43:49 -05:00
permalink = doc3 . Permalink ( )
2016-07-28 03:30:58 -04:00
assert . NoError ( t , err , "permalink call failed" )
2016-09-14 12:51:34 -04:00
// 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.
2016-07-28 03:30:58 -04:00
assert . Equal ( t , "http://example.com/blog/superbob" , permalink , "invalid doc3 permalink" )
2016-09-14 12:51:34 -04:00
assert . Equal ( t , "/superbob" , doc3 . URL ( ) , "invalid url, was specified on doc3" )
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/superbob/index.html" , true , "doc3|Hello|en" )
2016-07-28 03:30:58 -04:00
assert . Equal ( t , doc2 . Next , doc3 , "doc3 should follow doc2, in .Next" )
doc1fr := doc1en . Translations ( ) [ 0 ]
2016-11-15 04:43:49 -05:00
permalink = doc1fr . Permalink ( )
2016-07-28 03:30:58 -04:00
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 ]
2016-11-15 04:43:49 -05:00
permalink = doc4 . Permalink ( )
2016-07-28 03:30:58 -04:00
assert . Equal ( t , "http://example.com/blog/fr/sect/doc4/" , permalink , "invalid doc4 permalink" )
2016-09-14 12:51:34 -04:00
assert . Equal ( t , "/blog/fr/sect/doc4/" , doc4 . URL ( ) )
2016-07-28 03:30:58 -04:00
assert . Len ( t , doc4 . Translations ( ) , 0 , "found translations for doc4" )
doc5 := enSite . AllPages [ 5 ]
2016-11-15 04:43:49 -05:00
permalink = doc5 . Permalink ( )
2016-07-28 03:30:58 -04:00
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 )
2016-11-13 08:27:10 -05:00
assert . Len ( t , frSite . RegularPages , 3 , "should have 3 pages" )
2016-11-11 03:01:47 -05:00
assert . Len ( t , frSite . AllPages , 28 , "should have 28 total pages (including translations and nodes)" )
2016-07-28 03:30:58 -04:00
2016-11-13 08:27:10 -05:00
for _ , frenchPage := range frSite . RegularPages {
2016-07-28 03:30:58 -04:00
assert . Equal ( t , "fr" , frenchPage . Lang ( ) )
}
2016-08-04 16:12:19 -04:00
// Check redirect to main language, French
2017-01-10 04:55:03 -05:00
languageRedirect := readDestination ( t , fs , "public/index.html" )
2016-08-04 14:41:30 -04:00
require . True ( t , strings . Contains ( languageRedirect , "0; url=http://example.com/blog/fr" ) , languageRedirect )
2016-08-11 12:26:45 -04:00
// check home page content (including data files rendering)
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/en/index.html" , true , "Home Page 1" , "Hello" , "Hugo Rocks!" )
assertFileContent ( t , fs , "public/fr/index.html" , true , "Home Page 1" , "Bonjour" , "Hugo Rocks!" )
2016-08-11 12:26:45 -04:00
2016-08-12 12:17:00 -04:00
// check single page content
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sect/doc1/index.html" , true , "Single" , "Shortcode: Bonjour" )
assertFileContent ( t , fs , "public/en/sect/doc1-slug/index.html" , true , "Single" , "Shortcode: Hello" )
2016-08-12 12:17:00 -04:00
2016-08-09 14:06:15 -04:00
// Check node translations
2016-11-13 05:43:23 -05:00
homeEn := enSite . getPage ( KindHome )
2016-08-09 14:06:15 -04:00
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 ( ) )
2016-09-12 14:57:52 -04:00
require . Equal ( t , "På nynorsk" , homeEn . Translations ( ) [ 1 ] . Title )
2016-08-09 14:06:15 -04:00
require . Equal ( t , "nb" , homeEn . Translations ( ) [ 2 ] . Lang ( ) )
2016-09-12 14:57:52 -04:00
require . Equal ( t , "På bokmål" , homeEn . Translations ( ) [ 2 ] . Title , configSuffix )
require . Equal ( t , "Bokmål" , homeEn . Translations ( ) [ 2 ] . Language ( ) . LanguageName , configSuffix )
2016-08-09 14:06:15 -04:00
2016-11-13 05:43:23 -05:00
sectFr := frSite . getPage ( KindSection , "sect" )
2016-08-09 14:06:15 -04:00
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 )
2016-11-13 05:43:23 -05:00
taxNn := nnSite . getPage ( KindTaxonomyTerm , "lag" )
2016-08-09 14:06:15 -04:00
require . NotNil ( t , taxNn )
require . Len ( t , taxNn . Translations ( ) , 1 )
require . Equal ( t , "nb" , taxNn . Translations ( ) [ 0 ] . Lang ( ) )
2016-11-13 05:43:23 -05:00
taxTermNn := nnSite . getPage ( KindTaxonomy , "lag" , "sogndal" )
2016-08-09 14:06:15 -04:00
require . NotNil ( t , taxTermNn )
require . Len ( t , taxTermNn . Translations ( ) , 1 )
require . Equal ( t , "nb" , taxTermNn . Translations ( ) [ 0 ] . Lang ( ) )
2016-08-04 16:12:19 -04:00
// Check sitemap(s)
2017-01-10 04:55:03 -05:00
sitemapIndex := readDestination ( t , fs , "public/sitemap.xml" )
2016-09-30 10:24:09 -04:00
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 )
2017-01-10 04:55:03 -05:00
sitemapEn := readDestination ( t , fs , "public/en/sitemap.xml" )
sitemapFr := readDestination ( t , fs , "public/fr/sitemap.xml" )
2016-08-04 16:12:19 -04:00
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 )
2016-08-05 07:10:58 -04:00
// Check taxonomies
enTags := enSite . Taxonomies [ "tags" ]
frTags := frSite . Taxonomies [ "plaques" ]
2016-08-05 10:11:03 -04:00
require . Len ( t , enTags , 2 , fmt . Sprintf ( "Tags in en: %v" , enTags ) )
require . Len ( t , frTags , 2 , fmt . Sprintf ( "Tags in fr: %v" , frTags ) )
2016-08-05 07:10:58 -04:00
require . NotNil ( t , enTags [ "tag1" ] )
require . NotNil ( t , frTags [ "frtag1" ] )
2017-01-10 04:55:03 -05:00
readDestination ( t , fs , "public/fr/plaques/frtag1/index.html" )
readDestination ( t , fs , "public/en/tags/tag1/index.html" )
2016-08-07 08:03:03 -04:00
// 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 ) )
2016-08-08 03:05:16 -04:00
// Check that the drafts etc. are not built/processed/rendered.
assertShouldNotBuild ( t , sites )
2016-09-12 14:41:52 -04:00
// 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 )
2016-07-28 03:30:58 -04:00
}
func TestMultiSitesRebuild ( t * testing . T ) {
2016-11-07 14:24:37 -05:00
2016-09-23 13:04:19 -04:00
defer leaktest . Check ( t ) ( )
2016-08-05 07:10:58 -04:00
testCommonResetState ( )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
siteConfig := testSiteConfig { DefaultContentLanguage : "fr" , Fs : fs }
2016-09-21 08:09:41 -04:00
sites := createMultiTestSites ( t , siteConfig , multiSiteTOMLConfigTemplate )
2016-08-12 18:33:17 -04:00
cfg := BuildCfg { Watching : true }
2016-07-28 03:30:58 -04:00
err := sites . Build ( cfg )
if err != nil {
t . Fatalf ( "Failed to build sites: %s" , err )
}
2017-01-10 04:55:03 -05:00
_ , err = fs . Destination . Open ( "public/en/sect/doc2/index.html" )
2016-07-28 03:30:58 -04:00
if err != nil {
t . Fatalf ( "Unable to locate file" )
}
enSite := sites . Sites [ 0 ]
frSite := sites . Sites [ 1 ]
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 4 )
require . Len ( t , frSite . RegularPages , 3 )
2016-07-28 03:30:58 -04:00
// Verify translations
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/en/sect/doc1-slug/index.html" , true , "Hello" )
assertFileContent ( t , fs , "public/fr/sect/doc1/index.html" , true , "Bonjour" )
2016-07-28 03:30:58 -04:00
2016-08-12 18:33:17 -04:00
// check single page content
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sect/doc1/index.html" , true , "Single" , "Shortcode: Bonjour" )
assertFileContent ( t , fs , "public/en/sect/doc1-slug/index.html" , true , "Single" , "Shortcode: Hello" )
2016-08-12 18:33:17 -04:00
2016-07-28 03:30:58 -04:00
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 ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 3 , "1 en removed" )
2016-07-28 03:30:58 -04:00
// Check build stats
2016-11-09 03:58:18 -05:00
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" )
2016-07-28 03:30:58 -04:00
} ,
} ,
{
func ( t * testing . T ) {
2017-01-10 04:55:03 -05:00
writeNewContentFile ( t , fs , "new_en_1" , "2016-07-31" , "content/new1.en.md" , - 5 )
writeNewContentFile ( t , fs , "new_en_2" , "1989-07-30" , "content/new2.en.md" , - 10 )
writeNewContentFile ( t , fs , "new_fr_1" , "2016-07-30" , "content/new1.fr.md" , 10 )
2016-07-28 03:30:58 -04:00
} ,
[ ] 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 ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 5 )
2016-11-11 03:01:47 -05:00
require . Len ( t , enSite . AllPages , 30 )
2016-11-13 08:27:10 -05:00
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 )
2016-07-28 03:30:58 -04:00
2017-01-10 04:55:03 -05:00
rendered := readDestination ( t , fs , "public/en/new1/index.html" )
2016-11-09 03:58:18 -05:00
require . True ( t , strings . Contains ( rendered , "new_en_1" ) , rendered )
2016-07-28 03:30:58 -04:00
} ,
} ,
{
func ( t * testing . T ) {
p := "content/sect/doc1.en.md"
2017-01-10 04:55:03 -05:00
doc1 := readSource ( t , fs , p )
2016-07-28 03:30:58 -04:00
doc1 += "CHANGED"
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , p , doc1 )
2016-07-28 03:30:58 -04:00
} ,
[ ] fsnotify . Event { { Name : "content/sect/doc1.en.md" , Op : fsnotify . Write } } ,
func ( t * testing . T ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 5 )
2017-01-10 04:55:03 -05:00
doc1 := readDestination ( t , fs , "public/en/sect/doc1-slug/index.html" )
2016-11-09 03:58:18 -05:00
require . True ( t , strings . Contains ( doc1 , "CHANGED" ) , doc1 )
2016-07-28 03:30:58 -04:00
} ,
} ,
// Rename a file
{
func ( t * testing . T ) {
2017-01-10 04:55:03 -05:00
if err := fs . Source . Rename ( "content/new1.en.md" , "content/new1renamed.en.md" ) ; err != nil {
2016-07-28 03:30:58 -04:00
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 ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 5 , "Rename" )
require . Equal ( t , "new_en_1" , enSite . RegularPages [ 1 ] . Title )
2017-01-10 04:55:03 -05:00
rendered := readDestination ( t , fs , "public/en/new1renamed/index.html" )
2016-11-09 03:58:18 -05:00
require . True ( t , strings . Contains ( rendered , "new_en_1" ) , rendered )
2016-07-28 03:30:58 -04:00
} } ,
{
// Change a template
func ( t * testing . T ) {
template := "layouts/_default/single.html"
2017-01-10 04:55:03 -05:00
templateContent := readSource ( t , fs , template )
2016-07-28 03:30:58 -04:00
templateContent += "{{ print \"Template Changed\"}}"
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , template , templateContent )
2016-07-28 03:30:58 -04:00
} ,
[ ] fsnotify . Event { { Name : "layouts/_default/single.html" , Op : fsnotify . Write } } ,
func ( t * testing . T ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 5 )
2016-11-11 03:01:47 -05:00
require . Len ( t , enSite . AllPages , 30 )
2016-11-13 08:27:10 -05:00
require . Len ( t , frSite . RegularPages , 4 )
2017-01-10 04:55:03 -05:00
doc1 := readDestination ( t , fs , "public/en/sect/doc1-slug/index.html" )
2016-11-09 03:58:18 -05:00
require . True ( t , strings . Contains ( doc1 , "Template Changed" ) , doc1 )
2016-07-28 03:30:58 -04:00
} ,
} ,
{
// Change a language file
func ( t * testing . T ) {
languageFile := "i18n/fr.yaml"
2017-01-10 04:55:03 -05:00
langContent := readSource ( t , fs , languageFile )
2016-07-28 03:30:58 -04:00
langContent = strings . Replace ( langContent , "Bonjour" , "Salut" , 1 )
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , languageFile , langContent )
2016-07-28 03:30:58 -04:00
} ,
[ ] fsnotify . Event { { Name : "i18n/fr.yaml" , Op : fsnotify . Write } } ,
func ( t * testing . T ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 5 )
2016-11-11 03:01:47 -05:00
require . Len ( t , enSite . AllPages , 30 )
2016-11-13 08:27:10 -05:00
require . Len ( t , frSite . RegularPages , 4 )
2017-01-10 04:55:03 -05:00
docEn := readDestination ( t , fs , "public/en/sect/doc1-slug/index.html" )
2016-11-09 03:58:18 -05:00
require . True ( t , strings . Contains ( docEn , "Hello" ) , "No Hello" )
2017-01-10 04:55:03 -05:00
docFr := readDestination ( t , fs , "public/fr/sect/doc1/index.html" )
2016-11-09 03:58:18 -05:00
require . True ( t , strings . Contains ( docFr , "Salut" ) , "No Salut" )
2016-08-09 14:06:15 -04:00
2016-11-13 05:43:23 -05:00
homeEn := enSite . getPage ( KindHome )
2016-08-09 14:06:15 -04:00
require . NotNil ( t , homeEn )
require . Len ( t , homeEn . Translations ( ) , 3 )
require . Equal ( t , "fr" , homeEn . Translations ( ) [ 0 ] . Lang ( ) )
2016-07-28 03:30:58 -04:00
} ,
} ,
2016-08-12 18:33:17 -04:00
// Change a shortcode
{
func ( t * testing . T ) {
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , "layouts/shortcodes/shortcode.html" , "Modified Shortcode: {{ i18n \"hello\" }}" )
2016-08-12 18:33:17 -04:00
} ,
[ ] fsnotify . Event {
{ Name : "layouts/shortcodes/shortcode.html" , Op : fsnotify . Write } ,
} ,
func ( t * testing . T ) {
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 5 )
2016-11-11 03:01:47 -05:00
require . Len ( t , enSite . AllPages , 30 )
2016-11-13 08:27:10 -05:00
require . Len ( t , frSite . RegularPages , 4 )
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sect/doc1/index.html" , true , "Single" , "Modified Shortcode: Salut" )
assertFileContent ( t , fs , "public/en/sect/doc1-slug/index.html" , true , "Single" , "Modified Shortcode: Hello" )
2016-08-12 18:33:17 -04:00
} ,
} ,
2016-07-28 03:30:58 -04:00
} {
if this . preFunc != nil {
this . preFunc ( t )
}
2016-11-10 14:55:52 -05:00
err = sites . Build ( cfg , this . events ... )
2016-07-28 03:30:58 -04:00
if err != nil {
t . Fatalf ( "[%d] Failed to rebuild sites: %s" , i , err )
}
this . assertFunc ( t )
}
2016-08-08 03:05:16 -04:00
// 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
2016-12-01 04:21:49 -05:00
require . Equal ( t , p . shouldBuild ( ) , bytes . Contains ( p . workContent , [ ] byte ( "</" ) ) , p . BaseFileName ( ) + ": " + string ( p . workContent ) )
2016-08-08 03:05:16 -04:00
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 )
}
2017-01-10 04:55:03 -05:00
require . Equal ( t , p . shouldBuild ( ) , destinationExists ( sites . Fs , filename ) , filename )
2016-08-08 03:05:16 -04:00
}
2016-08-06 08:51:50 -04:00
}
func TestAddNewLanguage ( t * testing . T ) {
testCommonResetState ( )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
siteConfig := testSiteConfig { DefaultContentLanguage : "fr" , Fs : fs }
2016-08-06 08:51:50 -04:00
2016-09-21 08:09:41 -04:00
sites := createMultiTestSites ( t , siteConfig , multiSiteTOMLConfigTemplate )
2016-08-06 08:51:50 -04:00
cfg := BuildCfg { }
err := sites . Build ( cfg )
if err != nil {
t . Fatalf ( "Failed to build sites: %s" , err )
}
2016-09-21 08:09:41 -04:00
newConfig := multiSiteTOMLConfigTemplate + `
2016-08-06 08:51:50 -04:00
2016-08-09 14:06:15 -04:00
[ Languages . sv ]
2016-08-06 08:51:50 -04:00
weight = 15
2016-08-09 14:06:15 -04:00
title = "Svenska"
2016-08-06 08:51:50 -04:00
`
2016-09-21 08:09:41 -04:00
newConfig = createConfig ( t , siteConfig , newConfig )
2017-01-10 04:55:03 -05:00
writeNewContentFile ( t , fs , "Swedish Contentfile" , "2016-01-01" , "content/sect/doc1.sv.md" , 10 )
2016-08-06 08:51:50 -04:00
// replace the config
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , "multilangconfig.toml" , newConfig )
2016-08-06 08:51:50 -04:00
// 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 )
}
2016-08-09 14:06:15 -04:00
require . Len ( t , sites . Sites , 5 , fmt . Sprintf ( "Len %d" , len ( sites . Sites ) ) )
2016-08-06 08:51:50 -04:00
2016-08-09 14:06:15 -04:00
// The Swedish site should be put in the middle (language weight=15)
2016-08-06 08:51:50 -04:00
enSite := sites . Sites [ 0 ]
2016-08-09 14:06:15 -04:00
svSite := sites . Sites [ 1 ]
2016-08-06 08:51:50 -04:00
frSite := sites . Sites [ 2 ]
require . True ( t , enSite . Language . Lang == "en" , enSite . Language . Lang )
2016-08-09 14:06:15 -04:00
require . True ( t , svSite . Language . Lang == "sv" , svSite . Language . Lang )
2016-08-06 08:51:50 -04:00
require . True ( t , frSite . Language . Lang == "fr" , frSite . Language . Lang )
2016-11-13 05:43:23 -05:00
homeEn := enSite . getPage ( KindHome )
2016-08-09 14:06:15 -04:00
require . NotNil ( t , homeEn )
require . Len ( t , homeEn . Translations ( ) , 4 )
require . Equal ( t , "sv" , homeEn . Translations ( ) [ 0 ] . Lang ( ) )
2016-11-13 08:27:10 -05:00
require . Len ( t , enSite . RegularPages , 4 )
require . Len ( t , frSite . RegularPages , 3 )
2016-08-06 08:51:50 -04:00
2016-08-09 14:06:15 -04:00
// Veriy Swedish site
2016-11-13 08:27:10 -05:00
require . Len ( t , svSite . RegularPages , 1 )
svPage := svSite . RegularPages [ 0 ]
2016-08-09 14:06:15 -04:00
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 ( ) )
2016-07-28 03:30:58 -04:00
}
2016-09-21 08:09:41 -04:00
func TestChangeDefaultLanguage ( t * testing . T ) {
testCommonResetState ( )
2016-10-24 14:56:00 -04:00
viper . Set ( "defaultContentLanguageInSubdir" , false )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
sites := createMultiTestSites ( t , testSiteConfig { DefaultContentLanguage : "fr" , Fs : fs } , multiSiteTOMLConfigTemplate )
2016-09-21 08:09:41 -04:00
cfg := BuildCfg { }
err := sites . Build ( cfg )
if err != nil {
t . Fatalf ( "Failed to build sites: %s" , err )
}
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/sect/doc1/index.html" , true , "Single" , "Bonjour" )
assertFileContent ( t , fs , "public/en/sect/doc2/index.html" , true , "Single" , "Hello" )
2016-09-21 08:09:41 -04:00
newConfig := createConfig ( t , testSiteConfig { DefaultContentLanguage : "en" } , multiSiteTOMLConfigTemplate )
// replace the config
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , "multilangconfig.toml" , newConfig )
2016-09-21 08:09:41 -04:00
// 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
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/fr/sect/doc1/index.html" , true , "Single" , "Bonjour" )
assertFileContent ( t , fs , "public/sect/doc2/index.html" , true , "Single" , "Hello" )
2016-09-21 08:09:41 -04:00
}
2016-10-24 08:40:57 -04:00
func TestTableOfContentsInShortcodes ( t * testing . T ) {
testCommonResetState ( )
2017-01-10 04:55:03 -05:00
fs := hugofs . NewMem ( )
2016-10-24 08:40:57 -04:00
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , "layouts/shortcodes/toc.html" , tocShortcode )
writeSource ( t , fs , "content/post/simple.en.md" , tocPageSimple )
writeSource ( t , fs , "content/post/withSCInHeading.en.md" , tocPageWithShortcodesInHeadings )
2016-10-24 08:40:57 -04:00
2017-01-10 04:55:03 -05:00
sites := createMultiTestSites ( t , testSiteConfig { DefaultContentLanguage : "en" , Fs : fs } , multiSiteTOMLConfigTemplate )
2016-10-24 08:40:57 -04:00
cfg := BuildCfg { }
err := sites . Build ( cfg )
if err != nil {
t . Fatalf ( "Failed to build sites: %s" , err )
}
2017-01-10 04:55:03 -05:00
assertFileContent ( t , fs , "public/en/post/simple/index.html" , true , tocPageSimpleExpected )
assertFileContent ( t , fs , "public/en/post/withSCInHeading/index.html" , true , tocPageWithShortcodesInHeadingsExpected )
2016-10-24 08:40:57 -04:00
}
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 > `
2016-09-21 08:09:41 -04:00
var multiSiteTOMLConfigTemplate = `
2016-10-24 14:56:00 -04:00
defaultExtension = "html"
baseURL = "http://example.com/blog"
disableSitemap = false
disableRSS = false
rssURI = "index.xml"
2016-08-06 08:51:50 -04:00
2016-08-08 07:55:18 -04:00
paginate = 1
2016-10-24 14:56:00 -04:00
defaultContentLanguage = "{{ .DefaultContentLanguage }}"
2016-08-06 08:51:50 -04:00
[ permalinks ]
2016-08-07 08:03:03 -04:00
other = "/somewhere/else/:filename"
[ blackfriday ]
angledQuotes = true
2016-08-06 08:51:50 -04:00
[ Taxonomies ]
tag = "tags"
[ Languages ]
[ Languages . en ]
weight = 10
2016-09-12 14:57:52 -04:00
title = "In English"
languageName = "English"
2016-08-07 08:03:03 -04:00
[ Languages . en . blackfriday ]
angledQuotes = false
2016-09-12 14:41:52 -04:00
[ [ Languages . en . menu . main ] ]
url = "/"
name = "Home"
weight = 0
2016-08-06 08:51:50 -04:00
[ Languages . fr ]
weight = 20
2016-09-12 14:57:52 -04:00
title = "Le Français"
languageName = "Français"
2016-08-06 08:51:50 -04:00
[ Languages . fr . Taxonomies ]
plaque = "plaques"
2016-08-09 14:06:15 -04:00
[ Languages . nn ]
weight = 30
2016-09-12 14:57:52 -04:00
title = "På nynorsk"
languageName = "Nynorsk"
2016-09-15 03:32:52 -04:00
paginatePath = "side"
2016-08-09 14:06:15 -04:00
[ Languages . nn . Taxonomies ]
lag = "lag"
2016-09-12 14:41:52 -04:00
[ [ Languages . nn . menu . main ] ]
url = "/"
name = "Heim"
weight = 1
2016-08-09 14:06:15 -04:00
[ Languages . nb ]
weight = 40
2016-09-12 14:57:52 -04:00
title = "På bokmål"
languageName = "Bokmål"
2016-09-15 03:32:52 -04:00
paginatePath = "side"
2016-08-09 14:06:15 -04:00
[ Languages . nb . Taxonomies ]
lag = "lag"
2016-08-06 08:51:50 -04:00
`
2016-08-10 16:46:02 -04:00
var multiSiteYAMLConfig = `
2016-10-24 14:56:00 -04:00
defaultExtension : "html"
baseURL : "http://example.com/blog"
disableSitemap : false
disableRSS : false
rssURI : "index.xml"
2016-08-10 16:46:02 -04:00
paginate : 1
2016-10-24 14:56:00 -04:00
defaultContentLanguage : "fr"
2016-08-10 16:46:02 -04:00
permalinks :
other : "/somewhere/else/:filename"
blackfriday :
angledQuotes : true
Taxonomies :
tag : "tags"
Languages :
en :
weight : 10
2016-09-12 14:57:52 -04:00
title : "In English"
languageName : "English"
2016-08-10 16:46:02 -04:00
blackfriday :
angledQuotes : false
2016-09-12 14:41:52 -04:00
menu :
main :
- url : "/"
name : "Home"
weight : 0
2016-08-10 16:46:02 -04:00
fr :
weight : 20
2016-09-12 14:57:52 -04:00
title : "Le Français"
languageName : "Français"
2016-08-10 16:46:02 -04:00
Taxonomies :
plaque : "plaques"
nn :
weight : 30
2016-09-12 14:57:52 -04:00
title : "På nynorsk"
languageName : "Nynorsk"
2016-09-15 03:32:52 -04:00
paginatePath : "side"
2016-08-10 16:46:02 -04:00
Taxonomies :
lag : "lag"
2016-09-12 14:41:52 -04:00
menu :
main :
- url : "/"
name : "Heim"
weight : 1
2016-08-10 16:46:02 -04:00
nb :
weight : 40
2016-09-12 14:57:52 -04:00
title : "På bokmål"
languageName : "Bokmål"
2016-09-15 03:32:52 -04:00
paginatePath : "side"
2016-08-10 16:46:02 -04:00
Taxonomies :
lag : "lag"
`
2016-08-10 17:57:10 -04:00
var multiSiteJSONConfig = `
{
2016-10-24 14:56:00 -04:00
"defaultExtension" : "html" ,
"baseURL" : "http://example.com/blog" ,
"disableSitemap" : false ,
"disableRSS" : false ,
"rssURI" : "index.xml" ,
2016-08-10 17:57:10 -04:00
"paginate" : 1 ,
2016-10-24 14:56:00 -04:00
"defaultContentLanguage" : "fr" ,
2016-08-10 17:57:10 -04:00
"permalinks" : {
"other" : "/somewhere/else/:filename"
} ,
"blackfriday" : {
"angledQuotes" : true
} ,
"Taxonomies" : {
"tag" : "tags"
} ,
"Languages" : {
"en" : {
"weight" : 10 ,
2016-09-12 14:57:52 -04:00
"title" : "In English" ,
"languageName" : "English" ,
2016-08-10 17:57:10 -04:00
"blackfriday" : {
"angledQuotes" : false
2016-09-12 14:41:52 -04:00
} ,
"menu" : {
"main" : [
{
"url" : "/" ,
"name" : "Home" ,
"weight" : 0
}
]
2016-08-10 17:57:10 -04:00
}
} ,
"fr" : {
"weight" : 20 ,
2016-09-12 14:57:52 -04:00
"title" : "Le Français" ,
"languageName" : "Français" ,
2016-08-10 17:57:10 -04:00
"Taxonomies" : {
"plaque" : "plaques"
}
} ,
"nn" : {
"weight" : 30 ,
2016-09-12 14:57:52 -04:00
"title" : "På nynorsk" ,
2016-09-15 03:32:52 -04:00
"paginatePath" : "side" ,
2016-09-12 14:57:52 -04:00
"languageName" : "Nynorsk" ,
2016-08-10 17:57:10 -04:00
"Taxonomies" : {
"lag" : "lag"
2016-09-12 14:41:52 -04:00
} ,
"menu" : {
"main" : [
{
"url" : "/" ,
"name" : "Heim" ,
"weight" : 1
}
]
2016-08-10 17:57:10 -04:00
}
} ,
"nb" : {
"weight" : 40 ,
2016-09-12 14:57:52 -04:00
"title" : "På bokmål" ,
2016-09-15 03:32:52 -04:00
"paginatePath" : "side" ,
2016-09-12 14:57:52 -04:00
"languageName" : "Bokmål" ,
2016-08-10 17:57:10 -04:00
"Taxonomies" : {
"lag" : "lag"
}
}
}
}
`
2016-09-21 08:09:41 -04:00
func createMultiTestSites ( t * testing . T , siteConfig testSiteConfig , tomlConfigTemplate string ) * HugoSites {
return createMultiTestSitesForConfig ( t , siteConfig , tomlConfigTemplate , "toml" )
2016-08-10 16:46:02 -04:00
}
2016-09-21 08:09:41 -04:00
func createMultiTestSitesForConfig ( t * testing . T , siteConfig testSiteConfig , configTemplate , configSuffix string ) * HugoSites {
2017-01-10 04:55:03 -05:00
depsCfg := deps . DepsCfg { Fs : siteConfig . Fs }
2016-09-21 08:09:41 -04:00
configContent := createConfig ( t , siteConfig , configTemplate )
2016-07-28 03:30:58 -04:00
// Add some layouts
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source ,
2016-07-28 03:30:58 -04:00
filepath . Join ( "layouts" , "_default/single.html" ) ,
2016-08-12 12:17:00 -04:00
[ ] byte ( "Single: {{ .Title }}|{{ i18n \"hello\" }}|{{.Lang}}|{{ .Content }}" ) ,
2016-07-28 03:30:58 -04:00
0755 ) ; err != nil {
t . Fatalf ( "Failed to write layout file: %s" , err )
}
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source ,
2016-07-28 03:30:58 -04:00
filepath . Join ( "layouts" , "_default/list.html" ) ,
2016-08-08 07:55:18 -04:00
[ ] byte ( "{{ $p := .Paginator }}List Page {{ $p.PageNumber }}: {{ .Title }}|{{ i18n \"hello\" }}|{{ .Permalink }}" ) ,
2016-07-28 03:30:58 -04:00
0755 ) ; err != nil {
t . Fatalf ( "Failed to write layout file: %s" , err )
}
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source ,
2016-07-28 03:30:58 -04:00
filepath . Join ( "layouts" , "index.html" ) ,
2016-08-11 12:26:45 -04:00
[ ] byte ( "{{ $p := .Paginator }}Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}" ) ,
2016-07-28 03:30:58 -04:00
0755 ) ; err != nil {
t . Fatalf ( "Failed to write layout file: %s" , err )
}
2016-08-12 12:17:00 -04:00
// Add a shortcode
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source ,
2016-08-12 12:17:00 -04:00
filepath . Join ( "layouts" , "shortcodes" , "shortcode.html" ) ,
[ ] byte ( "Shortcode: {{ i18n \"hello\" }}" ) ,
0755 ) ; err != nil {
t . Fatalf ( "Failed to write layout file: %s" , err )
}
2016-07-28 03:30:58 -04:00
// Add some language files
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source ,
2016-07-28 03:30:58 -04:00
filepath . Join ( "i18n" , "en.yaml" ) ,
[ ] byte ( `
- id : hello
translation : "Hello"
` ) ,
0755 ) ; err != nil {
t . Fatalf ( "Failed to write language file: %s" , err )
}
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source ,
2016-07-28 03:30:58 -04:00
filepath . Join ( "i18n" , "fr.yaml" ) ,
[ ] byte ( `
- id : hello
translation : "Bonjour"
` ) ,
0755 ) ; err != nil {
t . Fatalf ( "Failed to write language file: %s" , err )
}
// Sources
sources := [ ] source . ByteSource {
2016-11-09 05:09:16 -05:00
{ Name : filepath . FromSlash ( "root.en.md" ) , Content : [ ] byte ( ` -- -
title : root
weight : 10000
slug : root
publishdate : "2000-01-01"
-- -
# root
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "sect/doc1.en.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : doc1
2016-11-06 09:38:52 -05:00
weight : 1
2016-07-28 03:30:58 -04:00
slug : doc1 - slug
tags :
- tag1
publishdate : "2000-01-01"
-- -
# doc1
2016-08-07 08:03:03 -04:00
* some "content" *
2016-08-12 12:17:00 -04:00
{ { < shortcode > } }
2016-07-28 03:30:58 -04:00
NOTE : slug should be used as URL
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "sect/doc1.fr.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : doc1
2016-11-06 09:38:52 -05:00
weight : 1
2016-08-05 07:10:58 -04:00
plaques :
- frtag1
- frtag2
2016-07-28 03:30:58 -04:00
publishdate : "2000-01-04"
-- -
# doc1
2016-08-07 08:03:03 -04:00
* quelque "contenu" *
2016-08-12 12:17:00 -04:00
{ { < shortcode > } }
2016-07-28 03:30:58 -04:00
NOTE : should be in the ' en ' Page ' s ' Translations ' field .
NOTE : date is after "doc3"
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "sect/doc2.en.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : doc2
2016-11-06 09:38:52 -05:00
weight : 2
2016-07-28 03:30:58 -04:00
publishdate : "2000-01-02"
-- -
# doc2
* some content *
NOTE : without slug , "doc2" should be used , without ".en" as URL
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "sect/doc3.en.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : doc3
2016-11-06 09:38:52 -05:00
weight : 3
2016-07-28 03:30:58 -04:00
publishdate : "2000-01-03"
tags :
- tag2
2016-08-08 07:55:18 -04:00
- tag1
2016-07-28 03:30:58 -04:00
url : / superbob
-- -
# doc3
* some content *
NOTE : third ' en ' doc , should trigger pagination on home page .
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "sect/doc4.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : doc4
2016-11-06 09:38:52 -05:00
weight : 4
2016-08-05 07:10:58 -04:00
plaques :
- frtag1
2016-07-28 03:30:58 -04:00
publishdate : "2000-01-05"
-- -
# doc4
* du contenu francophone *
2016-10-24 14:56:00 -04:00
NOTE : should use the defaultContentLanguage and mark this doc as ' fr ' .
2016-07-28 03:30:58 -04:00
NOTE : doesn ' t have any corresponding translation in ' en '
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "other/doc5.fr.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : doc5
2016-11-06 09:38:52 -05:00
weight : 5
2016-07-28 03:30:58 -04:00
publishdate : "2000-01-06"
-- -
# doc5
* autre contenu francophone *
NOTE : should use the "permalinks" configuration with : filename
` ) } ,
// Add some for the stats
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/expired.fr.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : expired
publishdate : "2000-01-06"
expiryDate : "2001-01-06"
-- -
# Expired
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/future.fr.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : future
2016-11-06 09:38:52 -05:00
weight : 6
2016-07-28 03:30:58 -04:00
publishdate : "2100-01-06"
-- -
# Future
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/expired.en.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : expired
2016-11-06 09:38:52 -05:00
weight : 7
2016-07-28 03:30:58 -04:00
publishdate : "2000-01-06"
expiryDate : "2001-01-06"
-- -
# Expired
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/future.en.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : future
2016-11-06 09:38:52 -05:00
weight : 6
2016-07-28 03:30:58 -04:00
publishdate : "2100-01-06"
-- -
# Future
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/draft.en.md" ) , Content : [ ] byte ( ` -- -
2016-07-28 03:30:58 -04:00
title : expired
publishdate : "2000-01-06"
draft : true
-- -
# Draft
2016-08-09 14:06:15 -04:00
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/tax.nn.md" ) , Content : [ ] byte ( ` -- -
2016-08-09 14:06:15 -04:00
title : Tax NN
2016-11-06 09:38:52 -05:00
weight : 8
2016-08-09 14:06:15 -04:00
publishdate : "2000-01-06"
weight : 1001
lag :
- Sogndal
-- -
# Tax NN
` ) } ,
2016-08-20 14:54:10 -04:00
{ Name : filepath . FromSlash ( "stats/tax.nb.md" ) , Content : [ ] byte ( ` -- -
2016-08-09 14:06:15 -04:00
title : Tax NB
2016-11-06 09:38:52 -05:00
weight : 8
2016-08-09 14:06:15 -04:00
publishdate : "2000-01-06"
weight : 1002
lag :
- Sogndal
-- -
# Tax NB
2016-07-28 03:30:58 -04:00
` ) } ,
}
2016-08-10 16:46:02 -04:00
configFile := "multilangconfig." + configSuffix
2017-01-10 04:55:03 -05:00
writeSource ( t , depsCfg . Fs , configFile , configContent )
viper . SetFs ( depsCfg . Fs . Source )
2016-08-10 16:46:02 -04:00
if err := LoadGlobalConfig ( "" , configFile ) ; err != nil {
2016-08-05 07:10:58 -04:00
t . Fatalf ( "Failed to load config: %s" , err )
}
2016-07-28 03:30:58 -04:00
// Hugo support using ByteSource's directly (for testing),
// but to make it more real, we write them to the mem file system.
for _ , s := range sources {
2017-01-10 04:55:03 -05:00
if err := afero . WriteFile ( depsCfg . Fs . Source , filepath . Join ( "content" , s . Name ) , s . Content , 0755 ) ; err != nil {
2016-07-28 03:30:58 -04:00
t . Fatalf ( "Failed to write file: %s" , err )
}
}
2016-08-11 12:26:45 -04:00
// Add some data
2017-01-10 04:55:03 -05:00
writeSource ( t , depsCfg . Fs , "data/hugo.toml" , "slogan = \"Hugo Rocks!\"" )
2016-08-05 07:10:58 -04:00
2017-01-10 04:55:03 -05:00
sites , err := NewHugoSitesFromConfiguration ( depsCfg )
2016-07-28 03:30:58 -04:00
if err != nil {
t . Fatalf ( "Failed to create sites: %s" , err )
}
2016-08-09 14:06:15 -04:00
if len ( sites . Sites ) != 4 {
2016-07-28 03:30:58 -04:00
t . Fatalf ( "Got %d sites" , len ( sites . Sites ) )
}
return sites
}
2017-01-10 04:55:03 -05:00
func writeSource ( t * testing . T , fs * hugofs . Fs , filename , content string ) {
if err := afero . WriteFile ( fs . Source , filepath . FromSlash ( filename ) , [ ] byte ( content ) , 0755 ) ; err != nil {
2016-07-28 03:30:58 -04:00
t . Fatalf ( "Failed to write file: %s" , err )
}
}
2017-01-10 04:55:03 -05:00
func readDestination ( t * testing . T , fs * hugofs . Fs , filename string ) string {
return readFileFromFs ( t , fs . Destination , filename )
2016-07-28 03:30:58 -04:00
}
2017-01-10 04:55:03 -05:00
func destinationExists ( fs * hugofs . Fs , filename string ) bool {
b , err := helpers . Exists ( filename , fs . Destination )
2016-08-08 03:05:16 -04:00
if err != nil {
panic ( err )
}
return b
}
2017-01-10 04:55:03 -05:00
func readSource ( t * testing . T , fs * hugofs . Fs , filename string ) string {
return readFileFromFs ( t , fs . Source , filename )
2016-07-28 03:30:58 -04:00
}
func readFileFromFs ( t * testing . T , fs afero . Fs , filename string ) string {
filename = filepath . FromSlash ( filename )
b , err := afero . ReadFile ( fs , filename )
if err != nil {
// Print some debug info
root := strings . Split ( filename , helpers . FilePathSeparator ) [ 0 ]
afero . Walk ( fs , root , func ( path string , info os . FileInfo , err error ) error {
2016-08-04 14:41:30 -04:00
if info != nil && ! info . IsDir ( ) {
2016-07-28 03:30:58 -04:00
fmt . Println ( " " , path )
}
return nil
} )
t . Fatalf ( "Failed to read file: %s" , err )
}
return string ( b )
}
const testPageTemplate = ` -- -
title : "%s"
publishdate : "%s"
weight : % d
-- -
# Doc % s
`
func newTestPage ( title , date string , weight int ) string {
return fmt . Sprintf ( testPageTemplate , title , date , weight , title )
}
2017-01-10 04:55:03 -05:00
func writeNewContentFile ( t * testing . T , fs * hugofs . Fs , title , date , filename string , weight int ) {
2016-07-28 03:30:58 -04:00
content := newTestPage ( title , date , weight )
2017-01-10 04:55:03 -05:00
writeSource ( t , fs , filename , content )
2016-07-28 03:30:58 -04:00
}
2016-09-21 08:09:41 -04:00
func createConfig ( t * testing . T , config testSiteConfig , configTemplate string ) string {
templ , err := template . New ( "test" ) . Parse ( configTemplate )
if err != nil {
t . Fatal ( "Template parse failed:" , err )
}
var b bytes . Buffer
templ . Execute ( & b , config )
return b . String ( )
}