github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/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  	"fmt"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/gohugoio/hugo/htesting/hqt"
    22  	"github.com/gohugoio/hugo/source"
    23  
    24  	"github.com/gohugoio/hugo/resources/resource"
    25  
    26  	qt "github.com/frankban/quicktest"
    27  )
    28  
    29  var eq = qt.CmpEquals(hqt.DeepAllowUnexported(
    30  	&testPage{},
    31  	&source.FileInfo{},
    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  
   109  	for i, this := range []struct {
   110  		sortFunc   func(p Pages) Pages
   111  		assertFunc func(p Pages) bool
   112  	}{
   113  		{(Pages).ByWeight, func(p Pages) bool { return p[0].Weight() == 1 }},
   114  		{(Pages).ByTitle, func(p Pages) bool { return p[0].Title() == "ab" }},
   115  		{(Pages).ByLinkTitle, func(p Pages) bool { return p[0].LinkTitle() == "abl" }},
   116  		{(Pages).ByDate, func(p Pages) bool { return p[0].Date() == d4 }},
   117  		{(Pages).ByPublishDate, func(p Pages) bool { return p[0].PublishDate() == d4 }},
   118  		{(Pages).ByExpiryDate, func(p Pages) bool { return p[0].ExpiryDate() == d4 }},
   119  		{(Pages).ByLastmod, func(p Pages) bool { return p[1].Lastmod() == d3 }},
   120  		{(Pages).ByLength, func(p Pages) bool { return p[0].(resource.LengthProvider).Len() == len(p[0].(*testPage).content) }},
   121  	} {
   122  		setSortVals([4]time.Time{d1, d2, d3, d4}, [4]string{"b", "ab", "cde", "fg"}, [4]int{0, 3, 2, 1}, p)
   123  
   124  		sorted := this.sortFunc(p)
   125  		if !this.assertFunc(sorted) {
   126  			t.Errorf("[%d] sort error", i)
   127  		}
   128  	}
   129  }
   130  
   131  func TestLimit(t *testing.T) {
   132  	t.Parallel()
   133  	c := qt.New(t)
   134  	p := createSortTestPages(10)
   135  	firstFive := p.Limit(5)
   136  	c.Assert(len(firstFive), qt.Equals, 5)
   137  	for i := 0; i < 5; i++ {
   138  		c.Assert(firstFive[i], qt.Equals, p[i])
   139  	}
   140  	c.Assert(p.Limit(10), eq, p)
   141  	c.Assert(p.Limit(11), eq, p)
   142  }
   143  
   144  func TestPageSortReverse(t *testing.T) {
   145  	t.Parallel()
   146  	c := qt.New(t)
   147  	p1 := createSortTestPages(10)
   148  	c.Assert(p1[0].(*testPage).fuzzyWordCount, qt.Equals, 0)
   149  	c.Assert(p1[9].(*testPage).fuzzyWordCount, qt.Equals, 9)
   150  	p2 := p1.Reverse()
   151  	c.Assert(p2[0].(*testPage).fuzzyWordCount, qt.Equals, 9)
   152  	c.Assert(p2[9].(*testPage).fuzzyWordCount, qt.Equals, 0)
   153  	// cached
   154  	c.Assert(pagesEqual(p2, p1.Reverse()), qt.Equals, true)
   155  }
   156  
   157  func TestPageSortByParam(t *testing.T) {
   158  	t.Parallel()
   159  	c := qt.New(t)
   160  	var k interface{} = "arbitrarily.nested"
   161  
   162  	unsorted := createSortTestPages(10)
   163  	delete(unsorted[9].Params(), "arbitrarily")
   164  
   165  	firstSetValue, _ := unsorted[0].Param(k)
   166  	secondSetValue, _ := unsorted[1].Param(k)
   167  	lastSetValue, _ := unsorted[8].Param(k)
   168  	unsetValue, _ := unsorted[9].Param(k)
   169  
   170  	c.Assert(firstSetValue, qt.Equals, "xyz100")
   171  	c.Assert(secondSetValue, qt.Equals, "xyz99")
   172  	c.Assert(lastSetValue, qt.Equals, "xyz92")
   173  	c.Assert(unsetValue, qt.Equals, nil)
   174  
   175  	sorted := unsorted.ByParam("arbitrarily.nested")
   176  	firstSetSortedValue, _ := sorted[0].Param(k)
   177  	secondSetSortedValue, _ := sorted[1].Param(k)
   178  	lastSetSortedValue, _ := sorted[8].Param(k)
   179  	unsetSortedValue, _ := sorted[9].Param(k)
   180  
   181  	c.Assert(firstSetSortedValue, qt.Equals, firstSetValue)
   182  	c.Assert(lastSetSortedValue, qt.Equals, secondSetValue)
   183  	c.Assert(secondSetSortedValue, qt.Equals, lastSetValue)
   184  	c.Assert(unsetSortedValue, qt.Equals, unsetValue)
   185  }
   186  
   187  func TestPageSortByParamNumeric(t *testing.T) {
   188  	t.Parallel()
   189  	c := qt.New(t)
   190  
   191  	var k interface{} = "arbitrarily.nested"
   192  
   193  	n := 10
   194  	unsorted := createSortTestPages(n)
   195  	for i := 0; i < n; i++ {
   196  		v := 100 - i
   197  		if i%2 == 0 {
   198  			v = 100.0 - i
   199  		}
   200  
   201  		unsorted[i].(*testPage).params = map[string]interface{}{
   202  			"arbitrarily": map[string]interface{}{
   203  				"nested": v,
   204  			},
   205  		}
   206  	}
   207  	delete(unsorted[9].Params(), "arbitrarily")
   208  
   209  	firstSetValue, _ := unsorted[0].Param(k)
   210  	secondSetValue, _ := unsorted[1].Param(k)
   211  	lastSetValue, _ := unsorted[8].Param(k)
   212  	unsetValue, _ := unsorted[9].Param(k)
   213  
   214  	c.Assert(firstSetValue, qt.Equals, 100)
   215  	c.Assert(secondSetValue, qt.Equals, 99)
   216  	c.Assert(lastSetValue, qt.Equals, 92)
   217  	c.Assert(unsetValue, qt.Equals, nil)
   218  
   219  	sorted := unsorted.ByParam("arbitrarily.nested")
   220  	firstSetSortedValue, _ := sorted[0].Param(k)
   221  	secondSetSortedValue, _ := sorted[1].Param(k)
   222  	lastSetSortedValue, _ := sorted[8].Param(k)
   223  	unsetSortedValue, _ := sorted[9].Param(k)
   224  
   225  	c.Assert(firstSetSortedValue, qt.Equals, 92)
   226  	c.Assert(secondSetSortedValue, qt.Equals, 93)
   227  	c.Assert(lastSetSortedValue, qt.Equals, 100)
   228  	c.Assert(unsetSortedValue, qt.Equals, unsetValue)
   229  }
   230  
   231  func BenchmarkSortByWeightAndReverse(b *testing.B) {
   232  	p := createSortTestPages(300)
   233  
   234  	b.ResetTimer()
   235  	for i := 0; i < b.N; i++ {
   236  		p = p.ByWeight().Reverse()
   237  	}
   238  }
   239  
   240  func setSortVals(dates [4]time.Time, titles [4]string, weights [4]int, pages Pages) {
   241  	for i := range dates {
   242  		this := pages[i].(*testPage)
   243  		other := pages[len(dates)-1-i].(*testPage)
   244  
   245  		this.date = dates[i]
   246  		this.lastMod = dates[i]
   247  		this.weight = weights[i]
   248  		this.title = titles[i]
   249  		// make sure we compare apples and ... apples ...
   250  		other.linkTitle = this.Title() + "l"
   251  		other.pubDate = dates[i]
   252  		other.expiryDate = dates[i]
   253  		other.content = titles[i] + "_content"
   254  	}
   255  	lastLastMod := pages[2].Lastmod()
   256  	pages[2].(*testPage).lastMod = pages[1].Lastmod()
   257  	pages[1].(*testPage).lastMod = lastLastMod
   258  
   259  	for _, p := range pages {
   260  		p.(*testPage).content = ""
   261  	}
   262  }
   263  
   264  func createSortTestPages(num int) Pages {
   265  	pages := make(Pages, num)
   266  
   267  	for i := 0; i < num; i++ {
   268  		p := newTestPage()
   269  		p.path = fmt.Sprintf("/x/y/p%d.md", i)
   270  		p.title = fmt.Sprintf("Title %d", i%(num+1/2))
   271  		p.params = map[string]interface{}{
   272  			"arbitrarily": map[string]interface{}{
   273  				"nested": ("xyz" + fmt.Sprintf("%v", 100-i)),
   274  			},
   275  		}
   276  
   277  		w := 5
   278  
   279  		if i%2 == 0 {
   280  			w = 10
   281  		}
   282  		p.fuzzyWordCount = i
   283  		p.weight = w
   284  		p.description = "initial"
   285  
   286  		pages[i] = p
   287  	}
   288  
   289  	return pages
   290  }