Skip to content

[MODEL] Port adapter tests to rspec #834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions elasticsearch-model/spec/elasticsearch/model/adapter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require 'spec_helper'

describe Elasticsearch::Model::Adapter do

before(:all) do
class ::DummyAdapterClass; end
class ::DummyAdapterClassWithAdapter; end
class ::DummyAdapter
Records = Module.new
Callbacks = Module.new
Importing = Module.new
end
end

after(:all) do
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyAdapterClassWithAdapter)
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyAdapterClass)
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyAdapter)
Object.send(:remove_const, :DummyAdapterClass) if defined?(DummyAdapterClass)
Object.send(:remove_const, :DummyAdapterClassWithAdapter) if defined?(DummyAdapterClassWithAdapter)
Object.send(:remove_const, :DummyAdapter) if defined?(DummyAdapter)
end

describe '#from_class' do

it 'should return an Adapter instance' do
expect(Elasticsearch::Model::Adapter.from_class(DummyAdapterClass)).to be_a(Elasticsearch::Model::Adapter::Adapter)
end
end

describe 'register' do

before do
expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original
Elasticsearch::Model::Adapter.register(:foo, lambda { |c| false })
end

it 'should register an adapter' do
expect(Elasticsearch::Model::Adapter::Adapter.adapters[:foo]).to be_a(Proc)
end

context 'when a specific adapter class is set' do

before do
expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
lambda { |c| c == DummyAdapterClassWithAdapter })
end

let(:adapter) do
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
end

it 'should register the adapter' do
expect(adapter.adapter).to eq(DummyAdapter)
end
end
end

describe 'default adapter' do

let(:adapter) do
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClass)
end

it 'sets a default adapter' do
expect(adapter.adapter).to eq(Elasticsearch::Model::Adapter::Default)
end
end

describe '#records_mixin' do

before do
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
lambda { |c| c == DummyAdapterClassWithAdapter })

end

let(:adapter) do
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
end

it 'returns a Module' do
expect(adapter.records_mixin).to be_a(Module)
end
end

describe '#callbacks_mixin' do

before do
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
lambda { |c| c == DummyAdapterClassWithAdapter })

end

let(:adapter) do
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
end

it 'returns a Module' do
expect(adapter.callbacks_mixin).to be_a(Module)
end
end

describe '#importing_mixin' do

before do
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
lambda { |c| c == DummyAdapterClassWithAdapter })

end

let(:adapter) do
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
end

it 'returns a Module' do
expect(adapter.importing_mixin).to be_a(Module)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
require 'spec_helper'

describe Elasticsearch::Model::Adapter::ActiveRecord do

before(:all) do
class DummyClassForActiveRecord; end
end

after(:all) do
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyClassForActiveRecord)
Object.send(:remove_const, :DummyClassForActiveRecord) if defined?(DummyClassForActiveRecord)
end

let(:model) do
DummyClassForActiveRecord.new.tap do |m|
allow(m).to receive(:response).and_return(double('response', response: response))
allow(m).to receive(:ids).and_return(ids)
end
end

let(:response) do
{ 'hits' => {'hits' => [ {'_id' => 2 }, {'_id' => 1 } ]} }
end

let(:ids) do
[2, 1]
end

let(:record_1) do
double('record').tap do |rec|
allow(rec).to receive(:id).and_return(1)
end
end

let(:record_2) do
double('record').tap do |rec|
allow(rec).to receive(:id).and_return(2)
end
end

let(:records) do
[record_1, record_2].tap do |r|
allow(r).to receive(:load).and_return(true)
allow(r).to receive(:exec_queries).and_return(true)
end
end

describe 'adapter registration' do

before(:all) do
DummyClassForActiveRecord.__send__ :include, Elasticsearch::Model::Adapter::ActiveRecord::Records
end

it 'can register an adapater' do
expect(Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::ActiveRecord]).not_to be_nil
expect(Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::ActiveRecord].call(DummyClassForActiveRecord)).to be(false)
end
end

describe '#records' do

before(:all) do
DummyClassForActiveRecord.__send__ :include, Elasticsearch::Model::Adapter::ActiveRecord::Records
end

