github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/resources/page/permalinks_test.go (about)

     1  // Copyright 2023 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  	"regexp"
    19  	"strings"
    20  	"sync"
    21  	"testing"
    22  	"time"
    23  
    24  	qt "github.com/frankban/quicktest"
    25  )
    26  
    27  // testdataPermalinks is used by a couple of tests; the expandsTo content is
    28  // subject to the data in simplePageJSON.
    29  var testdataPermalinks = []struct {
    30  	spec      string
    31  	valid     bool
    32  	expandsTo string
    33  }{
    34  	{":title", true, "spf13-vim-3.0-release-and-new-website"},
    35  	{"/:year-:month-:title", true, "/2012-04-spf13-vim-3.0-release-and-new-website"},
    36  	{"/:year/:yearday/:month/:monthname/:day/:weekday/:weekdayname/", true, "/2012/97/04/April/06/5/Friday/"}, // Dates
    37  	{"/:section/", true, "/blue/"},                                  // Section
    38  	{"/:title/", true, "/spf13-vim-3.0-release-and-new-website/"},   // Title
    39  	{"/:slug/", true, "/the-slug/"},                                 // Slug
    40  	{"/:slugorfilename/", true, "/the-slug/"},                       // Slug or filename
    41  	{"/:filename/", true, "/test-page/"},                            // Filename
    42  	{"/:06-:1-:2-:Monday", true, "/12-4-6-Friday"},                  // Dates with Go formatting
    43  	{"/:2006_01_02_15_04_05.000", true, "/2012_04_06_03_01_59.000"}, // Complicated custom date format
    44  	{"/:sections/", true, "/a/b/c/"},                                // Sections
    45  	{"/:sections[last]/", true, "/c/"},                              // Sections
    46  	{"/:sections[0]/:sections[last]/", true, "/a/c/"},               // Sections
    47  
    48  	// Failures
    49  	{"/blog/:fred", false, ""},
    50  	{"/:year//:title", false, ""},
    51  	{"/:TITLE", false, ""},      // case is not normalized
    52  	{"/:2017", false, ""},       // invalid date format
    53  	{"/:2006-01-02", false, ""}, // valid date format but invalid attribute name
    54  }
    55  
    56  func urlize(uri string) string {
    57  	// This is just an approximation of the real urlize function.
    58  	return strings.ToLower(strings.ReplaceAll(uri, " ", "-"))
    59  }
    60  
    61  func TestPermalinkExpansion(t *testing.T) {
    62  	t.Parallel()
    63  
    64  	c := qt.New(t)
    65  
    66  	page := newTestPageWithFile("/test-page/index.md")
    67  	page.title = "Spf13 Vim 3.0 Release and new website"
    68  	d, _ := time.Parse("2006-01-02 15:04:05", "2012-04-06 03:01:59")
    69  	page.date = d
    70  	page.section = "blue"
    71  	page.slug = "The Slug"
    72  	page.kind = "page"
    73  
    74  	for _, item := range testdataPermalinks {
    75  		if !item.valid {
    76  			continue
    77  		}
    78  
    79  		specNameCleaner := regexp.MustCompile(`[\:\/\[\]]`)
    80  		name := specNameCleaner.ReplaceAllString(item.spec, "")
    81  
    82  		c.Run(name, func(c *qt.C) {
    83  			patterns := map[string]map[string]string{
    84  				"page": {
    85  					"posts": item.spec,
    86  				},
    87  			}
    88  			expander, err := NewPermalinkExpander(urlize, patterns)
    89  			c.Assert(err, qt.IsNil)
    90  			expanded, err := expander.Expand("posts", page)
    91  			c.Assert(err, qt.IsNil)
    92  			c.Assert(expanded, qt.Equals, item.expandsTo)
    93  		})
    94  
    95  	}
    96  }
    97  
    98  func TestPermalinkExpansionMultiSection(t *testing.T) {
    99  	t.Parallel()
   100  
   101  	c := qt.New(t)
   102  
   103  	page := newTestPage()
   104  	page.title = "Page Title"
   105  	d, _ := time.Parse("2006-01-02", "2012-04-06")
   106  	page.date = d
   107  	page.section = "blue"
   108  	page.slug = "The Slug"
   109  	page.kind = "page"
   110  
   111  	page_slug_fallback := newTestPageWithFile("/page-filename/index.md")
   112  	page_slug_fallback.title = "Page Title"
   113  	page_slug_fallback.kind = "page"
   114  
   115  	permalinksConfig := map[string]map[string]string{
   116  		"page": {
   117  			"posts":   "/:slug",
   118  			"blog":    "/:section/:year",
   119  			"recipes": "/:slugorfilename",
   120  		},
   121  	}
   122  	expander, err := NewPermalinkExpander(urlize, permalinksConfig)
   123  	c.Assert(err, qt.IsNil)
   124  
   125  	expanded, err := expander.Expand("posts", page)
   126  	c.Assert(err, qt.IsNil)
   127  	c.Assert(expanded, qt.Equals, "/the-slug")
   128  
   129  	expanded, err = expander.Expand("blog", page)
   130  	c.Assert(err, qt.IsNil)
   131  	c.Assert(expanded, qt.Equals, "/blue/2012")
   132  
   133  	expanded, err = expander.Expand("posts", page_slug_fallback)
   134  	c.Assert(err, qt.IsNil)
   135  	c.Assert(expanded, qt.Equals, "/page-title")
   136  
   137  	expanded, err = expander.Expand("recipes", page_slug_fallback)
   138  	c.Assert(err, qt.IsNil)
   139  	c.Assert(expanded, qt.Equals, "/page-filename")
   140  }
   141  
   142  func TestPermalinkExpansionConcurrent(t *testing.T) {
   143  	t.Parallel()
   144  
   145  	c := qt.New(t)
   146  
   147  	permalinksConfig := map[string]map[string]string{
   148  		"page": {
   149  			"posts": "/:slug/",
   150  		},
   151  	}
   152  
   153  	expander, err := NewPermalinkExpander(urlize, permalinksConfig)
   154  	c.Assert(err, qt.IsNil)
   155  
   156  	var wg sync.WaitGroup
   157  
   158  	for i := 1; i < 20; i++ {
   159  		wg.Add(1)
   160  		go func(i int) {
   161  			defer wg.Done()
   162  			page := newTestPage()
   163  			page.kind = "page"
   164  			for j := 1; j < 20; j++ {
   165  				page.slug = fmt.Sprintf("slug%d", i+j)
   166  				expanded, err := expander.Expand("posts", page)
   167  				c.Assert(err, qt.IsNil)
   168  				c.Assert(expanded, qt.Equals, fmt.Sprintf("/%s/", page.slug))
   169  			}
   170  		}(i)
   171  	}
   172  
   173  	wg.Wait()
   174  }
   175  
   176  func TestPermalinkExpansionSliceSyntax(t *testing.T) {
   177  	t.Parallel()
   178  
   179  	c := qt.New(t)
   180  	exp, err := NewPermalinkExpander(urlize, nil)
   181  	c.Assert(err, qt.IsNil)
   182  	slice4 := []string{"a", "b", "c", "d"}
   183  	fn4 := func(s string) []string {
   184  		return exp.toSliceFunc(s)(slice4)
   185  	}
   186  
   187  	slice1 := []string{"a"}
   188  	fn1 := func(s string) []string {
   189  		return exp.toSliceFunc(s)(slice1)
   190  	}
   191  
   192  	c.Run("Basic", func(c *qt.C) {
   193  		c.Assert(fn4("[1:3]"), qt.DeepEquals, []string{"b", "c"})
   194  		c.Assert(fn4("[1:]"), qt.DeepEquals, []string{"b", "c", "d"})
   195  		c.Assert(fn4("[:2]"), qt.DeepEquals, []string{"a", "b"})
   196  		c.Assert(fn4("[0:2]"), qt.DeepEquals, []string{"a", "b"})
   197  		c.Assert(fn4("[:]"), qt.DeepEquals, []string{"a", "b", "c", "d"})
   198  		c.Assert(fn4(""), qt.DeepEquals, []string{"a", "b", "c", "d"})
   199  		c.Assert(fn4("[last]"), qt.DeepEquals, []string{"d"})
   200  		c.Assert(fn4("[:last]"), qt.DeepEquals, []string{"a", "b", "c"})
   201  		c.Assert(fn1("[last]"), qt.DeepEquals, []string{"a"})
   202  		c.Assert(fn1("[:last]"), qt.DeepEquals, []string{})
   203  		c.Assert(fn1("[1:last]"), qt.DeepEquals, []string{})
   204  		c.Assert(fn1("[1]"), qt.DeepEquals, []string{})
   205  
   206  	})
   207  
   208  	c.Run("Out of bounds", func(c *qt.C) {
   209  		c.Assert(fn4("[1:5]"), qt.DeepEquals, []string{"b", "c", "d"})
   210  		c.Assert(fn4("[-1:5]"), qt.DeepEquals, []string{"a", "b", "c", "d"})
   211  		c.Assert(fn4("[5:]"), qt.DeepEquals, []string{})
   212  		c.Assert(fn4("[5:]"), qt.DeepEquals, []string{})
   213  		c.Assert(fn4("[5:32]"), qt.DeepEquals, []string{})
   214  		c.Assert(exp.toSliceFunc("[:1]")(nil), qt.DeepEquals, []string(nil))
   215  		c.Assert(exp.toSliceFunc("[:1]")([]string{}), qt.DeepEquals, []string(nil))
   216  
   217  		// These all return nil
   218  		c.Assert(fn4("[]"), qt.IsNil)
   219  		c.Assert(fn4("[1:}"), qt.IsNil)
   220  		c.Assert(fn4("foo"), qt.IsNil)
   221  
   222  	})
   223  
   224  }
   225  
   226  func BenchmarkPermalinkExpand(b *testing.B) {
   227  	page := newTestPage()
   228  	page.title = "Hugo Rocks"
   229  	d, _ := time.Parse("2006-01-02", "2019-02-28")
   230  	page.date = d
   231  	page.kind = "page"
   232  
   233  	permalinksConfig := map[string]map[string]string{
   234  		"page": {
   235  			"posts": "/:year-:month-:title",
   236  		},
   237  	}
   238  	expander, err := NewPermalinkExpander(urlize, permalinksConfig)
   239  	if err != nil {
   240  		b.Fatal(err)
   241  	}
   242  
   243  	b.ResetTimer()
   244  	for i := 0; i < b.N; i++ {
   245  		s, err := expander.Expand("posts", page)
   246  		if err != nil {
   247  			b.Fatal(err)
   248  		}
   249  		if s != "/2019-02-hugo-rocks" {
   250  			b.Fatal(s)
   251  		}
   252  
   253  	}
   254  }