View | Details | Raw Unified | Return to bug 33080
Collapse All | Expand All

(-)a/Koha/REST/Plugin/Objects.pm (-17 / +17 lines)
Lines 114-120 shouldn't be called twice in it. Link Here
114
        'objects.search' => sub {
114
        'objects.search' => sub {
115
            my ( $c, $result_set ) = @_;
115
            my ( $c, $result_set ) = @_;
116
116
117
            return $c->objects->to_api( $c->objects->search_rs($result_set) );
117
            # Generate the resultset using the HTTP request information
118
            my $objects_rs = $c->objects->search_rs($result_set);
119
            # Add pagination headers
120
            $c->add_pagination_headers({ result_set => $objects_rs });
121
122
            return $c->objects->to_api($objects_rs);
118
        }
123
        }
119
    );
124
    );
120
125
Lines 155-163 shouldn't be called twice in it. Link Here
155
160
156
            # If no pagination parameters are passed, default
161
            # If no pagination parameters are passed, default
157
            $reserved_params->{_per_page} //=
162
            $reserved_params->{_per_page} //=
158
              C4::Context->preference('RESTdefaultPageSize');
163
              C4::Context->preference('RESTdefaultPageSize') // 20;
159
            $reserved_params->{_page} //= 1;
164
            $reserved_params->{_page} //= 1;
160
165
166
            $c->stash('koha.pagination.page'     => $reserved_params->{_page});
167
            $c->stash('koha.pagination.per_page' => $reserved_params->{_per_page});
168
161
            unless ( $reserved_params->{_per_page} == -1 ) {
169
            unless ( $reserved_params->{_per_page} == -1 ) {
162
170
163
                # Merge pagination into query attributes
171
                # Merge pagination into query attributes
Lines 244-266 shouldn't be called twice in it. Link Here
244
            $result_set = $result_set->search_limited,
252
            $result_set = $result_set->search_limited,
245
              if $result_set->can('search_limited');
253
              if $result_set->can('search_limited');
246
254
247
            # Perform search
255
            $c->stash('koha.pagination.base_total'   => $result_set->count);
248
            my $objects = $result_set->search( $filtered_params, $attributes );
256
            $c->stash('koha.pagination.query_params' => $args);
249
            my $total   = $result_set->search->count;
250
257
251
            $c->add_pagination_headers(
258
            # Generate the resultset
252
                {
259
            my $objects_rs = $result_set->search( $filtered_params, $attributes );
253
                    total => (
260
            # Stash the page total if requires, total otherwise
254
                          $objects->is_paged
261
            $c->stash('koha.pagination.total' => $objects_rs->is_paged ? $objects_rs->pager->total_entries : $objects_rs->count);
255
                        ? $objects->pager->total_entries
256
                        : $objects->count
257
                    ),
258
                    base_total => $total,
259
                    params     => $args,
260
                }
261
            );
262
262
263
            return $objects;
263
            return $objects_rs;
264
        }
264
        }
265
    );
265
    );
