github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/resources/page/pages_sort_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  	"context"
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/gohugoio/hugo/resources/resource"
    23  	"github.com/google/go-cmp/cmp"
    24  
    25  	qt "github.com/frankban/quicktest"
    26  )
    27  
    28  var eq = qt.CmpEquals(
    29  	cmp.Comparer(func(p1, p2 testPage) bool {
    30  		return p1.path == p2.path && p1.weight == p2.weight
    31  	}),
    32  )
    33  
    34  func TestDefaultSort(t *testing.T) {
    35  	t.Parallel()
    36  	c := qt.New(t)
    37  	d1 := time.Now()
    38  	d2 := d1.Add(-1 * time.Hour)
    39  	d3 := d1.Add(-2 * time.Hour)
    40  	d4 := d1.Add(-3 * time.Hour)
    41  
    42  	p := createSortTestPages(4)
    43  
    44  	// first by weight
    45  	setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "a", "c", "d"}, [4]int{4, 3, 2, 1}, p)
    46  	SortByDefault(p)
    47  
    48  	c.Assert(p[0].Weight(), qt.Equals, 1)
    49  
    50  	// Consider zero weight, issue #2673
    51  	setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "a", "d", "c"}, [4]int{0, 0, 0, 1}, p)
    52  	SortByDefault(p)
    53  
    54  	c.Assert(p[0].Weight(), qt.Equals, 1)
    55  
    56  	// next by date
    57  	setSortVals([4]time.Time{d3, d4, d1, d2}, [4]string{"a", "b", "c", "d"}, [4]int{1, 1, 1, 1}, p)
    58  	SortByDefault(p)
    59  	c.Assert(p[0].Date(), qt.Equals, d1)
    60  
    61  	// finally by link title
    62  	setSortVals([4]time.Time{d3, d3, d3, d3}, [4]string{"b", "c", "a", "d"}, [4]int{1, 1, 1, 1}, p)
    63  	SortByDefault(p)
    64  	c.Assert(p[0].LinkTitle(), qt.Equals, "al")
    65  	c.Assert(p[1].LinkTitle(), qt.Equals, "bl")
    66  	c.Assert(p[2].LinkTitle(), qt.Equals, "cl")
    67  }
    68  
    69  // https://github.com/gohugoio/hugo/issues/4953
    70  func TestSortByLinkTitle(t *testing.T) {
    71  	t.Parallel()
    72  	c := qt.New(t)
    73  	pages := createSortTestPages(6)
    74  
    75  	for i, p := range pages {
    76  		pp := p.(*testPage)
    77  		if i < 5 {
    78  			pp.title = fmt.Sprintf("title%d", i)
    79  		}
    80  
    81  		if i > 2 {
    82  			pp.linkTitle = fmt.Sprintf("linkTitle%d", i)
    83  		}
    84  
    85  	}
    86  
    87  	pages.shuffle()
    88  
    89  	bylt := pages.ByLinkTitle()
    90  
    91  	for i, p := range bylt {
    92  		if i < 3 {
    93  			c.Assert(p.LinkTitle(), qt.Equals, fmt.Sprintf("linkTitle%d", i+3))
    94  		} else {
    95  			c.Assert(p.LinkTitle(), qt.Equals, fmt.Sprintf("title%d", i-3))
    96  		}
    97  	}
    98  }
    99  
   100  func TestSortByN(t *testing.T) {
   101  	t.Parallel()
   102  	d1 := time.Now()
   103  	d2 := d1.Add(-2 * time.Hour)
   104  	d3 := d1.Add(-10 * time.Hour)
   105  	d4 := d1.Add(-20 * time.Hour)
   106  
   107  	p := createSortTestPages(4)
   108  	ctx := context.Background()
   109  
   110  	byLen := func(p Pages) Pages {
   111  		return p.ByLength(ctx)
   112  
   113  	}
   114  
   115  	for i, this := range []struct {
   116  		sortFunc   func(p Pages) Pages
   117  		assertFunc func(p Pages) bool
   118  	}{
   119  		{(Pages).ByWeight, func(p Pages) bool { return p[0].Weight() == 1 }},
   120  		{(Pages).ByTitle, func(p Pages) bool { return p[0].Title() == "ab" }},
   121  		{(Pages).ByLinkTitle, func(p Pages) bool { return p[0].LinkTitle() == "abl" }},
   122  		{(Pages).ByDate, func(p Pages) bool { return p[0].Date() == d4 }},
   123  		{(Pages).ByPublishDate, func(p Pages) bool { return p[0].PublishDate() == d4 }},
   124  		{(Pages).ByExpiryDate, func(p Pages) bool { return p[0].ExpiryDate() == d4 }},
   125  		{(Pages).ByLastmod, func(p Pages) bool { return p[1].Lastmod() == d3 }},
   126  		{byLen, func(p Pages) bool { return p[0].(resource.LengthProvider).Len(ctx) == len(p[0].(*testPage).content) }},
   127  	} {
   128  		setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "ab", "cde", "fg"}, [4]int{0, 3, 2, 1}, p)
   129  
   130  		sorted := this.sortFunc(p)
   131  		if !this.assertFunc(sorted) {
   132  			t.Errorf("[%d] sort error", i)
   133  		}
   134  	}
   135  }
   136  
   137  func TestLimit(t *testing.T) {
   138  	t.Parallel()
   139  	c := qt.New(t)
   140  	p := createSortTestPages(10)
   141  	firstFive := p.Limit(5)
   142  	c.Assert(len(firstFive), qt.Equals, 5)
   143  	for i := 0; i < 5; i++ {
   144  		c.Assert(firstFive[i], qt.Equals, p[i])
   145  	}
   146  	c.Assert(p.Limit(10), eq, p)
   147  	c.Assert(p.Limit(11), eq, p)
   148  }
   149  
   150  func TestPageSortReverse(t *testing.T) {
   151  	t.Parallel()
   152  	c := qt.New(t)
   153  	p1 := createSortTestPages(10)
   154  	c.Assert(p1[0].(*testPage).fuzzyWordCount, qt.Equals, 0)
   155  	c.Assert(p1[9].(*testPage).fuzzyWordCount, qt.Equals, 9)
   156  	p2 := p1.Reverse()
   157  	c.Assert(p2[0].(*testPage).fuzzyWordCount, qt.Equals, 9)
   158  	c.Assert(p2[9].(*testPage).fuzzyWordCount, qt.Equals, 0)
   159  	// cached
   160  	c.Assert(pagesEqual(p2, p1.Reverse()), qt.Equals, true)
   161  }
   162  
   163  func TestPageSortByParam(t *testing.T) {
   164  	t.Parallel()
   165  	c := qt.New(t)
   166  	var k any = "arbitrarily.nested"
   167  
   168  	unsorted := createSortTestPages(10)
   169  	delete(unsorted[9].Params(), "arbitrarily")
   170  
   171  	firstSetValue, _ := unsorted[0].Param(k)
   172  	secondSetValue, _ := unsorted[1].Param(k)
   173  	lastSetValue, _ := unsorted[8].Param(k)
   174  	unsetValue, _ := unsorted[9].Param(k)
   175  
   176  	c.Assert(firstSetValue, qt.Equals, "xyz100")
   177  	c.Assert(secondSetValue, qt.Equals, "xyz99")
   178  	c.Assert(lastSetValue, qt.Equals, "xyz92")
   179  	c.Assert(unsetValue, qt.Equals, nil)
   180  
   181  	sorted := unsorted.ByParam("arbitrarily.nested")
   182  	firstSetSortedValue, _ := sorted[0].Param(k)
   183  	secondSetSortedValue, _ := sorted[1].Param(k)
   184  	lastSetSortedValue, _ := sorted[8].Param(k)
   185  	unsetSortedValue, _ := sorted[9].Param(k)
   186  
   187  	c.Assert(firstSetSortedValue, qt.Equals, firstSetValue)
   188  	c.Assert(lastSetSortedValue, qt.Equals, secondSetValue)
   189  	c.Assert(secondSetSortedValue, qt.Equals, lastSetValue)
   190  	c.Assert(unsetSortedValue, qt.Equals, unsetValue)
   191  }
   192  
   193  func TestPageSortByParamNumeric(t *testing.T) {
   194  	t.Parallel()
   195  	c := qt.New(t)
   196  
   197  	var k any = "arbitrarily.nested"
   198  
   199  	n := 10
   200  	unsorted := createSortTestPages(n)
   201  	for i := 0; i < n; i++ {
   202  		v := 100 - i
   203  		if i%2 == 0 {
   204  			v = 100.0 - i
   205  		}
   206  
   207  		unsorted[i].(*testPage).params = map[string]any{
   208  			"arbitrarily": map[string]any{
   209  				"nested": v,
   210  			},
   211  		}
   212  	}
   213  	delete(unsorted[9].Params(), "arbitrarily")
   214  
   215  	firstSetValue, _ := unsorted[0].Param(k)
   216  	secondSetValue, _ := unsorted[1].Param(k)
   217  	lastSetValue, _ := unsorted[8].Param(k)
   218  	unsetValue, _ := unsorted[9].Param(k)
   219  
   220  	c.Assert(firstSetValue, qt.Equals, 100)
   221  	c.Assert(secondSetValue, qt.Equals, 99)
   222  	c.Assert(lastSetValue, qt.Equals, 92)
   223  	c.Assert(unsetValue, qt.Equals, nil)
   224  
   225  	sorted := unsorted.ByParam("arbitrarily.nested")
   226  	firstSetSortedValue, _ := sorted[0].Param(k)
   227  	secondSetSortedValue, _ := sorted[1].Param(k)
   228  	lastSetSortedValue, _ := sorted[8].Param(k)
   229  	unsetSortedValue, _ := sorted[9].Param(k)
   230  
   231  	c.Assert(firstSetSortedValue, qt.Equals, 92)
   232  	c.Assert(secondSetSortedValue, qt.Equals, 93)
   233  	c.Assert(lastSetSortedValue, qt.Equals, 100)
   234  	c.Assert(unsetSortedValue, qt.Equals, unsetValue)
   235  }
   236  
   237  func BenchmarkSortByWeightAndReverse(b *testing.B) {
   238  	p := createSortTestPages(300)
   239  
   240  	b.ResetTimer()
   241  	for i := 0; i < b.N; i++ {
   242  		p = p.ByWeight().Reverse()
   243  	}
   244  }
   245  
   246  func setSortVals(dates [4]time.Time, titles [4]string, weights [4]int, pages Pages) {
   247  	for i := range dates {
   248  		this := pages[i].(*testPage)
   249  		other := pages[len(dates)-1-i].(*testPage)
   250  
   251  		this.date = dates[i]
   252  		this.lastMod = dates[i]
   253  		this.weight = weights[i]
   254  		this.title = titles[i]
   255  		// make sure we compare apples and ... apples ...
   256  		other.linkTitle = this.Title() + "l"
   257  		other.pubDate = dates[i]
   258  		other.expiryDate = dates[i]
   259  		other.content = titles[i] + "_content"
   260  	}
   261  	lastLastMod := pages[2].Lastmod()
   262  	pages[2].(*testPage).lastMod = pages[1].Lastmod()
   263  	pages[1].(*testPage).lastMod = lastLastMod
   264  
   265  	for _, p := range pages {
   266  		p.(*testPage).content = ""
   267  	}
   268  }
   269  
   270  func createSortTestPages(num int) Pages {
   271  	pages := make(Pages, num)
   272  
   273  	for i := 0; i < num; i++ {
   274  		p := newTestPage()
   275  		p.path = fmt.Sprintf("/x/y/p%d.md", i)
   276  		p.title = fmt.Sprintf("Title %d", i%(num+1/2))
   277  		p.params = map[string]any{
   278  			"arbitrarily": map[string]any{
   279  				"nested": ("xyz" + fmt.Sprintf("%v", 100-i)),
   280  			},
   281  		}
   282  
   283  		w := 5
   284  
   285  		if i%2 == 0 {
   286  			w = 10
   287  		}
   288  		p.fuzzyWordCount = i
   289  		p.weight = w
   290  		p.description = "initial"
   291  
   292  		pages[i] = p
   293  	}
   294  
   295  	return pages
   296  }