github.com/jbramsden/hugo@v0.47.1/hugolib/hugo_themes_test.go (about) 1 // Copyright 2018 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package hugolib 15 16 import ( 17 "fmt" 18 "os" 19 "path/filepath" 20 "testing" 21 22 "github.com/gohugoio/hugo/common/loggers" 23 ) 24 25 func TestThemesGraph(t *testing.T) { 26 t.Parallel() 27 28 const ( 29 themeStandalone = ` 30 title = "Theme Standalone" 31 [params] 32 v1 = "v1s" 33 v2 = "v2s" 34 ` 35 themeCyclic = ` 36 title = "Theme Cyclic" 37 theme = "theme3" 38 [params] 39 v1 = "v1c" 40 v2 = "v2c" 41 ` 42 theme1 = ` 43 title = "Theme #1" 44 theme = "themeStandalone" 45 [params] 46 v2 = "v21" 47 ` 48 49 theme2 = ` 50 title = "Theme #2" 51 theme = "theme1" 52 [params] 53 v1 = "v12" 54 ` 55 56 theme3 = ` 57 title = "Theme #3" 58 theme = ["theme2", "themeStandalone", "themeCyclic"] 59 [params] 60 v1 = "v13" 61 v2 = "v24" 62 ` 63 64 theme4 = ` 65 title = "Theme #4" 66 theme = "theme3" 67 [params] 68 v1 = "v14" 69 v2 = "v24" 70 ` 71 72 site1 = ` 73 theme = "theme4" 74 75 [params] 76 v1 = "site" 77 ` 78 site2 = ` 79 theme = ["theme2", "themeStandalone"] 80 ` 81 ) 82 83 var ( 84 testConfigs = []struct { 85 siteConfig string 86 87 // The name of theme somewhere in the middle to write custom key/files. 88 offset string 89 90 check func(b *sitesBuilder) 91 }{ 92 {site1, "theme3", func(b *sitesBuilder) { 93 94 // site1: theme4 theme3 theme2 theme1 themeStandalone themeCyclic 95 96 // Check data 97 // theme3 should win the offset competition 98 b.AssertFileContent("public/index.html", "theme1o::[offset][v]theme3", "theme4o::[offset][v]theme3", "themeStandaloneo::[offset][v]theme3") 99 b.AssertFileContent("public/index.html", "nproject::[inner][other]project|[project][other]project|[theme][other]theme4|[theme1][other]theme1") 100 b.AssertFileContent("public/index.html", "ntheme::[inner][other]theme4|[theme][other]theme4|[theme1][other]theme1|[theme2][other]theme2|[theme3][other]theme3") 101 b.AssertFileContent("public/index.html", "theme1::[inner][other]project|[project][other]project|[theme][other]theme1|[theme1][other]theme1|") 102 b.AssertFileContent("public/index.html", "theme4::[inner][other]project|[project][other]project|[theme][other]theme4|[theme4][other]theme4|") 103 104 // Check layouts 105 b.AssertFileContent("public/index.html", "partial ntheme: theme4", "partial theme2o: theme3") 106 107 // Check i18n 108 b.AssertFileContent("public/index.html", "i18n: project theme4") 109 110 // Check static files 111 // TODO(bep) static files not currently part of the build b.AssertFileContent("public/nproject.txt", "TODO") 112 113 // Check site params 114 b.AssertFileContent("public/index.html", "v1::site", "v2::v24") 115 }}, 116 {site2, "", func(b *sitesBuilder) { 117 118 // site2: theme2 theme1 themeStandalone 119 b.AssertFileContent("public/index.html", "nproject::[inner][other]project|[project][other]project|[theme][other]theme2|[theme1][other]theme1|[theme2][other]theme2|[themeStandalone][other]themeStandalone|") 120 b.AssertFileContent("public/index.html", "ntheme::[inner][other]theme2|[theme][other]theme2|[theme1][other]theme1|[theme2][other]theme2|[themeStandalone][other]themeStandalone|") 121 b.AssertFileContent("public/index.html", "i18n: project theme2") 122 b.AssertFileContent("public/index.html", "partial ntheme: theme2") 123 124 // Params only set in themes 125 b.AssertFileContent("public/index.html", "v1::v12", "v2::v21") 126 127 }}, 128 } 129 130 themeConfigs = []struct { 131 name string 132 config string 133 }{ 134 {"themeStandalone", themeStandalone}, 135 {"themeCyclic", themeCyclic}, 136 {"theme1", theme1}, 137 {"theme2", theme2}, 138 {"theme3", theme3}, 139 {"theme4", theme4}, 140 } 141 ) 142 143 for i, testConfig := range testConfigs { 144 t.Log(fmt.Sprintf("Test %d", i)) 145 b := newTestSitesBuilder(t).WithLogger(loggers.NewErrorLogger()) 146 b.WithConfigFile("toml", testConfig.siteConfig) 147 148 for _, tc := range themeConfigs { 149 var variationsNameBase = []string{"nproject", "ntheme", tc.name} 150 151 themeRoot := filepath.Join("themes", tc.name) 152 b.WithSourceFile(filepath.Join(themeRoot, "config.toml"), tc.config) 153 154 b.WithSourceFile(filepath.Join("layouts", "partials", "m.html"), `{{- range $k, $v := . }}{{ $k }}::{{ template "printv" $v }} 155 {{ end }} 156 {{ define "printv" }} 157 {{- $tp := printf "%T" . -}} 158 {{- if (strings.HasSuffix $tp "map[string]interface {}") -}} 159 {{- range $k, $v := . }}[{{ $k }}]{{ template "printv" $v }}{{ end -}} 160 {{- else -}} 161 {{- . }}| 162 {{- end -}} 163 {{ end }} 164 `) 165 166 for _, nameVariaton := range variationsNameBase { 167 roots := []string{"", themeRoot} 168 169 for _, root := range roots { 170 name := tc.name 171 if root == "" { 172 name = "project" 173 } 174 175 if nameVariaton == "ntheme" && name == "project" { 176 continue 177 } 178 179 // static 180 b.WithSourceFile(filepath.Join(root, "static", nameVariaton+".txt"), name) 181 182 // layouts 183 if i == 1 { 184 b.WithSourceFile(filepath.Join(root, "layouts", "partials", "theme2o.html"), "Not Set") 185 } 186 b.WithSourceFile(filepath.Join(root, "layouts", "partials", nameVariaton+".html"), name) 187 if root != "" && testConfig.offset == tc.name { 188 for _, tc2 := range themeConfigs { 189 b.WithSourceFile(filepath.Join(root, "layouts", "partials", tc2.name+"o.html"), name) 190 } 191 } 192 193 // i18n + data 194 195 var dataContent string 196 if root == "" { 197 dataContent = fmt.Sprintf(` 198 [%s] 199 other = %q 200 201 [inner] 202 other = %q 203 204 `, name, name, name) 205 } else { 206 dataContent = fmt.Sprintf(` 207 [%s] 208 other = %q 209 210 [inner] 211 other = %q 212 213 [theme] 214 other = %q 215 216 `, name, name, name, name) 217 } 218 219 b.WithSourceFile(filepath.Join(root, "data", nameVariaton+".toml"), dataContent) 220 b.WithSourceFile(filepath.Join(root, "i18n", "en.toml"), dataContent) 221 222 // If an offset is set, duplicate a data key with a winner in the middle. 223 if root != "" && testConfig.offset == tc.name { 224 for _, tc2 := range themeConfigs { 225 dataContent := fmt.Sprintf(` 226 [offset] 227 v = %q 228 `, tc.name) 229 b.WithSourceFile(filepath.Join(root, "data", tc2.name+"o.toml"), dataContent) 230 } 231 } 232 } 233 234 } 235 236 } 237 238 for _, themeConfig := range themeConfigs { 239 b.WithSourceFile(filepath.Join("themes", "config.toml"), themeConfig.config) 240 } 241 242 b.WithContent(filepath.Join("content", "page.md"), `--- 243 title: "Page" 244 --- 245 246 `) 247 248 homeTpl := ` 249 data: {{ partial "m" .Site.Data }} 250 i18n: {{ i18n "inner" }} {{ i18n "theme" }} 251 partial ntheme: {{ partial "ntheme" . }} 252 partial theme2o: {{ partial "theme2o" . }} 253 params: {{ partial "m" .Site.Params }} 254 255 ` 256 257 b.WithTemplates(filepath.Join("layouts", "home.html"), homeTpl) 258 259 b.Build(BuildCfg{}) 260 261 var _ = os.Stdout 262 263 // printFs(b.H.Deps.BaseFs.LayoutsFs, "", os.Stdout) 264 testConfig.check(b) 265 266 } 267 268 }