266
266
(-)a/Koha/REST/Plugin/Pagination.pm (-23 / +53 lines)
Lines 38-58 sub register { Link Here
38
38
39
=head3 add_pagination_headers
39
=head3 add_pagination_headers
40
40
41
    my $patrons = Koha::Patrons->search( ... );
41
    $c->add_pagination_headers(
42
    $c->add_pagination_headers({
42
        {
43
        total  => $patrons->count,
43
          [ base_total   => $base_total,
44
        params => {
44
            page         => $page,
45
            _page     => ...
45
            per_page     => $per_page,
46
            _per_page => ...
46
            query_params => $query_params,
47
            ...
47
            total        => $total, ]
48
        }
48
        }
49
    });
49
    );
50
51
It gets passed a I<result_set> and adds Link headers to the response message $c
52
carries, following RFC5988, including the following relation types: 'prev', 'next',
53
'first' and 'last'.
54
55
It also adds X-Total-Count containing the total results count, and X-Base-Total-Count
56
containing the total of the non-filtered results count.
57
58
For pagination information it will read the passed parameters, and fallback to the
59
following values from the stash otherwise:
60
61
=over
62
63
=item koha.pagination.base_total
64
65
Total records for the search domain (e.g. all patron records, filtered by visibility)
50
66
51
Adds a Link header to the response message $c carries, following RFC5988, including
67
=item koha.pagination.page
52
the following relation types: 'prev', 'next', 'first' and 'last'.
53
It also adds X-Total-Count containing the total results count, and X-Base-Total-Count containing the total of the non-filtered results count.
54
68
55
If page size is omitted, it defaults to the value of the RESTdefaultPageSize syspref.
69
The requested page number. See I<objects.search_rs> for more information.
70
71
=item koha.pagination.per_page
72
73
The requested maximum results per page. See I<objects.search_rs> for more information.
74
75
=item koha.pagination.query_params
76
77
The request query, to be used to build the I<Link> headers.
78
79
=item koha.pagination.total
80
81
Total records for the page.
82
83
=back
56
84
57
=cut
85
=cut
58
86
Lines 60-70 If page size is omitted, it defaults to the value of the RESTdefaultPageSize sys Link Here
60
        'add_pagination_headers' => sub {
88
        'add_pagination_headers' => sub {
61
            my ( $c, $args ) = @_;
89
            my ( $c, $args ) = @_;
62
90
63
            my $total    = $args->{total};
91
            my $base_total = $args->{base_total} // $c->stash('koha.pagination.base_total');
64
            my $base_total = $args->{base_total};
92
            my $req_page   = $args->{page}         // $c->stash('koha.pagination.page')     // 1;
65
            my $req_page = $args->{params}->{_page} // 1;
93
            my $per_page   = $args->{per_page}     // $c->stash('koha.pagination.per_page') // C4::Context->preference('RESTdefaultPageSize') // 20;
66
            my $per_page = $args->{params}->{_per_page} //
94
            my $params     = $args->{query_params} // $c->stash('koha.pagination.query_params');
67
                            C4::Context->preference('RESTdefaultPageSize') // 20;
95
            my $total      = $args->{total}        // $c->stash('koha.pagination.total');
68
96
69
            my $pages;
97
            my $pages;
70
            if ( $per_page == -1 ) {
98
            if ( $per_page == -1 ) {
Lines 86-92 If page size is omitted, it defaults to the value of the RESTdefaultPageSize sys Link Here
86
                    {   page     => $req_page - 1,
114
                    {   page     => $req_page - 1,
87
                        per_page => $per_page,
115
                        per_page => $per_page,
88
                        rel      => 'prev',
116
                        rel      => 'prev',
89
                        params   => $args->{params}
117
                        params   => $params
90
                    }
118
                    }
91
                    );
119
                    );
92
            }
120
            }
Lines 98-114 If page size is omitted, it defaults to the value of the RESTdefaultPageSize sys Link Here
98
                    {   page     => $req_page + 1,
126
                    {   page     => $req_page + 1,
99
                        per_page => $per_page,
127
                        per_page => $per_page,
100
                        rel      => 'next',
128
                        rel      => 'next',
101
                        params   => $args->{params}
129
                        params   => $params
102
                    }
130
                    }
103
                    );
131
                    );
104
            }
132
            }
105
133
106
            push @links,
134
            push @links,
107
                _build_link( $c,
135
                _build_link( $c,
108
                { page => 1, per_page => $per_page, rel => 'first', params => $args->{params} } );
136
                { page => 1, per_page => $per_page, rel => 'first', params => $params } );
109
            push @links,
137
            push @links,
110
                _build_link( $c,
138
                _build_link( $c,
111
                { page => $pages, per_page => $per_page, rel => 'last', params => $args->{params} } );
139
                { page => $pages, per_page => $per_page, rel => 'last', params => $params } );
112
140
113
            # Add Link header
141
            # Add Link header
