hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

menu_test.go (13540B)

    1 // Copyright 2019 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 	"testing"
   19 
   20 	qt "github.com/frankban/quicktest"
   21 )
   22 
   23 const (
   24 	menuPageTemplate = `---
   25 title: %q
   26 weight: %d
   27 menu:
   28   %s:
   29     title: %s
   30     weight: %d
   31 ---
   32 # Doc Menu
   33 `
   34 )
   35 
   36 func TestMenusSectionPagesMenu(t *testing.T) {
   37 	t.Parallel()
   38 
   39 	siteConfig := `
   40 baseurl = "http://example.com/"
   41 title = "Section Menu"
   42 sectionPagesMenu = "sect"
   43 `
   44 
   45 	b := newTestSitesBuilder(t).WithConfigFile("toml", siteConfig)
   46 
   47 	b.WithTemplates(
   48 		"partials/menu.html",
   49 		`{{- $p := .page -}}
   50 {{- $m := .menu -}}
   51 {{ range (index $p.Site.Menus $m) -}}
   52 {{- .URL }}|{{ .Name }}|{{ .Title }}|{{ .Weight -}}|
   53 {{- if $p.IsMenuCurrent $m . }}IsMenuCurrent{{ else }}-{{ end -}}|
   54 {{- if $p.HasMenuCurrent $m . }}HasMenuCurrent{{ else }}-{{ end -}}|
   55 {{- end -}}
   56 `,
   57 		"_default/single.html",
   58 		`Single|{{ .Title }}
   59 Menu Sect:  {{ partial "menu.html" (dict "page" . "menu" "sect") }}
   60 Menu Main:  {{ partial "menu.html" (dict "page" . "menu" "main") }}`,
   61 		"_default/list.html", "List|{{ .Title }}|{{ .Content }}",
   62 	)
   63 
   64 	b.WithContent(
   65 		"sect1/p1.md", fmt.Sprintf(menuPageTemplate, "p1", 1, "main", "atitle1", 40),
   66 		"sect1/p2.md", fmt.Sprintf(menuPageTemplate, "p2", 2, "main", "atitle2", 30),
   67 		"sect2/p3.md", fmt.Sprintf(menuPageTemplate, "p3", 3, "main", "atitle3", 20),
   68 		"sect2/p4.md", fmt.Sprintf(menuPageTemplate, "p4", 4, "main", "atitle4", 10),
   69 		"sect3/p5.md", fmt.Sprintf(menuPageTemplate, "p5", 5, "main", "atitle5", 5),
   70 		"sect1/_index.md", newTestPage("Section One", "2017-01-01", 100),
   71 		"sect5/_index.md", newTestPage("Section Five", "2017-01-01", 10),
   72 	)
   73 
   74 	b.Build(BuildCfg{})
   75 	h := b.H
   76 
   77 	s := h.Sites[0]
   78 
   79 	b.Assert(len(s.Menus()), qt.Equals, 2)
   80 
   81 	p1 := s.RegularPages()[0].Menus()
   82 
   83 	// There is only one menu in the page, but it is "member of" 2
   84 	b.Assert(len(p1), qt.Equals, 1)
   85 
   86 	b.AssertFileContent("public/sect1/p1/index.html", "Single",
   87 		"Menu Sect:  "+
   88 			"/sect5/|Section Five|Section Five|10|-|-|"+
   89 			"/sect1/|Section One|Section One|100|-|HasMenuCurrent|"+
   90 			"/sect2/|Sect2s|Sect2s|0|-|-|"+
   91 			"/sect3/|Sect3s|Sect3s|0|-|-|",
   92 		"Menu Main:  "+
   93 			"/sect3/p5/|p5|atitle5|5|-|-|"+
   94 			"/sect2/p4/|p4|atitle4|10|-|-|"+
   95 			"/sect2/p3/|p3|atitle3|20|-|-|"+
   96 			"/sect1/p2/|p2|atitle2|30|-|-|"+
   97 			"/sect1/p1/|p1|atitle1|40|IsMenuCurrent|-|",
   98 	)
   99 
  100 	b.AssertFileContent("public/sect2/p3/index.html", "Single",
  101 		"Menu Sect:  "+
  102 			"/sect5/|Section Five|Section Five|10|-|-|"+
  103 			"/sect1/|Section One|Section One|100|-|-|"+
  104 			"/sect2/|Sect2s|Sect2s|0|-|HasMenuCurrent|"+
  105 			"/sect3/|Sect3s|Sect3s|0|-|-|")
  106 }
  107 
  108 // related issue #7594
  109 func TestMenusSort(t *testing.T) {
  110 	b := newTestSitesBuilder(t).WithSimpleConfigFile()
  111 
  112 	b.WithTemplatesAdded("index.html", `
  113 {{ range $k, $v := .Site.Menus.main }}
  114 Default1|{{ $k }}|{{ $v.Weight }}|{{ $v.Name }}|{{ .URL }}|{{ $v.Page }}{{ end }}
  115 {{ range $k, $v := .Site.Menus.main.ByWeight }}
  116 ByWeight|{{ $k }}|{{ $v.Weight }}|{{ $v.Name }}|{{ .URL }}|{{ $v.Page }}{{ end }}
  117 {{ range $k, $v := (.Site.Menus.main.ByWeight).Reverse }}
  118 Reverse|{{ $k }}|{{ $v.Weight }}|{{ $v.Name }}|{{ .URL }}|{{ $v.Page }}{{ end }}
  119 {{ range $k, $v := .Site.Menus.main }}
  120 Default2|{{ $k }}|{{ $v.Weight }}|{{ $v.Name }}|{{ .URL }}|{{ $v.Page }}{{ end }}
  121 {{ range $k, $v := .Site.Menus.main.ByWeight }}
  122 ByWeight|{{ $k }}|{{ $v.Weight }}|{{ $v.Name }}|{{ .URL }}|{{ $v.Page }}{{ end }}
  123 {{ range $k, $v := .Site.Menus.main }}
  124 Default3|{{ $k }}|{{ $v.Weight }}|{{ $v.Name }}|{{ .URL }}|{{ $v.Page }}{{ end }}
  125 `)
  126 
  127 	b.WithContent("_index.md", `
  128 ---
  129 title: Home
  130 menu:
  131   main:
  132     weight: 100
  133 ---`)
  134 
  135 	b.WithContent("blog/A.md", `
  136 ---
  137 title: "A"
  138 menu:
  139   main:
  140     weight: 10
  141 ---
  142 `)
  143 
  144 	b.WithContent("blog/B.md", `
  145 ---
  146 title: "B"
  147 menu:
  148   main:
  149     weight: 20
  150 ---
  151 `)
  152 	b.WithContent("blog/C.md", `
  153 ---
  154 title: "C"
  155 menu:
  156   main:
  157     weight: 30
  158 ---
  159 `)
  160 
  161 	b.Build(BuildCfg{})
  162 
  163 	b.AssertFileContent("public/index.html",
  164 		`Default1|0|10|A|/blog/a/|Page(/blog/A.md)
  165         Default1|1|20|B|/blog/b/|Page(/blog/B.md)
  166         Default1|2|30|C|/blog/c/|Page(/blog/C.md)
  167         Default1|3|100|Home|/|Page(/_index.md)
  168 
  169         ByWeight|0|10|A|/blog/a/|Page(/blog/A.md)
  170         ByWeight|1|20|B|/blog/b/|Page(/blog/B.md)
  171         ByWeight|2|30|C|/blog/c/|Page(/blog/C.md)
  172         ByWeight|3|100|Home|/|Page(/_index.md)
  173 
  174         Reverse|0|100|Home|/|Page(/_index.md)
  175         Reverse|1|30|C|/blog/c/|Page(/blog/C.md)
  176         Reverse|2|20|B|/blog/b/|Page(/blog/B.md)
  177         Reverse|3|10|A|/blog/a/|Page(/blog/A.md)
  178 
  179         Default2|0|10|A|/blog/a/|Page(/blog/A.md)
  180         Default2|1|20|B|/blog/b/|Page(/blog/B.md)
  181         Default2|2|30|C|/blog/c/|Page(/blog/C.md)
  182         Default2|3|100|Home|/|Page(/_index.md)
  183 
  184         ByWeight|0|10|A|/blog/a/|Page(/blog/A.md)
  185         ByWeight|1|20|B|/blog/b/|Page(/blog/B.md)
  186         ByWeight|2|30|C|/blog/c/|Page(/blog/C.md)
  187         ByWeight|3|100|Home|/|Page(/_index.md)
  188 
  189         Default3|0|10|A|/blog/a/|Page(/blog/A.md)
  190         Default3|1|20|B|/blog/b/|Page(/blog/B.md)
  191         Default3|2|30|C|/blog/c/|Page(/blog/C.md)
  192         Default3|3|100|Home|/|Page(/_index.md)`,
  193 	)
  194 }
  195 
  196 func TestMenusFrontMatter(t *testing.T) {
  197 	b := newTestSitesBuilder(t).WithSimpleConfigFile()
  198 
  199 	b.WithTemplatesAdded("index.html", `
  200 Main: {{ len .Site.Menus.main }}
  201 Other: {{ len .Site.Menus.other }}
  202 {{ range .Site.Menus.main }}
  203 * Main|{{ .Name }}: {{ .URL }}
  204 {{ end }}
  205 {{ range .Site.Menus.other }}
  206 * Other|{{ .Name }}: {{ .URL }}
  207 {{ end }}
  208 `)
  209 
  210 	// Issue #5828
  211 	b.WithContent("blog/page1.md", `
  212 ---
  213 title: "P1"
  214 menu: main
  215 ---
  216 
  217 `)
  218 
  219 	b.WithContent("blog/page2.md", `
  220 ---
  221 title: "P2"
  222 menu: [main,other]
  223 ---
  224 
  225 `)
  226 
  227 	b.WithContent("blog/page3.md", `
  228 ---
  229 title: "P3"
  230 menu:
  231   main:
  232     weight: 30
  233 ---
  234 `)
  235 
  236 	b.Build(BuildCfg{})
  237 
  238 	b.AssertFileContent("public/index.html",
  239 		"Main: 3", "Other: 1",
  240 		"Main|P1: /blog/page1/",
  241 		"Other|P2: /blog/page2/",
  242 	)
  243 }
  244 
  245 // https://github.com/gohugoio/hugo/issues/5849
  246 func TestMenusPageMultipleOutputFormats(t *testing.T) {
  247 	config := `
  248 baseURL = "https://example.com"
  249 
  250 # DAMP is similar to AMP, but not permalinkable.
  251 [outputFormats]
  252 [outputFormats.damp]
  253 mediaType = "text/html"
  254 path = "damp"
  255 
  256 `
  257 
  258 	b := newTestSitesBuilder(t).WithConfigFile("toml", config)
  259 	b.WithContent("_index.md", `
  260 ---
  261 Title: Home Sweet Home
  262 outputs: [ "html", "amp" ]
  263 menu: "main"
  264 ---
  265 
  266 `)
  267 
  268 	b.WithContent("blog/html-amp.md", `
  269 ---
  270 Title: AMP and HTML
  271 outputs: [ "html", "amp" ]
  272 menu: "main"
  273 ---
  274 
  275 `)
  276 
  277 	b.WithContent("blog/html.md", `
  278 ---
  279 Title: HTML only
  280 outputs: [ "html" ]
  281 menu: "main"
  282 ---
  283 
  284 `)
  285 
  286 	b.WithContent("blog/amp.md", `
  287 ---
  288 Title: AMP only
  289 outputs: [ "amp" ]
  290 menu: "main"
  291 ---
  292 
  293 `)
  294 
  295 	b.WithTemplatesAdded("index.html", `{{ range .Site.Menus.main }}{{ .Title }}|{{ .URL }}|{{ end }}`)
  296 
  297 	b.Build(BuildCfg{})
  298 
  299 	b.AssertFileContent("public/index.html", "AMP and HTML|/blog/html-amp/|AMP only|/amp/blog/amp/|Home Sweet Home|/|HTML only|/blog/html/|")
  300 	b.AssertFileContent("public/amp/index.html", "AMP and HTML|/amp/blog/html-amp/|AMP only|/amp/blog/amp/|Home Sweet Home|/amp/|HTML only|/blog/html/|")
  301 }
  302 
  303 // https://github.com/gohugoio/hugo/issues/5989
  304 func TestMenusPageSortByDate(t *testing.T) {
  305 	b := newTestSitesBuilder(t).WithSimpleConfigFile()
  306 
  307 	b.WithContent("blog/a.md", `
  308 ---
  309 Title: A
  310 date: 2019-01-01
  311 menu:
  312   main:
  313     identifier: "a"
  314     weight: 1
  315 ---
  316 
  317 `)
  318 
  319 	b.WithContent("blog/b.md", `
  320 ---
  321 Title: B
  322 date: 2018-01-02
  323 menu:
  324   main:
  325     parent: "a"
  326     weight: 100
  327 ---
  328 
  329 `)
  330 
  331 	b.WithContent("blog/c.md", `
  332 ---
  333 Title: C
  334 date: 2019-01-03
  335 menu:
  336   main:
  337     parent: "a"
  338     weight: 10
  339 ---
  340 
  341 `)
  342 
  343 	b.WithTemplatesAdded("index.html", `{{ range .Site.Menus.main }}{{ .Title }}|Children: 
  344 {{- $children := sort .Children ".Page.Date" "desc" }}{{ range $children }}{{ .Title }}|{{ end }}{{ end }}
  345 	
  346 `)
  347 
  348 	b.Build(BuildCfg{})
  349 
  350 	b.AssertFileContent("public/index.html", "A|Children:C|B|")
  351 }
  352 
  353 // Issue #8825
  354 func TestMenuParamsEmptyYaml(t *testing.T) {
  355 	b := newTestSitesBuilder(t).WithConfigFile("yaml", `
  356 
  357 `)
  358 
  359 	b.WithTemplates("index.html", `{{ site.Menus }}`)
  360 
  361 	b.WithContent("p1.md", `---
  362 menus:
  363   main: 
  364     identity: journal
  365     weight: 2
  366     params:
  367 ---	
  368 `)
  369 	b.Build(BuildCfg{})
  370 }
  371 
  372 func TestMenuParams(t *testing.T) {
  373 	b := newTestSitesBuilder(t).WithConfigFile("toml", `
  374 [[menus.main]]
  375 identifier = "contact"
  376 title = "Contact Us"
  377 url = "mailto:noreply@example.com"
  378 weight = 300
  379 [menus.main.params]
  380 foo = "foo_config"	
  381 key2 = "key2_config"	
  382 camelCase = "camelCase_config"	
  383 `)
  384 
  385 	b.WithTemplatesAdded("index.html", `
  386 Main: {{ len .Site.Menus.main }}
  387 {{ range .Site.Menus.main }}
  388 foo: {{ .Params.foo }}
  389 key2: {{ .Params.KEy2 }}
  390 camelCase: {{ .Params.camelcase }}
  391 {{ end }}
  392 `)
  393 
  394 	b.WithContent("_index.md", `
  395 ---
  396 title: "Home"
  397 menu:
  398   main:
  399     weight: 10
  400     params:
  401       foo: "foo_content"
  402       key2: "key2_content"
  403       camelCase: "camelCase_content"
  404 ---
  405 `)
  406 
  407 	b.Build(BuildCfg{})
  408 
  409 	b.AssertFileContent("public/index.html", `
  410 Main: 2
  411 
  412 foo: foo_content
  413 key2: key2_content
  414 camelCase: camelCase_content
  415 
  416 foo: foo_config
  417 key2: key2_config
  418 camelCase: camelCase_config
  419 `)
  420 }
  421 
  422 func TestMenusShadowMembers(t *testing.T) {
  423 	b := newTestSitesBuilder(t).WithConfigFile("toml", `
  424 [[menus.main]]
  425 identifier = "contact"
  426 pageRef = "contact"
  427 title = "Contact Us"
  428 url = "mailto:noreply@example.com"
  429 weight = 1
  430 [[menus.main]]
  431 pageRef = "/blog/post3"
  432 title = "My Post 3"
  433 url = "/blog/post3"
  434 	
  435 `)
  436 
  437 	commonTempl := `
  438 Main: {{ len .Site.Menus.main }}
  439 {{ range .Site.Menus.main }}
  440 {{ .Title }}|HasMenuCurrent: {{ $.HasMenuCurrent "main" . }}|Page: {{ .Page }}
  441 {{ .Title }}|IsMenuCurrent: {{ $.IsMenuCurrent "main" . }}|Page: {{ .Page }}
  442 {{ end }}
  443 `
  444 
  445 	b.WithTemplatesAdded("index.html", commonTempl)
  446 	b.WithTemplatesAdded("_default/single.html", commonTempl)
  447 
  448 	b.WithContent("_index.md", `
  449 ---
  450 title: "Home"
  451 menu:
  452   main:
  453     weight: 10
  454 ---
  455 `)
  456 
  457 	b.WithContent("blog/_index.md", `
  458 ---
  459 title: "Blog"
  460 menu:
  461   main:
  462     weight: 20
  463 ---
  464 `)
  465 
  466 	b.WithContent("blog/post1.md", `
  467 ---
  468 title: "My Post 1: With  No Menu Defined"
  469 ---
  470 `)
  471 
  472 	b.WithContent("blog/post2.md", `
  473 ---
  474 title: "My Post 2: With Menu Defined"
  475 menu:
  476   main:
  477     weight: 30
  478 ---
  479 `)
  480 
  481 	b.WithContent("blog/post3.md", `
  482 ---
  483 title: "My Post 2: With  No Menu Defined"
  484 ---
  485 `)
  486 
  487 	b.WithContent("contact.md", `
  488 ---
  489 title: "Contact: With  No Menu Defined"
  490 ---
  491 `)
  492 
  493 	b.Build(BuildCfg{})
  494 
  495 	b.AssertFileContent("public/index.html", `
  496 Main: 5
  497 Home|HasMenuCurrent: false|Page: Page(/_index.md)
  498 Blog|HasMenuCurrent: false|Page: Page(/blog/_index.md)
  499 My Post 2: With Menu Defined|HasMenuCurrent: false|Page: Page(/blog/post2.md)
  500 My Post 3|HasMenuCurrent: false|Page: Page(/blog/post3.md)
  501 Contact Us|HasMenuCurrent: false|Page: Page(/contact.md)
  502 `)
  503 
  504 	b.AssertFileContent("public/blog/post1/index.html", `
  505 Home|HasMenuCurrent: false|Page: Page(/_index.md)
  506 Blog|HasMenuCurrent: true|Page: Page(/blog/_index.md)
  507 `)
  508 
  509 	b.AssertFileContent("public/blog/post2/index.html", `
  510 Home|HasMenuCurrent: false|Page: Page(/_index.md)
  511 Blog|HasMenuCurrent: true|Page: Page(/blog/_index.md)
  512 Blog|IsMenuCurrent: false|Page: Page(/blog/_index.md)
  513 `)
  514 
  515 	b.AssertFileContent("public/blog/post3/index.html", `
  516 Home|HasMenuCurrent: false|Page: Page(/_index.md)
  517 Blog|HasMenuCurrent: true|Page: Page(/blog/_index.md)
  518 `)
  519 
  520 	b.AssertFileContent("public/contact/index.html", `
  521 Contact Us|HasMenuCurrent: false|Page: Page(/contact.md)
  522 Contact Us|IsMenuCurrent: true|Page: Page(/contact.md)
  523 Blog|HasMenuCurrent: false|Page: Page(/blog/_index.md)
  524 Blog|IsMenuCurrent: false|Page: Page(/blog/_index.md)
  525 `)
  526 }
  527 
  528 // Issue 9846
  529 func TestMenuHasMenuCurrentSection(t *testing.T) {
  530 	t.Parallel()
  531 
  532 	files := `
  533 -- config.toml --
  534 disableKinds = ['RSS','sitemap','taxonomy','term']
  535 [[menu.main]]
  536 name = 'Home'
  537 pageRef = '/'
  538 weight = 1
  539 
  540 [[menu.main]]
  541 name = 'Tests'
  542 pageRef = '/tests'
  543 weight = 2
  544 [[menu.main]]
  545 name = 'Test 1'
  546 pageRef = '/tests/test-1'
  547 parent = 'Tests'
  548 weight = 1
  549 
  550 -- content/tests/test-1.md --
  551 ---
  552 title: "Test 1"
  553 ---
  554 -- layouts/_default/list.html --
  555 {{ range site.Menus.main }}
  556 {{ .Name }}|{{ .URL }}|IsMenuCurrent = {{ $.IsMenuCurrent "main" . }}|HasMenuCurrent = {{ $.HasMenuCurrent "main" . }}|
  557 {{ range .Children }}
  558 {{ .Name }}|{{ .URL }}|IsMenuCurrent = {{ $.IsMenuCurrent "main" . }}|HasMenuCurrent = {{ $.HasMenuCurrent "main" . }}|
  559 {{ end }}
  560 {{ end }}
  561 
  562 {{/* Some tests for issue 9925 */}}
  563 {{ $page := .Site.GetPage "tests/test-1" }}
  564 {{ $section := site.GetPage "tests" }}
  565 
  566 Home IsAncestor Self: {{ site.Home.IsAncestor site.Home }}
  567 Home IsDescendant Self: {{ site.Home.IsDescendant site.Home }}
  568 Section IsAncestor Self: {{ $section.IsAncestor $section }}
  569 Section IsDescendant Self: {{ $section.IsDescendant $section}}
  570 Page IsAncestor Self: {{ $page.IsAncestor $page }}
  571 Page IsDescendant Self: {{ $page.IsDescendant $page}}
  572 `
  573 
  574 	b := NewIntegrationTestBuilder(
  575 		IntegrationTestConfig{
  576 			T:           t,
  577 			TxtarString: files,
  578 		},
  579 	).Build()
  580 
  581 	b.AssertFileContent("public/tests/index.html", `
  582 Tests|/tests/|IsMenuCurrent = true|HasMenuCurrent = false
  583 Home IsAncestor Self: false
  584 Home IsDescendant Self: false
  585 Section IsAncestor Self: false
  586 Section IsDescendant Self: false
  587 Page IsAncestor Self: false
  588 Page IsDescendant Self: false
  589 `)
  590 }