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  }