114
            foreach my $link (@links) {
142
            foreach my $link (@links) {
Lines 116-123 If page size is omitted, it defaults to the value of the RESTdefaultPageSize sys Link Here
116
            }
144
            }
117
145
118
            # Add X-Total-Count header
146
            # Add X-Total-Count header
119
            $c->res->headers->add( 'X-Total-Count' => $total );
147
            $c->res->headers->add( 'X-Total-Count'      => $total );
120
            $c->res->headers->add( 'X-Base-Total-Count' => $base_total ) if defined $base_total;
148
            $c->res->headers->add( 'X-Base-Total-Count' => $base_total )
149
              if defined $base_total;
150
121
            return $c;
151
            return $c;
122
        }
152
        }
123
    );
153
    );
(-)a/t/Koha/REST/Plugin/Pagination.t (-69 / +58 lines)
Lines 20-29 use Modern::Perl; Link Here
20
# Dummy app for testing the plugin
20
# Dummy app for testing the plugin
21
use Mojolicious::Lite;
21
use Mojolicious::Lite;
22
22
23
use Koha::Patrons;
24
25
use t::lib::TestBuilder;
26
23
app->log->level('error');
27
app->log->level('error');
24
28
25
plugin 'Koha::REST::Plugin::Pagination';
29
plugin 'Koha::REST::Plugin::Pagination';
26
30
31
my $schema = Koha::Database->new->schema;
32
my $builder = t::lib::TestBuilder->new;
33
34
$schema->storage->txn_begin;
35
36
# Add 10 known 'Jonathan' patrons
37
my @patron_ids;
38
for my $i ( 1 .. 10 ) {
39
    push @patron_ids, $builder->build_object({ class => 'Koha::Patrons', value => { firstname => 'Jonathan' } })->id;
40
}
41
# Add two non-Jonathans
42
push @patron_ids, $builder->build_object({ class => 'Koha::Patrons' })->id;
43
push @patron_ids, $builder->build_object({ class => 'Koha::Patrons' })->id;
44
27
# For add_pagination_headers()
45
# For add_pagination_headers()
28
46
29
get '/empty' => sub {
47
get '/empty' => sub {
Lines 33-51 get '/empty' => sub { Link Here
33
51
34
get '/pagination_headers' => sub {
52
get '/pagination_headers' => sub {
35
    my $c = shift;
53
    my $c = shift;
36
    $c->add_pagination_headers({ total => 10, base_total => 12, params => { _page => 2, _per_page => 3, firstname => 'Jonathan' } });
37
    $c->render( json => { ok => 1 }, status => 200 );
38
};
39
54
40
get '/pagination_headers_first_page' => sub {
55
    my $args = $c->req->params->to_hash;
41
    my $c = shift;
56
42
    $c->add_pagination_headers({ total => 10, base_total => 12, params => { _page => 1, _per_page => 3, firstname => 'Jonathan' } });
57
    my $result_set = Koha::Patrons->search(
43
    $c->render( json => { ok => 1 }, status => 200 );
58
        { borrowernumber => \@patron_ids }
44
};
59
    );
60
61
    my $rows = ($args->{_per_page}) ?
62
                        ( $args->{_per_page} == -1 ) ?  undef : $args->{_per_page}
63
                        : C4::Context->preference('RESTdefaultPageSize');
64
65
    my $objects_rs = $result_set->search( { firstname => 'Jonathan' } ,{ page => $args->{_page} // 1, rows => $rows });
66
67
    $c->stash('koha.pagination.page'         => $args->{_page});
68
    $c->stash('koha.pagination.per_page'     => $args->{_per_page});
69
    $c->stash('koha.pagination.base_total'   => $result_set->count);
70
    $c->stash('koha.pagination.query_params' => $args);
71
    $c->stash('koha.pagination.total'        => $objects_rs->is_paged ? $objects_rs->pager->total_entries : $objects_rs->count);
72
73
    $c->add_pagination_headers;
45
74
46
get '/pagination_headers_last_page' => sub {
47
    my $c = shift;
48
    $c->add_pagination_headers({ total => 10, base_total => 12, params => { _page => 4, _per_page => 3, firstname => 'Jonathan' } });
49
    $c->render( json => { ok => 1 }, status => 200 );
75
    $c->render( json => { ok => 1 }, status => 200 );
50
};
76
};
51
77
Lines 58-99 get '/dbic_merge_pagination' => sub { Link Here
58
    $c->render( json => $filter, status => 200 );
84
    $c->render( json => $filter, status => 200 );
59
};
85
};
60
86
61
get '/pagination_headers_without_page_size' => sub {
62
    my $c = shift;
63
    $c->add_pagination_headers({ total => 10, base_total => 12, params => { _page => 2, firstname => 'Jonathan' } });
64
    $c->render( json => { ok => 1 }, status => 200 );
65
};
66
67
get '/pagination_headers_without_page' => sub {
68
    my $c = shift;
69
    $c->add_pagination_headers({ total => 10, base_total => 12, params => { _per_page => 3, firstname => 'Jonathan' } });
70
    $c->render( json => { ok => 1 }, status => 200 );
71
};
72
73
get '/pagination_headers_with_minus_one' => sub {
74
    my $c = shift;
75
    $c->add_pagination_headers(
76
        {
77
            total => 10,
78
            base_total => 12,
79
            params => { _per_page => -1, firstname => 'Jonathan' }
80
        }
81
    );
82
    $c->render( json => { ok => 1 }, status => 200 );
83
};
84
85
get '/pagination_headers_with_minus_one_and_invalid_page' => sub {
86
    my $c = shift;
87
    $c->add_pagination_headers(
88
        {
89
            total  => 10,
90
            base_total => 12,
91
            params => { page => 100, _per_page => -1, firstname => 'Jonathan' }
92
        }
93
    );
94
    $c->render( json => { ok => 1 }, status => 200 );
95
};
96
97
# The tests
87
# The tests
98
88
99
use Test::More tests => 2;
89
use Test::More tests => 2;
Lines 109-122 subtest 'add_pagination_headers() tests' => sub { Link Here
109
99
110
    $t->get_ok('/empty')
100
    $t->get_ok('/empty')
111
      ->status_is( 200 )
101
      ->status_is( 200 )
112
      ->header_is( 'X-Total-Count' => undef, 'X-Total-Count is undefined' )
102
      ->header_is( 'X-Total-Count'      => undef, 'X-Total-Count is undefined' )
113
      ->header_is( 'X-Base-Total-Count' => undef, 'X-Base-Total-Count is undefined' )
103
      ->header_is( 'X-Base-Total-Count' => undef, 'X-Base-Total-Count is undefined' )
114
      ->header_is( 'Link'          => undef, 'Link is undefined' );
104
      ->header_is( 'Link'               => undef, 'Link is undefined' );
115
105
116
    $t->get_ok('/pagination_headers')
106
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=2&_per_page=3')
117
      ->status_is( 200 )
107
      ->status_is( 200 )
118
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count contains the passed value' )
108
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count correctly set' )
119
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
109
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
120
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
110
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
121
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=1.*>; rel="prev",/ )
111
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=1.*>; rel="prev",/ )
122
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/ )
112
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/ )
Lines 130-139 subtest 'add_pagination_headers() tests' => sub { Link Here
130
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
120
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
131
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
121
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
132
122
133
    $t->get_ok('/pagination_headers_first_page')
123
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=1&_per_page=3')
134
      ->status_is( 200 )
124
      ->status_is( 200 )
135
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count contains the passed value' )
125
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count correctly set' )
136
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
126
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
137
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*>; rel="prev",/ )
127
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*>; rel="prev",/ )
138
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="next",/ )
128
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="next",/ )
139
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_page=2.*>; rel="next",/ )
129
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_page=2.*>; rel="next",/ )
Lines 145-154 subtest 'add_pagination_headers() tests' => sub { Link Here
145
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
135
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_page=4.*>; rel="last"/ )
146
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
136
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
147
137
148
    $t->get_ok('/pagination_headers_last_page')
