# Licensed to Elasticsearch B.V. under one or more contributor # license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright # ownership. Elasticsearch B.V. licenses this file to you under # the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. require 'spec_helper' describe 'Elasticsearch::Model::Response::Response WillPaginate' do before(:all) do class ModelClass def self.index_name; 'foo'; end def self.document_type; 'bar'; end def self.per_page 33 end end # Subclass Response so we can include WillPaginate module without conflicts with Kaminari. class WillPaginateResponse < Elasticsearch::Model::Response::Response include Elasticsearch::Model::Response::Pagination::WillPaginate end end after(:all) do remove_classes(ModelClass, WillPaginateResponse) end let(:response_document) do { 'took' => '5', 'timed_out' => false, '_shards' => {'one' => 'OK'}, 'hits' => { 'total' => 100, 'hits' => (1..100).to_a.map { |i| { _id: i } } } } end let(:search) do Elasticsearch::Model::Searching::SearchRequest.new(model, '*') end let(:response) do allow(model).to receive(:client).and_return(client) WillPaginateResponse.new(model, search, response_document).tap do |resp| allow(resp).to receive(:client).and_return(client) end end let(:client) do double('client') end shared_examples_for 'a search request that can be paginated' do describe '#offset' do context 'when per_page and page are set' do before do response.per_page(3).page(3) end it 'sets the correct offset' do expect(response.offset).to eq(6) end end end describe '#length' do context 'when per_page and page are set' do before do response.per_page(3).page(3) end it 'sets the correct offset' do expect(response.length).to eq(3) end end end describe '#paginate' do context 'when there are no settings' do context 'when page is set to nil' do before do response.paginate(page: nil) end it 'uses the defaults' do expect(response.search.definition[:size]).to eq(default_per_page) expect(response.search.definition[:from]).to eq(0) end end context 'when page is set to a value' do before do response.paginate(page: 2) end it 'uses the defaults' do expect(response.search.definition[:size]).to eq(default_per_page) expect(response.search.definition[:from]).to eq(default_per_page) end end context 'when a custom page and per_page is set' do before do response.paginate(page: 3, per_page: 9) end it 'uses the custom values' do expect(response.search.definition[:size]).to eq(9) expect(response.search.definition[:from]).to eq(18) end end context 'fall back to first page if invalid value is provided' do before do response.paginate(page: -1) end it 'uses the custom values' do expect(response.search.definition[:size]).to eq(default_per_page) expect(response.search.definition[:from]).to eq(0) end end end end describe '#page' do context 'when a value is provided for page' do before do response.page(5) end it 'calculates the correct :size and :from' do expect(response.search.definition[:size]).to eq(default_per_page) expect(response.search.definition[:from]).to eq(default_per_page * 4) end end context 'when a value is provided for page and per_page' do before do response.page(5).per_page(3) end it 'calculates the correct :size and :from' do expect(response.search.definition[:size]).to eq(3) expect(response.search.definition[:from]).to eq(12) end end context 'when a value is provided for per_page and page' do before do response.per_page(3).page(5) end it 'calculates the correct :size and :from' do expect(response.search.definition[:size]).to eq(3) expect(response.search.definition[:from]).to eq(12) end end end describe '#current_page' do context 'when no values are set' do before do response.paginate({}) end it 'returns the first page' do expect(response.current_page).to eq(1) end end context 'when values are provided for per_page and page' do before do response.paginate(page: 3, per_page: 9) end it 'calculates the correct current page' do expect(response.current_page).to eq(3) end end context 'when #paginate has not been called on the response' do it 'returns nil' do expect(response.current_page).to be_nil end end end describe '#per_page' do context 'when a value is set via the #paginate method' do before do response.paginate(per_page: 8) end it 'returns the per_page value' do expect(response.per_page).to eq(8) end end context 'when a value is set via the #per_page method' do before do response.per_page(8) end it 'returns the per_page value' do expect(response.per_page).to eq(8) end end end describe '#total_entries' do before do allow(response).to receive(:results).and_return(double('results', total: 100)) end it 'returns the total results' do expect(response.total_entries).to eq(100) end end end context 'when the model is a single one' do let(:model) do ModelClass end let(:default_per_page) do 33 end it_behaves_like 'a search request that can be paginated' end context 'when the model is a multimodel' do let(:model) do Elasticsearch::Model::Multimodel.new(ModelClass) end let(:default_per_page) do ::WillPaginate.per_page end it_behaves_like 'a search request that can be paginated' end end