github.com/mendersoftware/go-lib-micro@v0.0.0-20240304135804-e8e39c59b148/rest.utils/paging_test.go (about) 1 // Copyright 2023 Northern.tech AS 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 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package rest 16 17 import ( 18 "fmt" 19 "net/http" 20 "net/url" 21 "testing" 22 23 "github.com/pkg/errors" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestParsePagingParameters(t *testing.T) { 28 t.Parallel() 29 testCases := []struct { 30 Name string 31 URL url.URL 32 33 ExpectedPage int64 34 ExpectedPerPage int64 35 ExpectedError error 36 }{{ 37 Name: "ok", 38 URL: url.URL{ 39 Path: "/foobar", 40 RawQuery: "page=2&per_page=32", 41 }, 42 ExpectedPage: 2, 43 ExpectedPerPage: 32, 44 }, { 45 Name: "defaults", 46 URL: url.URL{Path: "/"}, 47 ExpectedPage: 1, 48 ExpectedPerPage: PerPageDefault, 49 }, { 50 Name: "error, bad page parameter", 51 URL: url.URL{Path: "/", RawQuery: "page=two"}, 52 ExpectedPage: -1, 53 ExpectedPerPage: -1, 54 ExpectedError: errors.New( 55 "invalid page query: \"two\"", 56 ), 57 }, { 58 Name: "error, bad per_page parameter", 59 URL: url.URL{Path: "/", RawQuery: "per_page=thirty"}, 60 ExpectedPage: -1, 61 ExpectedPerPage: -1, 62 ExpectedError: errors.New( 63 "invalid per_page query: \"thirty\"", 64 ), 65 }, { 66 Name: "error, negative page parameter", 67 URL: url.URL{Path: "/", RawQuery: "page=-12345"}, 68 ExpectedPage: -1, 69 ExpectedPerPage: -1, 70 ExpectedError: errors.New( 71 "invalid page query: " + 72 "value must be a non-zero positive integer", 73 ), 74 }, { 75 Name: "error, zero per_page parameter", 76 URL: url.URL{Path: "/", RawQuery: "per_page=0"}, 77 ExpectedPage: -1, 78 ExpectedPerPage: -1, 79 ExpectedError: errors.New( 80 "invalid per_page query: " + 81 "value must be a non-zero positive integer", 82 ), 83 }, { 84 Name: "error, per_page above limit", 85 URL: url.URL{ 86 Path: "/", 87 RawQuery: fmt.Sprintf("per_page=%d", PerPageMax+1), 88 }, 89 ExpectedPage: 1, 90 ExpectedPerPage: PerPageMax + 1, 91 ExpectedError: ErrPerPageLimit, 92 }} 93 94 for i := range testCases { 95 tc := testCases[i] 96 t.Run(tc.Name, func(t *testing.T) { 97 t.Parallel() 98 99 req := &http.Request{ 100 URL: &tc.URL, 101 } 102 page, perPage, err := ParsePagingParameters(req) 103 if tc.ExpectedError != nil { 104 assert.EqualError(t, err, tc.ExpectedError.Error()) 105 } else { 106 assert.NoError(t, err) 107 } 108 assert.Equal(t, tc.ExpectedPage, page) 109 assert.Equal(t, tc.ExpectedPerPage, perPage) 110 }) 111 } 112 } 113 114 func TestMakePagingHeaders(t *testing.T) { 115 testCases := []struct { 116 Name string 117 118 // Inputs 119 URL url.URL 120 Hints *PagingHints 121 122 // Expected 123 Links []string 124 Error error 125 }{{ 126 Name: "ok", 127 URL: url.URL{Path: "/foobar", RawQuery: "page=3&per_page=10"}, 128 Hints: NewPagingHints().SetTotalCount(120), 129 130 Links: []string{ 131 `</foobar?page=1&per_page=10>; rel="first"`, 132 `</foobar?page=2&per_page=10>; rel="prev"`, 133 `</foobar?page=4&per_page=10>; rel="next"`, 134 `</foobar?page=12&per_page=10>; rel="last"`, 135 }, 136 }, { 137 Name: "ok, up-by-one", 138 URL: url.URL{Path: "/foobar", RawQuery: "page=3&per_page=10"}, 139 Hints: NewPagingHints().SetTotalCount(121), 140 141 Links: []string{ 142 `</foobar?page=1&per_page=10>; rel="first"`, 143 `</foobar?page=2&per_page=10>; rel="prev"`, 144 `</foobar?page=4&per_page=10>; rel="next"`, 145 `</foobar?page=13&per_page=10>; rel="last"`, 146 }, 147 }, { 148 Name: "ok, defaults", 149 URL: url.URL{Path: "/foobar"}, 150 151 Links: []string{`</foobar?page=1&per_page=20>; rel="first"`}, 152 }, { 153 Name: "ok, default has next", 154 URL: url.URL{Path: "/foobar"}, 155 Hints: NewPagingHints(). 156 SetHasNext(true). 157 SetPage(1). 158 SetPerPage(20), 159 160 Links: []string{ 161 `</foobar?page=1&per_page=20>; rel="first"`, 162 `</foobar?page=2&per_page=20>; rel="next"`, 163 }, 164 }, { 165 Name: "error parsing paging parameters", 166 URL: url.URL{Path: "/foobar", RawQuery: "page=badvalue"}, 167 168 Error: errors.New("invalid page query: \"badvalue\""), 169 }} 170 171 for i := range testCases { 172 tc := testCases[i] 173 t.Run(tc.Name, func(t *testing.T) { 174 req := &http.Request{ 175 URL: &tc.URL, 176 } 177 links, err := MakePagingHeaders(req, tc.Hints) 178 if tc.Error != nil { 179 assert.EqualError(t, err, tc.Error.Error()) 180 } else { 181 assert.NoError(t, err) 182 assert.Equal(t, tc.Links, links) 183 } 184 }) 185 } 186 }