138
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=4&_per_page=3')
149
      ->status_is( 200 )
139
      ->status_is( 200 )
150
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count contains the passed value' )
140
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count correctly set' )
151
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
141
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
152
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
142
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_per_page=3.*>; rel="prev",/ )
153
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_page=3.*>; rel="prev",/ )
143
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*_page=3.*>; rel="prev",/ )
154
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/ )
144
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/ )
Lines 161-170 subtest 'add_pagination_headers() tests' => sub { Link Here
161
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
151
      ->header_like(   'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
162
152
163
    t::lib::Mocks::mock_preference('RESTdefaultPageSize', 3);
153
    t::lib::Mocks::mock_preference('RESTdefaultPageSize', 3);
164
    $t->get_ok('/pagination_headers_without_page_size')
154
    $t->get_ok('/pagination_headers?firstname=Jonathan&_page=2')
165
      ->status_is( 200 )
155
      ->status_is( 200 )
166
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count contains the passed value' )
156
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count correctly set' )
167
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
157
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
168
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/ )
158
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/ )
169
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/ )
159
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/ )
170
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/ )
160
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/ )
Lines 178-192 subtest 'add_pagination_headers() tests' => sub { Link Here
178
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
168
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
179
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
169
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
180
170
181
    $t->get_ok('/pagination_headers_without_page')
171
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=3')
182
      ->status_is( 200 )
172
      ->status_is( 200 )
183
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count header present, even without page param' )
173
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count header present, even without page param' )
184
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
174
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
185
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/, 'First page, no previous' )
175
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="prev",/, 'First page, no previous' )
186
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/, 'First page, no previous' )
176
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/, 'First page, no previous' )
187
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/, 'First page, no previous' )
177
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/, 'First page, no previous' )
188
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="next",/ )
178
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="next",/ )
189
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=3.*>; rel="next",/ )
179
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=2.*>; rel="next",/ )
190
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="next",/ )
180
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="next",/ )
191
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="first",/ )
181
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*per_page=3.*>; rel="first",/ )
192
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="first",/ )
182
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="first",/ )
Lines 195-204 subtest 'add_pagination_headers() tests' => sub { Link Here
195
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
185
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=4.*>; rel="last"/ )
196
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
186
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
197
187
198
    $t->get_ok('/pagination_headers_with_minus_one')
