summaryrefslogtreecommitdiff
path: root/spec/lib/api/helpers/pagination_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/api/helpers/pagination_spec.rb')
-rw-r--r--spec/lib/api/helpers/pagination_spec.rb212
1 files changed, 204 insertions, 8 deletions
diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb
index a547988d631..c73c6023b60 100644
--- a/spec/lib/api/helpers/pagination_spec.rb
+++ b/spec/lib/api/helpers/pagination_spec.rb
@@ -7,7 +7,203 @@ describe API::Helpers::Pagination do
Class.new.include(described_class).new
end
- describe '#paginate' do
+ describe '#paginate (keyset pagination)' do
+ let(:value) { spy('return value') }
+
+ before do
+ allow(value).to receive(:to_query).and_return(value)
+
+ allow(subject).to receive(:header).and_return(value)
+ allow(subject).to receive(:params).and_return(value)
+ allow(subject).to receive(:request).and_return(value)
+ end
+
+ context 'when resource can be paginated' do
+ let!(:projects) do
+ [
+ create(:project, name: 'One'),
+ create(:project, name: 'Two'),
+ create(:project, name: 'Three')
+ ].sort_by { |e| -e.id } # sort by id desc (this is the default sort order for the API)
+ end
+
+ describe 'first page' do
+ before do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', per_page: 2 })
+ end
+
+ it 'returns appropriate amount of resources' do
+ expect(subject.paginate(resource).count).to eq 2
+ end
+
+ it 'returns the first two records (by id desc)' do
+ expect(subject.paginate(resource)).to eq(projects[0..1])
+ end
+
+ it 'adds appropriate headers' do
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Next-Page', "#{value}?ks_prev_id=#{projects[1].id}&pagination=keyset&per_page=2")
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="next"')
+ end
+
+ subject.paginate(resource)
+ end
+ end
+
+ describe 'second page' do
+ before do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', per_page: 2, ks_prev_id: projects[1].id })
+ end
+
+ it 'returns appropriate amount of resources' do
+ expect(subject.paginate(resource).count).to eq 1
+ end
+
+ it 'returns the third record' do
+ expect(subject.paginate(resource)).to eq(projects[2..2])
+ end
+
+ it 'adds appropriate headers' do
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Next-Page', "#{value}?ks_prev_id=#{projects[2].id}&pagination=keyset&per_page=2")
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="next"')
+ end
+
+ subject.paginate(resource)
+ end
+ end
+
+ describe 'third page' do
+ before do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', per_page: 2, ks_prev_id: projects[2].id })
+ end
+
+ it 'returns appropriate amount of resources' do
+ expect(subject.paginate(resource).count).to eq 0
+ end
+
+ it 'adds appropriate headers' do
+ expect_header('X-Per-Page', '2')
+ expect(subject).not_to receive(:header).with('Link')
+
+ subject.paginate(resource)
+ end
+ end
+
+ context 'if order' do
+ context 'is not present' do
+ before do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', per_page: 2 })
+ end
+
+ it 'is not present it adds default order(:id) desc' do
+ resource.order_values = []
+
+ paginated_relation = subject.paginate(resource)
+
+ expect(resource.order_values).to be_empty
+ expect(paginated_relation.order_values).to be_present
+ expect(paginated_relation.order_values.size).to eq(1)
+ expect(paginated_relation.order_values.first).to be_descending
+ expect(paginated_relation.order_values.first.expr.name).to eq :id
+ end
+ end
+
+ context 'is present' do
+ let(:resource) { Project.all.order(name: :desc) }
+ let!(:projects) do
+ [
+ create(:project, name: 'One'),
+ create(:project, name: 'Two'),
+ create(:project, name: 'Three'),
+ create(:project, name: 'Three'), # Note the duplicate name
+ create(:project, name: 'Four'),
+ create(:project, name: 'Five'),
+ create(:project, name: 'Six')
+ ]
+
+ # if we sort this by name descending, id descending, this yields:
+ # {
+ # 2 => "Two",
+ # 4 => "Three",
+ # 3 => "Three",
+ # 7 => "Six",
+ # 1 => "One",
+ # 5 => "Four",
+ # 6 => "Five"
+ # }
+ #
+ # (key is the id)
+ end
+
+ it 'it also orders by primary key' do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', per_page: 2 })
+ paginated_relation = subject.paginate(resource)
+
+ expect(paginated_relation.order_values).to be_present
+ expect(paginated_relation.order_values.size).to eq(2)
+ expect(paginated_relation.order_values.first).to be_descending
+ expect(paginated_relation.order_values.first.expr.name).to eq :name
+ expect(paginated_relation.order_values.second).to be_descending
+ expect(paginated_relation.order_values.second.expr.name).to eq :id
+ end
+
+ it 'it returns the right records (first page)' do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', per_page: 2 })
+ result = subject.paginate(resource)
+
+ expect(result.first).to eq(projects[1])
+ expect(result.second).to eq(projects[3])
+ end
+
+ it 'it returns the right records (second page)' do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', ks_prev_id: projects[3].id, ks_prev_name: projects[3].name, per_page: 2 })
+ result = subject.paginate(resource)
+
+ expect(result.first).to eq(projects[2])
+ expect(result.second).to eq(projects[6])
+ end
+
+ it 'it returns the right records (third page), note increased per_page' do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', ks_prev_id: projects[6].id, ks_prev_name: projects[6].name, per_page: 5 })
+ result = subject.paginate(resource)
+
+ expect(result.size).to eq(3)
+ expect(result.first).to eq(projects[0])
+ expect(result.second).to eq(projects[4])
+ expect(result.last).to eq(projects[5])
+ end
+
+ it 'it returns the right link to the next page' do
+ allow(subject).to receive(:params)
+ .and_return({ pagination: 'keyset', ks_prev_id: projects[3].id, ks_prev_name: projects[3].name, per_page: 2 })
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Next-Page', "#{value}?ks_prev_id=#{projects[6].id}&ks_prev_name=#{projects[6].name}&pagination=keyset&per_page=2")
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="next"')
+ end
+
+ subject.paginate(resource)
+ end
+ end
+ end
+ end
+ end
+
+ describe '#paginate (default offset-based pagination)' do
let(:value) { spy('return value') }
before do
@@ -146,14 +342,14 @@ describe API::Helpers::Pagination do
end
end
end
+ end
- def expect_header(*args, &block)
- expect(subject).to receive(:header).with(*args, &block)
- end
+ def expect_header(*args, &block)
+ expect(subject).to receive(:header).with(*args, &block)
+ end
- def expect_message(method)
- expect(subject).to receive(method)
- .at_least(:once).and_return(value)
- end
+ def expect_message(method)
+ expect(subject).to receive(method)
+ .at_least(:once).and_return(value)
end
end