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 }