github.com/olliephillips/hugo@v0.42.2/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  }