1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::PaginatedResponse do
before do
array = [1, 2, 3, 4]
@paginated_response = described_class.new array
end
it 'responds to total, *_page and has_*_page methods' do
expect(@paginated_response).to respond_to :first_page
expect(@paginated_response).to respond_to :last_page
expect(@paginated_response).to respond_to :next_page
expect(@paginated_response).to respond_to :prev_page
expect(@paginated_response).to respond_to :has_first_page?
expect(@paginated_response).to respond_to :has_last_page?
expect(@paginated_response).to respond_to :has_next_page?
expect(@paginated_response).to respond_to :has_prev_page?
expect(@paginated_response).to respond_to :total
end
describe '.parse_headers!' do
it 'parses headers' do
@paginated_response.parse_headers!('Link' => '<http://example.com/api/v3/projects?page=1&per_page=5>; rel="first", <http://example.com/api/v3/projects?page=20&per_page=5>; rel="last"', 'x-total' => '8')
client = @paginated_response.client = double('client')
first_page_response = double('first_page_response')
last_page_response = double('last_page_response')
allow(client).to receive(:endpoint).and_return('http://example.com/api/v3')
allow(client).to receive(:get).with('/projects?page=1&per_page=5').and_return(first_page_response)
allow(client).to receive(:get).with('/projects?page=20&per_page=5').and_return(last_page_response)
expect(@paginated_response.has_first_page?).to be true
expect(@paginated_response.has_last_page?).to be true
expect(@paginated_response.has_next_page?).to be false
expect(@paginated_response.has_prev_page?).to be false
expect(@paginated_response.first_page).to be first_page_response
expect(@paginated_response.last_page).to be last_page_response
expect(@paginated_response.next_page).to be_nil
expect(@paginated_response.prev_page).to be_nil
expect(@paginated_response.total).to eq('8')
end
context 'when the Link header endpoint does not match the configured endpoint' do
it 'removes the apprpriate prefix from the pagination link' do
@paginated_response.parse_headers!('Link' => '<http://example.com/api/v3/projects?page=1&per_page=5>; rel="first", <http://example.com/api/v3/projects?page=20&per_page=5>; rel="last"')
client = @paginated_response.client = double('client')
first_page_response = double('first_page_response')
last_page_response = double('last_page_response')
allow(client).to receive(:endpoint).and_return('http://internal.example.com/api/v3')
allow(client).to receive(:get).with('/projects?page=1&per_page=5').and_return(first_page_response)
allow(client).to receive(:get).with('/projects?page=20&per_page=5').and_return(last_page_response)
expect(@paginated_response.first_page).to be first_page_response
expect(@paginated_response.last_page).to be last_page_response
end
end
end
describe '.each_page' do
it 'iterates pages' do
next_page = double('next_page')
allow(@paginated_response).to receive_messages(has_next_page?: true, next_page: next_page)
allow(next_page).to receive(:has_next_page?).and_return(false)
expect { |b| @paginated_response.each_page(&b) }.to yield_successive_args(@paginated_response, next_page)
end
end
describe '.lazy_paginate' do
it 'returns a lazy enumerator' do
expect(@paginated_response.lazy_paginate).to be_an(Enumerator::Lazy)
end
it 'only requests needed pages' do
next_page = double('next_page')
allow(@paginated_response).to receive_messages(has_next_page?: true, next_page: next_page)
# NOTE: Do not define :next_page on the next_page double
# to prove that it is NOT called even though :has_next_page?
# has been defined to claim another page is available.
allow(next_page).to receive_messages(has_next_page?: true, to_ary: [5, 6, 7, 8])
expect(@paginated_response.lazy_paginate.take(8)).to contain_exactly(1, 2, 3, 4, 5, 6, 7, 8)
end
end
describe '.auto_paginate' do
it 'returns an array if block is not given' do
next_page = double('next_page')
allow(@paginated_response).to receive_messages(has_next_page?: true, next_page: next_page)
allow(next_page).to receive_messages(has_next_page?: false, to_ary: [5, 6, 7, 8])
expect(@paginated_response.auto_paginate).to contain_exactly(1, 2, 3, 4, 5, 6, 7, 8)
end
end
shared_context 'when performing with a block limited pagination returning an array' do
before do
next_page = double('next_page')
allow(@paginated_response).to receive_messages(has_next_page?: true, next_page: next_page)
allow(next_page).to receive_messages(has_next_page?: false, to_ary: [5, 6, 7, 8])
end
end
describe '.paginate_with_limit' do
include_context 'when performing with a block limited pagination returning an array'
it 'returns a limited array' do
expect(@paginated_response.paginate_with_limit(3)).to contain_exactly(1, 2, 3)
end
it 'returns exactly the first page' do
expect(@paginated_response.paginate_with_limit(4)).to contain_exactly(1, 2, 3, 4)
end
it 'returns a page plus one' do
next_page = double('next_page')
allow(@paginated_response).to receive_messages(has_next_page?: true, next_page: next_page)
allow(next_page).to receive_messages(has_next_page?: false, to_ary: [5])
expect(@paginated_response.paginate_with_limit(5)).to contain_exactly(1, 2, 3, 4, 5)
end
it 'iterates items with limit' do
expect { |b| @paginated_response.paginate_with_limit(3, &b) }.to yield_successive_args(1, 2, 3)
end
it 'iterates exactly the first page' do
expect { |b| @paginated_response.paginate_with_limit(4, &b) }.to yield_successive_args(1, 2, 3, 4)
end
it 'iterates the first page plus one' do
expect { |b| @paginated_response.paginate_with_limit(5, &b) }.to yield_successive_args(1, 2, 3, 4, 5)
end
end
describe '.client_relative_path' do
subject(:client_relative_path) do
@paginated_response.client_relative_path('https://127.0.0.1/api/v4/projects/1/merge_requests/2/notes')
end
it 'removes the prefix and api version from the link' do
client = @paginated_response.client = double('client')
allow(client).to receive(:endpoint).and_return('https://example.com/api/v4')
expect(client_relative_path).to eq '/projects/1/merge_requests/2/notes'
end
end
end
|