site_sections_test.go - hugo - [fork] hugo port for 9front
 (HTM) git clone https://git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
       site_sections_test.go (15475B)
       ---
            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         "path/filepath"
           19         "strings"
           20         "testing"
           21 
           22         qt "github.com/frankban/quicktest"
           23         "github.com/gohugoio/hugo/deps"
           24         "github.com/gohugoio/hugo/htesting"
           25         "github.com/gohugoio/hugo/resources/kinds"
           26         "github.com/gohugoio/hugo/resources/page"
           27 )
           28 
           29 func TestNestedSections(t *testing.T) {
           30         var (
           31                 c       = qt.New(t)
           32                 cfg, fs = newTestCfg()
           33         )
           34 
           35         tt := htesting.NewPinnedRunner(c, "")
           36 
           37         cfg.Set("permalinks", map[string]string{
           38                 "perm-a": ":sections/:title",
           39         })
           40 
           41         pageTemplate := `---
           42 title: T%d_%d
           43 ---
           44 Content
           45 `
           46 
           47         // Home page
           48         writeSource(t, fs, filepath.Join("content", "_index.md"), fmt.Sprintf(pageTemplate, -1, -1))
           49 
           50         // Top level content page
           51         writeSource(t, fs, filepath.Join("content", "mypage.md"), fmt.Sprintf(pageTemplate, 1234, 5))
           52 
           53         // Top level section without index content page
           54         writeSource(t, fs, filepath.Join("content", "top", "mypage2.md"), fmt.Sprintf(pageTemplate, 12345, 6))
           55         // Just a page in a subfolder, i.e. not a section.
           56         writeSource(t, fs, filepath.Join("content", "top", "folder", "mypage3.md"), fmt.Sprintf(pageTemplate, 12345, 67))
           57 
           58         for level1 := 1; level1 < 3; level1++ {
           59                 writeSource(t, fs, filepath.Join("content", "l1", fmt.Sprintf("page_1_%d.md", level1)),
           60                         fmt.Sprintf(pageTemplate, 1, level1))
           61         }
           62 
           63         // Issue #3586
           64         writeSource(t, fs, filepath.Join("content", "post", "0000.md"), fmt.Sprintf(pageTemplate, 1, 2))
           65         writeSource(t, fs, filepath.Join("content", "post", "0000", "0001.md"), fmt.Sprintf(pageTemplate, 1, 3))
           66         writeSource(t, fs, filepath.Join("content", "elsewhere", "0003.md"), fmt.Sprintf(pageTemplate, 1, 4))
           67 
           68         // Empty nested section, i.e. no regular content pages.
           69         writeSource(t, fs, filepath.Join("content", "empty1", "b", "c", "_index.md"), fmt.Sprintf(pageTemplate, 33, -1))
           70         // Index content file a the end and in the middle.
           71         writeSource(t, fs, filepath.Join("content", "empty2", "b", "_index.md"), fmt.Sprintf(pageTemplate, 40, -1))
           72         writeSource(t, fs, filepath.Join("content", "empty2", "b", "c", "d", "_index.md"), fmt.Sprintf(pageTemplate, 41, -1))
           73 
           74         // Empty with content file in the middle.
           75         writeSource(t, fs, filepath.Join("content", "empty3", "b", "c", "d", "_index.md"), fmt.Sprintf(pageTemplate, 41, -1))
           76         writeSource(t, fs, filepath.Join("content", "empty3", "b", "empty3.md"), fmt.Sprintf(pageTemplate, 3, -1))
           77 
           78         // Section with permalink config
           79         writeSource(t, fs, filepath.Join("content", "perm a", "link", "_index.md"), fmt.Sprintf(pageTemplate, 9, -1))
           80         for i := 1; i < 4; i++ {
           81                 writeSource(t, fs, filepath.Join("content", "perm a", "link", fmt.Sprintf("page_%d.md", i)),
           82                         fmt.Sprintf(pageTemplate, 1, i))
           83         }
           84         writeSource(t, fs, filepath.Join("content", "perm a", "link", "regular", fmt.Sprintf("page_%d.md", 5)),
           85                 fmt.Sprintf(pageTemplate, 1, 5))
           86 
           87         writeSource(t, fs, filepath.Join("content", "l1", "l2", "_index.md"), fmt.Sprintf(pageTemplate, 2, -1))
           88         writeSource(t, fs, filepath.Join("content", "l1", "l2_2", "_index.md"), fmt.Sprintf(pageTemplate, 22, -1))
           89         writeSource(t, fs, filepath.Join("content", "l1", "l2", "l3", "_index.md"), fmt.Sprintf(pageTemplate, 3, -1))
           90 
           91         for level2 := 1; level2 < 4; level2++ {
           92                 writeSource(t, fs, filepath.Join("content", "l1", "l2", fmt.Sprintf("page_2_%d.md", level2)),
           93                         fmt.Sprintf(pageTemplate, 2, level2))
           94         }
           95         for level2 := 1; level2 < 3; level2++ {
           96                 writeSource(t, fs, filepath.Join("content", "l1", "l2_2", fmt.Sprintf("page_2_2_%d.md", level2)),
           97                         fmt.Sprintf(pageTemplate, 2, level2))
           98         }
           99         for level3 := 1; level3 < 3; level3++ {
          100                 writeSource(t, fs, filepath.Join("content", "l1", "l2", "l3", fmt.Sprintf("page_3_%d.md", level3)),
          101                         fmt.Sprintf(pageTemplate, 3, level3))
          102         }
          103 
          104         writeSource(t, fs, filepath.Join("content", "Spaces in Section", "page100.md"), fmt.Sprintf(pageTemplate, 10, 0))
          105 
          106         writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), "<html>Single|{{ .Title }}</html>")
          107         writeSource(t, fs, filepath.Join("layouts", "_default", "list.html"),
          108                 `
          109 {{ $sect := (.Site.GetPage "l1/l2") }}
          110 <html>List|{{ .Title }}|L1/l2-IsActive: {{ .InSection $sect }}
          111 {{ range .Paginator.Pages }}
          112 PAG|{{ .Title }}|{{ $sect.InSection . }}
          113 {{ end }}
          114 {{/* https://github.com/gohugoio/hugo/issues/4989 */}}
          115 {{ $sections := (.Site.GetPage "section" .Section).Sections.ByWeight }}
          116 </html>`)
          117 
          118         cfg.Set("pagination.pagerSize", 2)
          119 
          120         th, configs := newTestHelperFromProvider(cfg, fs, t)
          121 
          122         s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Configs: configs}, BuildCfg{})
          123 
          124         c.Assert(len(s.RegularPages()), qt.Equals, 21)
          125 
          126         tests := []struct {
          127                 sections string
          128                 verify   func(c *qt.C, p page.Page)
          129         }{
          130                 {"elsewhere", func(c *qt.C, p page.Page) {
          131                         c.Assert(len(p.Pages()), qt.Equals, 1)
          132                         for _, p := range p.Pages() {
          133                                 c.Assert(p.SectionsPath(), qt.Equals, "/elsewhere")
          134                         }
          135                 }},
          136                 {"post", func(c *qt.C, p page.Page) {
          137                         c.Assert(len(p.Pages()), qt.Equals, 2)
          138                         for _, p := range p.Pages() {
          139                                 c.Assert(p.Section(), qt.Equals, "post")
          140                         }
          141                 }},
          142                 {"empty1", func(c *qt.C, p page.Page) {
          143                         // > b,c
          144                         c.Assert(getPage(p, "/empty1/b"), qt.IsNil) // No _index.md page.
          145                         c.Assert(getPage(p, "/empty1/b/c"), qt.Not(qt.IsNil))
          146                 }},
          147                 {"empty2", func(c *qt.C, p page.Page) {
          148                         // > b,c,d where b and d have _index.md files.
          149                         b := getPage(p, "/empty2/b")
          150                         c.Assert(b, qt.Not(qt.IsNil))
          151                         c.Assert(b.Title(), qt.Equals, "T40_-1")
          152 
          153                         cp := getPage(p, "/empty2/b/c")
          154                         c.Assert(cp, qt.IsNil) // No _index.md
          155 
          156                         d := getPage(p, "/empty2/b/c/d")
          157                         c.Assert(d, qt.Not(qt.IsNil))
          158                         c.Assert(d.Title(), qt.Equals, "T41_-1")
          159 
          160                         c.Assert(cp.Eq(d), qt.Equals, false)
          161                         c.Assert(cp.Eq(cp), qt.Equals, true)
          162                         c.Assert(cp.Eq("asdf"), qt.Equals, false)
          163                 }},
          164                 {"empty3", func(c *qt.C, p page.Page) {
          165                         // b,c,d with regular page in b
          166                         b := getPage(p, "/empty3/b")
          167                         c.Assert(b, qt.IsNil) // No _index.md
          168                         e3 := getPage(p, "/empty3/b/empty3")
          169                         c.Assert(e3, qt.Not(qt.IsNil))
          170                         c.Assert(e3.File().LogicalName(), qt.Equals, "empty3.md")
          171                 }},
          172                 {"empty3", func(c *qt.C, p page.Page) {
          173                         xxx := getPage(p, "/empty3/nil")
          174                         c.Assert(xxx, qt.IsNil)
          175                 }},
          176                 {"top", func(c *qt.C, p page.Page) {
          177                         c.Assert(p.Title(), qt.Equals, "Tops")
          178                         c.Assert(len(p.Pages()), qt.Equals, 2)
          179                         c.Assert(p.Pages()[0].File().LogicalName(), qt.Equals, "mypage2.md")
          180                         c.Assert(p.Pages()[1].File().LogicalName(), qt.Equals, "mypage3.md")
          181                         home := p.Parent()
          182                         c.Assert(home.IsHome(), qt.Equals, true)
          183                         c.Assert(len(p.Sections()), qt.Equals, 0)
          184                         c.Assert(home.CurrentSection(), qt.Equals, home)
          185                         active := home.InSection(home)
          186                         c.Assert(active, qt.Equals, true)
          187                         c.Assert(p.FirstSection(), qt.Equals, p)
          188                         c.Assert(len(p.Ancestors()), qt.Equals, 1)
          189                 }},
          190                 {"l1", func(c *qt.C, p page.Page) {
          191                         c.Assert(p.Title(), qt.Equals, "L1s")
          192                         c.Assert(len(p.Pages()), qt.Equals, 4) // 2 pages + 2 sections
          193                         c.Assert(p.Parent().IsHome(), qt.Equals, true)
          194                         c.Assert(len(p.Sections()), qt.Equals, 2)
          195                         c.Assert(len(p.Ancestors()), qt.Equals, 1)
          196                 }},
          197                 {"l1,l2", func(c *qt.C, p page.Page) {
          198                         c.Assert(p.Title(), qt.Equals, "T2_-1")
          199                         c.Assert(len(p.Pages()), qt.Equals, 4) // 3 pages + 1 section
          200                         c.Assert(p.Pages()[0].Parent(), qt.Equals, p)
          201                         c.Assert(p.Parent().Title(), qt.Equals, "L1s")
          202                         c.Assert(p.RelPermalink(), qt.Equals, "/l1/l2/")
          203                         c.Assert(len(p.Sections()), qt.Equals, 1)
          204                         c.Assert(len(p.Ancestors()), qt.Equals, 2)
          205 
          206                         for _, child := range p.Pages() {
          207                                 if child.IsSection() {
          208                                         c.Assert(child.CurrentSection(), qt.Equals, child)
          209                                         continue
          210                                 }
          211 
          212                                 c.Assert(child.CurrentSection(), qt.Equals, p)
          213                                 active := child.InSection(p)
          214 
          215                                 c.Assert(active, qt.Equals, true)
          216                                 active = p.InSection(child)
          217                                 c.Assert(active, qt.Equals, true)
          218                                 active = p.InSection(getPage(p, "/"))
          219                                 c.Assert(active, qt.Equals, false)
          220 
          221                                 isAncestor := p.IsAncestor(child)
          222                                 c.Assert(isAncestor, qt.Equals, true)
          223                                 isAncestor = child.IsAncestor(p)
          224                                 c.Assert(isAncestor, qt.Equals, false)
          225 
          226                                 isDescendant := p.IsDescendant(child)
          227                                 c.Assert(isDescendant, qt.Equals, false)
          228                                 isDescendant = child.IsDescendant(p)
          229                                 c.Assert(isDescendant, qt.Equals, true)
          230                         }
          231 
          232                         c.Assert(p.Eq(p.CurrentSection()), qt.Equals, true)
          233                 }},
          234                 {"l1,l2_2", func(c *qt.C, p page.Page) {
          235                         c.Assert(p.Title(), qt.Equals, "T22_-1")
          236                         c.Assert(len(p.Pages()), qt.Equals, 2)
          237                         c.Assert(p.Pages()[0].File().Path(), qt.Equals, filepath.FromSlash("l1/l2_2/page_2_2_1.md"))
          238                         c.Assert(p.Parent().Title(), qt.Equals, "L1s")
          239                         c.Assert(len(p.Sections()), qt.Equals, 0)
          240                         c.Assert(len(p.Ancestors()), qt.Equals, 2)
          241                 }},
          242                 {"l1,l2,l3", func(c *qt.C, p page.Page) {
          243                         nilp, _ := p.GetPage("this/does/not/exist")
          244 
          245                         c.Assert(p.Title(), qt.Equals, "T3_-1")
          246                         c.Assert(len(p.Pages()), qt.Equals, 2)
          247                         c.Assert(p.Parent().Title(), qt.Equals, "T2_-1")
          248                         c.Assert(len(p.Sections()), qt.Equals, 0)
          249                         c.Assert(len(p.Ancestors()), qt.Equals, 3)
          250 
          251                         l1 := getPage(p, "/l1")
          252                         isDescendant := l1.IsDescendant(p)
          253                         c.Assert(isDescendant, qt.Equals, false)
          254                         isDescendant = l1.IsDescendant(nil)
          255                         c.Assert(isDescendant, qt.Equals, false)
          256                         isDescendant = nilp.IsDescendant(p)
          257                         c.Assert(isDescendant, qt.Equals, false)
          258                         isDescendant = p.IsDescendant(l1)
          259                         c.Assert(isDescendant, qt.Equals, true)
          260 
          261                         isAncestor := l1.IsAncestor(p)
          262                         c.Assert(isAncestor, qt.Equals, true)
          263                         isAncestor = p.IsAncestor(l1)
          264                         c.Assert(isAncestor, qt.Equals, false)
          265                         c.Assert(p.FirstSection(), qt.Equals, l1)
          266                         isAncestor = p.IsAncestor(nil)
          267                         c.Assert(isAncestor, qt.Equals, false)
          268                         c.Assert(isAncestor, qt.Equals, false)
          269 
          270                         l3 := getPage(p, "/l1/l2/l3")
          271                         c.Assert(l3.FirstSection(), qt.Equals, l1)
          272                 }},
          273                 {"perm a,link", func(c *qt.C, p page.Page) {
          274                         c.Assert(p.Title(), qt.Equals, "T9_-1")
          275                         c.Assert(p.RelPermalink(), qt.Equals, "/perm-a/link/")
          276                         c.Assert(len(p.Pages()), qt.Equals, 4)
          277                         first := p.Pages()[0]
          278                         c.Assert(first.RelPermalink(), qt.Equals, "/perm-a/link/t1_1/")
          279                         th.assertFileContent("public/perm-a/link/t1_1/index.html", "Single|T1_1")
          280 
          281                         last := p.Pages()[3]
          282                         c.Assert(last.RelPermalink(), qt.Equals, "/perm-a/link/t1_5/")
          283                 }},
          284         }
          285 
          286         home := s.getPageOldVersion(kinds.KindHome)
          287 
          288         for _, test := range tests {
          289                 test := test
          290                 tt.Run(fmt.Sprintf("sections %s", test.sections), func(c *qt.C) {
          291                         c.Parallel()
          292                         sections := strings.Split(test.sections, ",")
          293                         p := s.getPageOldVersion(kinds.KindSection, sections...)
          294                         c.Assert(p, qt.Not(qt.IsNil), qt.Commentf(fmt.Sprint(sections)))
          295 
          296                         if p.Pages() != nil {
          297                                 c.Assert(p.Data().(page.Data).Pages(), deepEqualsPages, p.Pages())
          298                         }
          299                         c.Assert(p.Parent(), qt.Not(qt.IsNil))
          300                         test.verify(c, p)
          301                 })
          302         }
          303 
          304         c.Assert(home, qt.Not(qt.IsNil))
          305         c.Assert(len(home.Ancestors()), qt.Equals, 0)
          306 
          307         c.Assert(len(home.Sections()), qt.Equals, 9)
          308         c.Assert(s.Sections(), deepEqualsPages, home.Sections())
          309 
          310         rootPage := s.getPageOldVersion(kinds.KindPage, "mypage.md")
          311         c.Assert(rootPage, qt.Not(qt.IsNil))
          312         c.Assert(rootPage.Parent().IsHome(), qt.Equals, true)
          313         // https://github.com/gohugoio/hugo/issues/6365
          314         c.Assert(rootPage.Sections(), qt.HasLen, 0)
          315 
          316         sectionWithSpace := s.getPageOldVersion(kinds.KindSection, "Spaces in Section")
          317         // s.h.pageTrees.debugPrint()
          318         c.Assert(sectionWithSpace, qt.Not(qt.IsNil))
          319         c.Assert(sectionWithSpace.RelPermalink(), qt.Equals, "/spaces-in-section/")
          320 
          321         th.assertFileContent("public/l1/l2/page/2/index.html", "L1/l2-IsActive: true", "PAG|T2_3|true")
          322 }
          323 
          324 func TestNextInSectionNested(t *testing.T) {
          325         t.Parallel()
          326 
          327         pageContent := `---
          328 title: "The Page"
          329 weight: %d
          330 ---
          331 Some content.
          332 `
          333         createPageContent := func(weight int) string {
          334                 return fmt.Sprintf(pageContent, weight)
          335         }
          336 
          337         b := newTestSitesBuilder(t)
          338         b.WithSimpleConfigFile()
          339         b.WithTemplates("_default/single.html", `
          340 Prev: {{ with .PrevInSection }}{{ .RelPermalink }}{{ end }}|
          341 Next: {{ with .NextInSection }}{{ .RelPermalink }}{{ end }}|
          342 `)
          343 
          344         b.WithContent("blog/page1.md", createPageContent(1))
          345         b.WithContent("blog/page2.md", createPageContent(2))
          346         b.WithContent("blog/cool/_index.md", createPageContent(1))
          347         b.WithContent("blog/cool/cool1.md", createPageContent(1))
          348         b.WithContent("blog/cool/cool2.md", createPageContent(2))
          349         b.WithContent("root1.md", createPageContent(1))
          350         b.WithContent("root2.md", createPageContent(2))
          351 
          352         b.Build(BuildCfg{})
          353 
          354         b.AssertFileContent("public/root1/index.html",
          355                 "Prev: /root2/|", "Next: |")
          356         b.AssertFileContent("public/root2/index.html",
          357                 "Prev: |", "Next: /root1/|")
          358         b.AssertFileContent("public/blog/page1/index.html",
          359                 "Prev: /blog/page2/|", "Next: |")
          360         b.AssertFileContent("public/blog/page2/index.html",
          361                 "Prev: |", "Next: /blog/page1/|")
          362         b.AssertFileContent("public/blog/cool/cool1/index.html",
          363                 "Prev: /blog/cool/cool2/|", "Next: |")
          364         b.AssertFileContent("public/blog/cool/cool2/index.html",
          365                 "Prev: |", "Next: /blog/cool/cool1/|")
          366 }
          367 
          368 func TestSectionEntries(t *testing.T) {
          369         t.Parallel()
          370 
          371         files := `
          372 -- hugo.toml --
          373 baseURL = "https://example.com/"
          374 -- content/myfirstsection/p1.md --
          375 ---
          376 title: "P1"
          377 ---
          378 P1
          379 -- content/a/b/c/_index.md --
          380 ---
          381 title: "C"
          382 ---
          383 C
          384 -- content/a/b/c/mybundle/index.md --
          385 ---
          386 title: "My Bundle"
          387 ---
          388 -- layouts/_default/list.html --
          389 Kind: {{ .Kind }}|RelPermalink: {{ .RelPermalink }}|SectionsPath: {{ .SectionsPath }}|SectionsEntries: {{ .SectionsEntries }}|Len: {{ len .SectionsEntries }}|
          390 -- layouts/_default/single.html --
          391 Kind: {{ .Kind }}|RelPermalink: {{ .RelPermalink }}|SectionsPath: {{ .SectionsPath }}|SectionsEntries: {{ .SectionsEntries }}|Len: {{ len .SectionsEntries }}|
          392 `
          393 
          394         b := Test(t, files)
          395 
          396         b.AssertFileContent("public/myfirstsection/p1/index.html", "RelPermalink: /myfirstsection/p1/|SectionsPath: /myfirstsection|SectionsEntries: [myfirstsection]|Len: 1")
          397         b.AssertFileContent("public/a/b/c/index.html", "RelPermalink: /a/b/c/|SectionsPath: /a/b/c|SectionsEntries: [a b c]|Len: 3")
          398         b.AssertFileContent("public/a/b/c/mybundle/index.html", "Kind: page|RelPermalink: /a/b/c/mybundle/|SectionsPath: /a/b/c|SectionsEntries: [a b c]|Len: 3")
          399         b.AssertFileContent("public/index.html", "Kind: home|RelPermalink: /|SectionsPath: /|SectionsEntries: []|Len: 0")
          400 }
          401 
          402 func TestParentWithPageOverlap(t *testing.T) {
          403         files := `
          404 -- hugo.toml --
          405 baseURL = "https://example.com/"
          406 -- content/docs/_index.md --
          407 -- content/docs/logs/_index.md --
          408 -- content/docs/logs/sdk.md --
          409 -- content/docs/logs/sdk_exporters/stdout.md --
          410 -- layouts/_default/list.html --
          411 {{ .RelPermalink }}|{{ with .Parent}}{{ .RelPermalink }}{{ end }}|
          412 -- layouts/_default/single.html --
          413 {{ .RelPermalink }}|{{ with .Parent}}{{ .RelPermalink }}{{ end }}|
          414 
          415 `
          416         b := Test(t, files)
          417 
          418         b.AssertFileContent("public/index.html", "/||")
          419         b.AssertFileContent("public/docs/index.html", "/docs/|/|")
          420         b.AssertFileContent("public/docs/logs/index.html", "/docs/logs/|/docs/|")
          421         b.AssertFileContent("public/docs/logs/sdk/index.html", "/docs/logs/sdk/|/docs/logs/|")
          422         b.AssertFileContent("public/docs/logs/sdk_exporters/stdout/index.html", "/docs/logs/sdk_exporters/stdout/|/docs/logs/|")
          423 }