github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/resources/page/page_paths_test.go (about)

     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 page
    15  
    16  import (
    17  	"fmt"
    18  	"path/filepath"
    19  	"strings"
    20  	"testing"
    21  
    22  	"github.com/gohugoio/hugo/media"
    23  
    24  	"github.com/gohugoio/hugo/output"
    25  )
    26  
    27  func TestPageTargetPath(t *testing.T) {
    28  	pathSpec := newTestPathSpec()
    29  
    30  	noExtNoDelimMediaType := media.WithDelimiterAndSuffixes(media.TextType, "", "")
    31  	noExtNoDelimMediaType.Delimiter = ""
    32  
    33  	// Netlify style _redirects
    34  	noExtDelimFormat := output.Format{
    35  		Name:      "NER",
    36  		MediaType: noExtNoDelimMediaType,
    37  		BaseName:  "_redirects",
    38  	}
    39  
    40  	for _, langPrefixPath := range []string{"", "no"} {
    41  		for _, langPrefixLink := range []string{"", "no"} {
    42  			for _, uglyURLs := range []bool{false, true} {
    43  
    44  				tests := []struct {
    45  					name     string
    46  					d        TargetPathDescriptor
    47  					expected TargetPaths
    48  				}{
    49  					{"JSON home", TargetPathDescriptor{Kind: KindHome, Type: output.JSONFormat}, TargetPaths{TargetFilename: "/index.json", SubResourceBaseTarget: "", Link: "/index.json"}},
    50  					{"AMP home", TargetPathDescriptor{Kind: KindHome, Type: output.AMPFormat}, TargetPaths{TargetFilename: "/amp/index.html", SubResourceBaseTarget: "/amp", Link: "/amp/"}},
    51  					{"HTML home", TargetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: output.HTMLFormat}, TargetPaths{TargetFilename: "/index.html", SubResourceBaseTarget: "", Link: "/"}},
    52  					{"Netlify redirects", TargetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: noExtDelimFormat}, TargetPaths{TargetFilename: "/_redirects", SubResourceBaseTarget: "", Link: "/_redirects"}},
    53  					{"HTML section list", TargetPathDescriptor{
    54  						Kind:     KindSection,
    55  						Sections: []string{"sect1"},
    56  						BaseName: "_index",
    57  						Type:     output.HTMLFormat,
    58  					}, TargetPaths{TargetFilename: "/sect1/index.html", SubResourceBaseTarget: "/sect1", Link: "/sect1/"}},
    59  					{"HTML taxonomy term", TargetPathDescriptor{
    60  						Kind:     KindTerm,
    61  						Sections: []string{"tags", "hugo"},
    62  						BaseName: "_index",
    63  						Type:     output.HTMLFormat,
    64  					}, TargetPaths{TargetFilename: "/tags/hugo/index.html", SubResourceBaseTarget: "/tags/hugo", Link: "/tags/hugo/"}},
    65  					{"HTML taxonomy", TargetPathDescriptor{
    66  						Kind:     KindTaxonomy,
    67  						Sections: []string{"tags"},
    68  						BaseName: "_index",
    69  						Type:     output.HTMLFormat,
    70  					}, TargetPaths{TargetFilename: "/tags/index.html", SubResourceBaseTarget: "/tags", Link: "/tags/"}},
    71  					{
    72  						"HTML page", TargetPathDescriptor{
    73  							Kind:     KindPage,
    74  							Dir:      "/a/b",
    75  							BaseName: "mypage",
    76  							Sections: []string{"a"},
    77  							Type:     output.HTMLFormat,
    78  						}, TargetPaths{TargetFilename: "/a/b/mypage/index.html", SubResourceBaseTarget: "/a/b/mypage", Link: "/a/b/mypage/"},
    79  					},
    80  
    81  					{
    82  						"HTML page with index as base", TargetPathDescriptor{
    83  							Kind:     KindPage,
    84  							Dir:      "/a/b",
    85  							BaseName: "index",
    86  							Sections: []string{"a"},
    87  							Type:     output.HTMLFormat,
    88  						}, TargetPaths{TargetFilename: "/a/b/index.html", SubResourceBaseTarget: "/a/b", Link: "/a/b/"},
    89  					},
    90  
    91  					{
    92  						"HTML page with special chars", TargetPathDescriptor{
    93  							Kind:     KindPage,
    94  							Dir:      "/a/b",
    95  							BaseName: "My Page!",
    96  							Type:     output.HTMLFormat,
    97  						}, TargetPaths{TargetFilename: "/a/b/my-page/index.html", SubResourceBaseTarget: "/a/b/my-page", Link: "/a/b/my-page/"},
    98  					},
    99  					{"RSS home", TargetPathDescriptor{Kind: "rss", Type: output.RSSFormat}, TargetPaths{TargetFilename: "/index.xml", SubResourceBaseTarget: "", Link: "/index.xml"}},
   100  					{"RSS section list", TargetPathDescriptor{
   101  						Kind:     "rss",
   102  						Sections: []string{"sect1"},
   103  						Type:     output.RSSFormat,
   104  					}, TargetPaths{TargetFilename: "/sect1/index.xml", SubResourceBaseTarget: "/sect1", Link: "/sect1/index.xml"}},
   105  					{
   106  						"AMP page", TargetPathDescriptor{
   107  							Kind:     KindPage,
   108  							Dir:      "/a/b/c",
   109  							BaseName: "myamp",
   110  							Type:     output.AMPFormat,
   111  						}, TargetPaths{TargetFilename: "/amp/a/b/c/myamp/index.html", SubResourceBaseTarget: "/amp/a/b/c/myamp", Link: "/amp/a/b/c/myamp/"},
   112  					},
   113  					{
   114  						"AMP page with URL with suffix", TargetPathDescriptor{
   115  							Kind:     KindPage,
   116  							Dir:      "/sect/",
   117  							BaseName: "mypage",
   118  							URL:      "/some/other/url.xhtml",
   119  							Type:     output.HTMLFormat,
   120  						}, TargetPaths{TargetFilename: "/some/other/url.xhtml", SubResourceBaseTarget: "/some/other", Link: "/some/other/url.xhtml"},
   121  					},
   122  					{
   123  						"JSON page with URL without suffix", TargetPathDescriptor{
   124  							Kind:     KindPage,
   125  							Dir:      "/sect/",
   126  							BaseName: "mypage",
   127  							URL:      "/some/other/path/",
   128  							Type:     output.JSONFormat,
   129  						}, TargetPaths{TargetFilename: "/some/other/path/index.json", SubResourceBaseTarget: "/some/other/path", Link: "/some/other/path/index.json"},
   130  					},
   131  					{
   132  						"JSON page with URL without suffix and no trailing slash", TargetPathDescriptor{
   133  							Kind:     KindPage,
   134  							Dir:      "/sect/",
   135  							BaseName: "mypage",
   136  							URL:      "/some/other/path",
   137  							Type:     output.JSONFormat,
   138  						}, TargetPaths{TargetFilename: "/some/other/path/index.json", SubResourceBaseTarget: "/some/other/path", Link: "/some/other/path/index.json"},
   139  					},
   140  					{
   141  						"HTML page with URL without suffix and no trailing slash", TargetPathDescriptor{
   142  							Kind:     KindPage,
   143  							Dir:      "/sect/",
   144  							BaseName: "mypage",
   145  							URL:      "/some/other/path",
   146  							Type:     output.HTMLFormat,
   147  						}, TargetPaths{TargetFilename: "/some/other/path/index.html", SubResourceBaseTarget: "/some/other/path", Link: "/some/other/path/"},
   148  					},
   149  					{
   150  						"HTML page with URL containing double hyphen", TargetPathDescriptor{
   151  							Kind:     KindPage,
   152  							Dir:      "/sect/",
   153  							BaseName: "mypage",
   154  							URL:      "/some/other--url/",
   155  							Type:     output.HTMLFormat,
   156  						}, TargetPaths{TargetFilename: "/some/other--url/index.html", SubResourceBaseTarget: "/some/other--url", Link: "/some/other--url/"},
   157  					},
   158  					{
   159  						"HTML page with expanded permalink", TargetPathDescriptor{
   160  							Kind:              KindPage,
   161  							Dir:               "/a/b",
   162  							BaseName:          "mypage",
   163  							ExpandedPermalink: "/2017/10/my-title/",
   164  							Type:              output.HTMLFormat,
   165  						}, TargetPaths{TargetFilename: "/2017/10/my-title/index.html", SubResourceBaseTarget: "/2017/10/my-title", Link: "/2017/10/my-title/"},
   166  					},
   167  					{
   168  						"Paginated HTML home", TargetPathDescriptor{
   169  							Kind:     KindHome,
   170  							BaseName: "_index",
   171  							Type:     output.HTMLFormat,
   172  							Addends:  "page/3",
   173  						}, TargetPaths{TargetFilename: "/page/3/index.html", SubResourceBaseTarget: "/page/3", Link: "/page/3/"},
   174  					},
   175  					{
   176  						"Paginated Taxonomy terms list", TargetPathDescriptor{
   177  							Kind:     KindTerm,
   178  							BaseName: "_index",
   179  							Sections: []string{"tags", "hugo"},
   180  							Type:     output.HTMLFormat,
   181  							Addends:  "page/3",
   182  						}, TargetPaths{TargetFilename: "/tags/hugo/page/3/index.html", SubResourceBaseTarget: "/tags/hugo/page/3", Link: "/tags/hugo/page/3/"},
   183  					},
   184  					{
   185  						"Regular page with addend", TargetPathDescriptor{
   186  							Kind:     KindPage,
   187  							Dir:      "/a/b",
   188  							BaseName: "mypage",
   189  							Addends:  "c/d/e",
   190  							Type:     output.HTMLFormat,
   191  						}, TargetPaths{TargetFilename: "/a/b/mypage/c/d/e/index.html", SubResourceBaseTarget: "/a/b/mypage/c/d/e", Link: "/a/b/mypage/c/d/e/"},
   192  					},
   193  				}
   194  
   195  				for i, test := range tests {
   196  					t.Run(fmt.Sprintf("langPrefixPath=%s,langPrefixLink=%s,uglyURLs=%t,name=%s", langPrefixPath, langPrefixLink, uglyURLs, test.name),
   197  						func(t *testing.T) {
   198  							test.d.ForcePrefix = true
   199  							test.d.PathSpec = pathSpec
   200  							test.d.UglyURLs = uglyURLs
   201  							test.d.PrefixFilePath = langPrefixPath
   202  							test.d.PrefixLink = langPrefixLink
   203  							test.d.Dir = filepath.FromSlash(test.d.Dir)
   204  							isUgly := uglyURLs && !test.d.Type.NoUgly
   205  
   206  							expected := test.expected
   207  
   208  							// TODO(bep) simplify
   209  							if test.d.Kind == KindPage && test.d.BaseName == test.d.Type.BaseName {
   210  							} else if test.d.Kind == KindHome && test.d.Type.Path != "" {
   211  							} else if test.d.Type.MediaType.FirstSuffix.Suffix != "" && (!strings.HasPrefix(expected.TargetFilename, "/index") || test.d.Addends != "") && test.d.URL == "" && isUgly {
   212  								expected.TargetFilename = strings.Replace(expected.TargetFilename,
   213  									"/"+test.d.Type.BaseName+"."+test.d.Type.MediaType.FirstSuffix.Suffix,
   214  									"."+test.d.Type.MediaType.FirstSuffix.Suffix, 1)
   215  								expected.Link = strings.TrimSuffix(expected.Link, "/") + "." + test.d.Type.MediaType.FirstSuffix.Suffix
   216  
   217  							}
   218  
   219  							if test.d.PrefixFilePath != "" && !strings.HasPrefix(test.d.URL, "/"+test.d.PrefixFilePath) {
   220  								expected.TargetFilename = "/" + test.d.PrefixFilePath + expected.TargetFilename
   221  								expected.SubResourceBaseTarget = "/" + test.d.PrefixFilePath + expected.SubResourceBaseTarget
   222  							}
   223  
   224  							if test.d.PrefixLink != "" && !strings.HasPrefix(test.d.URL, "/"+test.d.PrefixLink) {
   225  								expected.Link = "/" + test.d.PrefixLink + expected.Link
   226  							}
   227  
   228  							expected.TargetFilename = filepath.FromSlash(expected.TargetFilename)
   229  							expected.SubResourceBaseTarget = filepath.FromSlash(expected.SubResourceBaseTarget)
   230  
   231  							pagePath := CreateTargetPaths(test.d)
   232  
   233  							if !eqTargetPaths(pagePath, expected) {
   234  								t.Fatalf("[%d] [%s] targetPath expected\n%#v, got:\n%#v", i, test.name, expected, pagePath)
   235  							}
   236  						})
   237  				}
   238  			}
   239  		}
   240  	}
   241  }
   242  
   243  func TestPageTargetPathPrefix(t *testing.T) {
   244  	pathSpec := newTestPathSpec()
   245  	tests := []struct {
   246  		name     string
   247  		d        TargetPathDescriptor
   248  		expected TargetPaths
   249  	}{
   250  		{
   251  			"URL set, prefix both, no force",
   252  			TargetPathDescriptor{Kind: KindPage, Type: output.JSONFormat, URL: "/mydir/my.json", ForcePrefix: false, PrefixFilePath: "pf", PrefixLink: "pl"},
   253  			TargetPaths{TargetFilename: "/mydir/my.json", SubResourceBaseTarget: "/mydir", SubResourceBaseLink: "/mydir", Link: "/mydir/my.json"},
   254  		},
   255  		{
   256  			"URL set, prefix both, force",
   257  			TargetPathDescriptor{Kind: KindPage, Type: output.JSONFormat, URL: "/mydir/my.json", ForcePrefix: true, PrefixFilePath: "pf", PrefixLink: "pl"},
   258  			TargetPaths{TargetFilename: "/pf/mydir/my.json", SubResourceBaseTarget: "/pf/mydir", SubResourceBaseLink: "/pl/mydir", Link: "/pl/mydir/my.json"},
   259  		},
   260  	}
   261  
   262  	for i, test := range tests {
   263  		t.Run(fmt.Sprintf(test.name),
   264  			func(t *testing.T) {
   265  				test.d.PathSpec = pathSpec
   266  				expected := test.expected
   267  				expected.TargetFilename = filepath.FromSlash(expected.TargetFilename)
   268  				expected.SubResourceBaseTarget = filepath.FromSlash(expected.SubResourceBaseTarget)
   269  
   270  				pagePath := CreateTargetPaths(test.d)
   271  
   272  				if pagePath != expected {
   273  					t.Fatalf("[%d] [%s] targetPath expected\n%#v, got:\n%#v", i, test.name, expected, pagePath)
   274  				}
   275  			})
   276  	}
   277  }
   278  
   279  func eqTargetPaths(p1, p2 TargetPaths) bool {
   280  	if p1.Link != p2.Link {
   281  		return false
   282  	}
   283  
   284  	if p1.SubResourceBaseTarget != p2.SubResourceBaseTarget {
   285  		return false
   286  	}
   287  
   288  	if p1.TargetFilename != p2.TargetFilename {
   289  		return false
   290  	}
   291  
   292  	return true
   293  }