github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/hugolib/alias_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 hugolib
    15  
    16  import (
    17  	"path/filepath"
    18  	"runtime"
    19  	"testing"
    20  
    21  	"github.com/gohugoio/hugo/common/loggers"
    22  
    23  	qt "github.com/frankban/quicktest"
    24  )
    25  
    26  const pageWithAlias = `---
    27  title: Has Alias
    28  aliases: ["/foo/bar/", "rel"]
    29  ---
    30  For some moments the old man did not reply. He stood with bowed head, buried in deep thought. But at last he spoke.
    31  `
    32  
    33  const pageWithAliasMultipleOutputs = `---
    34  title: Has Alias for HTML and AMP
    35  aliases: ["/foo/bar/"]
    36  outputs: ["HTML", "AMP", "JSON"]
    37  ---
    38  For some moments the old man did not reply. He stood with bowed head, buried in deep thought. But at last he spoke.
    39  `
    40  
    41  const (
    42  	basicTemplate = "<html><body>{{.Content}}</body></html>"
    43  	aliasTemplate = "<html><body>ALIASTEMPLATE</body></html>"
    44  )
    45  
    46  func TestAlias(t *testing.T) {
    47  	t.Parallel()
    48  	c := qt.New(t)
    49  
    50  	tests := []struct {
    51  		fileSuffix string
    52  		urlPrefix  string
    53  		urlSuffix  string
    54  		settings   map[string]interface{}
    55  	}{
    56  		{"/index.html", "http://example.com", "/", map[string]interface{}{"baseURL": "http://example.com"}},
    57  		{"/index.html", "http://example.com/some/path", "/", map[string]interface{}{"baseURL": "http://example.com/some/path"}},
    58  		{"/index.html", "http://example.com", "/", map[string]interface{}{"baseURL": "http://example.com", "canonifyURLs": true}},
    59  		{"/index.html", "../..", "/", map[string]interface{}{"relativeURLs": true}},
    60  		{".html", "", ".html", map[string]interface{}{"uglyURLs": true}},
    61  	}
    62  
    63  	for _, test := range tests {
    64  		b := newTestSitesBuilder(t)
    65  		b.WithSimpleConfigFileAndSettings(test.settings).WithContent("blog/page.md", pageWithAlias)
    66  		b.CreateSites().Build(BuildCfg{})
    67  
    68  		c.Assert(len(b.H.Sites), qt.Equals, 1)
    69  		c.Assert(len(b.H.Sites[0].RegularPages()), qt.Equals, 1)
    70  
    71  		// the real page
    72  		b.AssertFileContent("public/blog/page"+test.fileSuffix, "For some moments the old man")
    73  		// the alias redirectors
    74  		b.AssertFileContent("public/foo/bar"+test.fileSuffix, "<meta http-equiv=\"refresh\" content=\"0; url="+test.urlPrefix+"/blog/page"+test.urlSuffix+"\" />")
    75  		b.AssertFileContent("public/blog/rel"+test.fileSuffix, "<meta http-equiv=\"refresh\" content=\"0; url="+test.urlPrefix+"/blog/page"+test.urlSuffix+"\" />")
    76  	}
    77  }
    78  
    79  func TestAliasMultipleOutputFormats(t *testing.T) {
    80  	t.Parallel()
    81  
    82  	c := qt.New(t)
    83  
    84  	b := newTestSitesBuilder(t)
    85  	b.WithSimpleConfigFile().WithContent("blog/page.md", pageWithAliasMultipleOutputs)
    86  
    87  	b.WithTemplates(
    88  		"_default/single.html", basicTemplate,
    89  		"_default/single.amp.html", basicTemplate,
    90  		"_default/single.json", basicTemplate)
    91  
    92  	b.CreateSites().Build(BuildCfg{})
    93  
    94  	// the real pages
    95  	b.AssertFileContent("public/blog/page/index.html", "For some moments the old man")
    96  	b.AssertFileContent("public/amp/blog/page/index.html", "For some moments the old man")
    97  	b.AssertFileContent("public/blog/page/index.json", "For some moments the old man")
    98  
    99  	// the alias redirectors
   100  	b.AssertFileContent("public/foo/bar/index.html", "<meta http-equiv=\"refresh\" content=\"0; ")
   101  	b.AssertFileContent("public/amp/foo/bar/index.html", "<meta http-equiv=\"refresh\" content=\"0; ")
   102  	c.Assert(b.CheckExists("public/foo/bar/index.json"), qt.Equals, false)
   103  }
   104  
   105  func TestAliasTemplate(t *testing.T) {
   106  	t.Parallel()
   107  
   108  	b := newTestSitesBuilder(t)
   109  	b.WithSimpleConfigFile().WithContent("page.md", pageWithAlias).WithTemplatesAdded("alias.html", aliasTemplate)
   110  
   111  	b.CreateSites().Build(BuildCfg{})
   112  
   113  	// the real page
   114  	b.AssertFileContent("public/page/index.html", "For some moments the old man")
   115  	// the alias redirector
   116  	b.AssertFileContent("public/foo/bar/index.html", "ALIASTEMPLATE")
   117  }
   118  
   119  func TestTargetPathHTMLRedirectAlias(t *testing.T) {
   120  	h := newAliasHandler(nil, loggers.NewErrorLogger(), false)
   121  
   122  	errIsNilForThisOS := runtime.GOOS != "windows"
   123  
   124  	tests := []struct {
   125  		value    string
   126  		expected string
   127  		errIsNil bool
   128  	}{
   129  		{"", "", false},
   130  		{"s", filepath.FromSlash("s/index.html"), true},
   131  		{"/", "", false},
   132  		{"alias 1", filepath.FromSlash("alias 1/index.html"), true},
   133  		{"alias 2/", filepath.FromSlash("alias 2/index.html"), true},
   134  		{"alias 3.html", "alias 3.html", true},
   135  		{"alias4.html", "alias4.html", true},
   136  		{"/alias 5.html", "alias 5.html", true},
   137  		{"/трям.html", "трям.html", true},
   138  		{"../../../../tmp/passwd", "", false},
   139  		{"/foo/../../../../tmp/passwd", filepath.FromSlash("tmp/passwd/index.html"), true},
   140  		{"foo/../../../../tmp/passwd", "", false},
   141  		{"C:\\Windows", filepath.FromSlash("C:\\Windows/index.html"), errIsNilForThisOS},
   142  		{"/trailing-space /", filepath.FromSlash("trailing-space /index.html"), errIsNilForThisOS},
   143  		{"/trailing-period./", filepath.FromSlash("trailing-period./index.html"), errIsNilForThisOS},
   144  		{"/tab\tseparated/", filepath.FromSlash("tab\tseparated/index.html"), errIsNilForThisOS},
   145  		{"/chrome/?p=help&ctx=keyboard#topic=3227046", filepath.FromSlash("chrome/?p=help&ctx=keyboard#topic=3227046/index.html"), errIsNilForThisOS},
   146  		{"/LPT1/Printer/", filepath.FromSlash("LPT1/Printer/index.html"), errIsNilForThisOS},
   147  	}
   148  
   149  	for _, test := range tests {
   150  		path, err := h.targetPathAlias(test.value)
   151  		if (err == nil) != test.errIsNil {
   152  			t.Errorf("Expected err == nil => %t, got: %t. err: %s", test.errIsNil, err == nil, err)
   153  			continue
   154  		}
   155  		if err == nil && path != test.expected {
   156  			t.Errorf("Expected: %q, got: %q", test.expected, path)
   157  		}
   158  	}
   159  }