188
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=-1')
199
      ->status_is( 200 )
189
      ->status_is( 200 )
200
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count header present, with per_page=-1' )
190
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count header present, with per_page=-1' )
201
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
191
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
202
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/, 'First page, no previous' )
192
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/, 'First page, no previous' )
203
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/, 'First page, no previous' )
193
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/, 'First page, no previous' )
204
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/, 'First page, no previous' )
194
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/, 'First page, no previous' )
Lines 210-219 subtest 'add_pagination_headers() tests' => sub { Link Here
210
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="last"/ )
200
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="last"/ )
211
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
201
      ->header_like( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="last"/ );
212
202
213
    $t->get_ok('/pagination_headers_with_minus_one_and_invalid_page')
203
    $t->get_ok('/pagination_headers?firstname=Jonathan&_per_page=-1&_page=100')
214
      ->status_is( 200 )
204
      ->status_is( 200 )
215
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count header present, with per_page=-1' )
205
      ->header_is( 'X-Total-Count' => 10, 'X-Total-Count header present, with per_page=-1' )
216
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count contains the passed value' )
206
      ->header_is( 'X-Base-Total-Count' => 12, 'X-Base-Total-Count correctly set' )
217
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/, 'First page, no previous' )
207
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*per_page=-1.*>; rel="prev",/, 'First page, no previous' )
218
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/, 'First page, no previous' )
208
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*page=1.*>; rel="prev",/, 'First page, no previous' )
219
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/, 'First page, no previous' )
209
      ->header_unlike( 'Link' => qr/<http:\/\/.*\?.*firstname=Jonathan.*>; rel="prev",/, 'First page, no previous' )
220
- 

Return to bug 33080