let(:instance) do
model.tap do |inst|
allow(inst).to receive(:klass).and_return(double('class', primary_key: :some_key, where: records)).at_least(:once)
end
end

it 'returns the list of records' do
expect(instance.records).to eq(records)
end

it 'loads the records' do
expect(instance.load).to eq(true)
end

context 'when :includes is specified' do

before do
expect(records).to receive(:includes).with([:submodel]).once.and_return(records)
instance.options[:includes] = [:submodel]
end

it 'incorporates the includes option in the query' do
expect(instance.records).to eq(records)
end
end

context 'when an order is not defined for the ActiveRecord query' do

context 'when the records have a different order than the hits' do

before do
records.instance_variable_set(:@records, records)
end

it 'reorders the records based on hits order' do
expect(records.collect(&:id)).to eq([1, 2])
expect(instance.records.to_a.collect(&:id)).to eq([2, 1])
end
end
end

context 'when an order is defined for the ActiveRecord query' do

context 'when the records have a different order than the hits' do

before do
records.instance_variable_set(:@records, records)
expect(instance.records).to receive(:order).and_return(records)
end

it 'reorders the records based on hits order' do
expect(records.collect(&:id)).to eq([1, 2])
expect(instance.records.to_a.collect(&:id)).to eq([2, 1])
expect(instance.order(:foo).to_a.collect(&:id)).to eq([1, 2])
end
end
end
end

describe 'callbacks registration' do

before do
expect(DummyClassForActiveRecord).to receive(:after_commit).exactly(3).times
end

it 'should register the model class for callbacks' do
Elasticsearch::Model::Adapter::ActiveRecord::Callbacks.included(DummyClassForActiveRecord)
end
end

describe 'importing' do

before do
DummyClassForActiveRecord.__send__ :extend, Elasticsearch::Model::Adapter::ActiveRecord::Importing
end

context 'when an invalid scope is specified' do

it 'raises a NoMethodError' do
expect {
DummyClassForActiveRecord.__find_in_batches(scope: :not_found_method)
}.to raise_exception(NoMethodError)
end
end

context 'when a valid scope is specified' do

before do
expect(DummyClassForActiveRecord).to receive(:find_in_batches).once.and_return([])
expect(DummyClassForActiveRecord).to receive(:published).once.and_return(DummyClassForActiveRecord)
end

it 'uses the scope' do
expect(DummyClassForActiveRecord.__find_in_batches(scope: :published)).to eq([])
end
end

context 'allow query criteria to be specified' do

before do
expect(DummyClassForActiveRecord).to receive(:find_in_batches).once.and_return([])
expect(DummyClassForActiveRecord).to receive(:where).with(color: 'red').once.and_return(DummyClassForActiveRecord)
end

it 'uses the scope' do
expect(DummyClassForActiveRecord.__find_in_batches(query: -> { where(color: 'red') })).to eq([])
end
end

context 'when preprocessing batches' do

context 'if the query returns results' do

before do
class << DummyClassForActiveRecord
def find_in_batches(options = {}, &block)
yield [:a, :b]
end

def update_batch(batch)
batch.collect { |b| b.to_s + '!' }
end
end
end

it 'applies the preprocessing method' do
DummyClassForActiveRecord.__find_in_batches(preprocess: :update_batch) do |batch|
expect(batch).to match(['a!', 'b!'])
end
end
end

context 'if the query does not return results' do

before do
class << DummyClassForActiveRecord
def find_in_batches(options = {}, &block)
yield [:a, :b]
end

def update_batch(batch)
[]
end
end
end

it 'applies the preprocessing method' do
DummyClassForActiveRecord.__find_in_batches(preprocess: :update_batch) do |batch|
expect(batch).to match([])
end
end
end
end

context 'when transforming models' do

let(:instance) do
model.tap do |inst|
allow(inst).to receive(:id).and_return(1)
allow(inst).to receive(:__elasticsearch__).and_return(double('object', id: 1, as_indexed_json: {}))
end
end

it 'returns an proc' do
expect(DummyClassForActiveRecord.__transform.respond_to?(:call)).to be(true)
end

it 'provides a default transformation' do
expect(DummyClassForActiveRecord.__transform.call(instance)).to eq(index: { _id: 1, data: {} })
end
end
end
end
Loading