Skip to content

Commit ff6c23d

Browse files
committed
[MODEL] Port adapter tests to rspec (elastic#834)
* [MODEL] Port adapter tests to rspec * [MODEL] Fix spacing in new specs
1 parent f3fde1c commit ff6c23d

11 files changed

+762
-551
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
require 'spec_helper'
2+
3+
describe Elasticsearch::Model::Adapter do
4+
5+
before(:all) do
6+
class ::DummyAdapterClass; end
7+
class ::DummyAdapterClassWithAdapter; end
8+
class ::DummyAdapter
9+
Records = Module.new
10+
Callbacks = Module.new
11+
Importing = Module.new
12+
end
13+
end
14+
15+
after(:all) do
16+
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyAdapterClassWithAdapter)
17+
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyAdapterClass)
18+
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyAdapter)
19+
Object.send(:remove_const, :DummyAdapterClass) if defined?(DummyAdapterClass)
20+
Object.send(:remove_const, :DummyAdapterClassWithAdapter) if defined?(DummyAdapterClassWithAdapter)
21+
Object.send(:remove_const, :DummyAdapter) if defined?(DummyAdapter)
22+
end
23+
24+
describe '#from_class' do
25+
26+
it 'should return an Adapter instance' do
27+
expect(Elasticsearch::Model::Adapter.from_class(DummyAdapterClass)).to be_a(Elasticsearch::Model::Adapter::Adapter)
28+
end
29+
end
30+
31+
describe 'register' do
32+
33+
before do
34+
expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original
35+
Elasticsearch::Model::Adapter.register(:foo, lambda { |c| false })
36+
end
37+
38+
it 'should register an adapter' do
39+
expect(Elasticsearch::Model::Adapter::Adapter.adapters[:foo]).to be_a(Proc)
40+
end
41+
42+
context 'when a specific adapter class is set' do
43+
44+
before do
45+
expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original
46+
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
47+
lambda { |c| c == DummyAdapterClassWithAdapter })
48+
end
49+
50+
let(:adapter) do
51+
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
52+
end
53+
54+
it 'should register the adapter' do
55+
expect(adapter.adapter).to eq(DummyAdapter)
56+
end
57+
end
58+
end
59+
60+
describe 'default adapter' do
61+
62+
let(:adapter) do
63+
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClass)
64+
end
65+
66+
it 'sets a default adapter' do
67+
expect(adapter.adapter).to eq(Elasticsearch::Model::Adapter::Default)
68+
end
69+
end
70+
71+
describe '#records_mixin' do
72+
73+
before do
74+
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
75+
lambda { |c| c == DummyAdapterClassWithAdapter })
76+
77+
end
78+
79+
let(:adapter) do
80+
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
81+
end
82+
83+
it 'returns a Module' do
84+
expect(adapter.records_mixin).to be_a(Module)
85+
end
86+
end
87+
88+
describe '#callbacks_mixin' do
89+
90+
before do
91+
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
92+
lambda { |c| c == DummyAdapterClassWithAdapter })
93+
94+
end
95+
96+
let(:adapter) do
97+
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
98+
end
99+
100+
it 'returns a Module' do
101+
expect(adapter.callbacks_mixin).to be_a(Module)
102+
end
103+
end
104+
105+
describe '#importing_mixin' do
106+
107+
before do
108+
Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
109+
lambda { |c| c == DummyAdapterClassWithAdapter })
110+
111+
end
112+
113+
let(:adapter) do
114+
Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClassWithAdapter)
115+
end
116+
117+
it 'returns a Module' do
118+
expect(adapter.importing_mixin).to be_a(Module)
119+
end
120+
end
121+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
require 'spec_helper'
2+
3+
describe Elasticsearch::Model::Adapter::ActiveRecord do
4+
5+
before(:all) do
6+
class DummyClassForActiveRecord; end
7+
end
8+
9+
after(:all) do
10+
Elasticsearch::Model::Adapter::Adapter.adapters.delete(DummyClassForActiveRecord)
11+
Object.send(:remove_const, :DummyClassForActiveRecord) if defined?(DummyClassForActiveRecord)
12+
end
13+
14+
let(:model) do
15+
DummyClassForActiveRecord.new.tap do |m|
16+
allow(m).to receive(:response).and_return(double('response', response: response))
17+
allow(m).to receive(:ids).and_return(ids)
18+
end
19+
end
20+
21+
let(:response) do
22+
{ 'hits' => {'hits' => [ {'_id' => 2 }, {'_id' => 1 } ]} }
23+
end
24+
25+
let(:ids) do
26+
[2, 1]
27+
end
28+
29+
let(:record_1) do
30+
double('record').tap do |rec|
31+
allow(rec).to receive(:id).and_return(1)
32+
end
33+
end
34+
35+
let(:record_2) do
36+
double('record').tap do |rec|
37+
allow(rec).to receive(:id).and_return(2)
38+
end
39+
end
40+
41+
let(:records) do
42+
[record_1, record_2].tap do |r|
43+
allow(r).to receive(:load).and_return(true)
44+
allow(r).to receive(:exec_queries).and_return(true)
45+
end
46+
end
47+
48+
describe 'adapter registration' do
49+
50+
before(:all) do
51+
DummyClassForActiveRecord.__send__ :include, Elasticsearch::Model::Adapter::ActiveRecord::Records
52+
end
53+
54+
it 'can register an adapater' do
55+
expect(Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::ActiveRecord]).not_to be_nil
56+
expect(Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::ActiveRecord].call(DummyClassForActiveRecord)).to be(false)
57+
end
58+
end
59+
60+
describe '#records' do
61+
62+
before(:all) do
63+
DummyClassForActiveRecord.__send__ :include, Elasticsearch::Model::Adapter::ActiveRecord::Records
64+
end
65+
66+
let(:instance) do
67+
model.tap do |inst|
68+
allow(inst).to receive(:klass).and_return(double('class', primary_key: :some_key, where: records)).at_least(:once)
69+
end
70+
end
71+
72+
it 'returns the list of records' do
73+
expect(instance.records).to eq(records)
74+
end
75+
76+
it 'loads the records' do
77+
expect(instance.load).to eq(true)
78+
end
79+
80+
context 'when :includes is specified' do
81+
82+
before do
83+
expect(records).to receive(:includes).with([:submodel]).once.and_return(records)
84+
instance.options[:includes] = [:submodel]
85+
end
86+
87+
it 'incorporates the includes option in the query' do
88+
expect(instance.records).to eq(records)
89+
end
90+
end
91+
92+
context 'when an order is not defined for the ActiveRecord query' do
93+
94+
context 'when the records have a different order than the hits' do
95+
96+
before do
97+
records.instance_variable_set(:@records, records)
98+
end
99+
100+
it 'reorders the records based on hits order' do
101+
expect(records.collect(&:id)).to eq([1, 2])
102+
expect(instance.records.to_a.collect(&:id)).to eq([2, 1])
103+
end
104+
end
105+
end
106+
107+
context 'when an order is defined for the ActiveRecord query' do
108+
109+
context 'when the records have a different order than the hits' do
110+
111+
before do
112+
records.instance_variable_set(:@records, records)
113+
expect(instance.records).to receive(:order).and_return(records)
114+
end
115+
116+
it 'reorders the records based on hits order' do
117+
expect(records.collect(&:id)).to eq([1, 2])
118+
expect(instance.records.to_a.collect(&:id)).to eq([2, 1])
119+
expect(instance.order(:foo).to_a.collect(&:id)).to eq([1, 2])
120+
end
121+
end
122+
end
123+
end
124+
125+
describe 'callbacks registration' do
126+
127+
before do
128+
expect(DummyClassForActiveRecord).to receive(:after_commit).exactly(3).times
129+
end
130+
131+
it 'should register the model class for callbacks' do
132+
Elasticsearch::Model::Adapter::ActiveRecord::Callbacks.included(DummyClassForActiveRecord)
133+
end
134+
end
135+
136+
describe 'importing' do
137+
138+
before do
139+
DummyClassForActiveRecord.__send__ :extend, Elasticsearch::Model::Adapter::ActiveRecord::Importing
140+
end
141+
142+
context 'when an invalid scope is specified' do
143+
144+
it 'raises a NoMethodError' do
145+
expect {
146+
DummyClassForActiveRecord.__find_in_batches(scope: :not_found_method)
147+
}.to raise_exception(NoMethodError)
148+
end
149+
end
150+
151+
context 'when a valid scope is specified' do
152+
153+
before do
154+
expect(DummyClassForActiveRecord).to receive(:find_in_batches).once.and_return([])
155+
expect(DummyClassForActiveRecord).to receive(:published).once.and_return(DummyClassForActiveRecord)
156+
end
157+
158+
it 'uses the scope' do
159+
expect(DummyClassForActiveRecord.__find_in_batches(scope: :published)).to eq([])
160+
end
161+
end
162+
163+
context 'allow query criteria to be specified' do
164+
165+
before do
166+
expect(DummyClassForActiveRecord).to receive(:find_in_batches).once.and_return([])
167+
expect(DummyClassForActiveRecord).to receive(:where).with(color: 'red').once.and_return(DummyClassForActiveRecord)
168+
end
169+
170+
it 'uses the scope' do
171+
expect(DummyClassForActiveRecord.__find_in_batches(query: -> { where(color: 'red') })).to eq([])
172+
end
173+
end
174+
175+
context 'when preprocessing batches' do
176+
177+
context 'if the query returns results' do
178+
179+
before do
180+
class << DummyClassForActiveRecord
181+
def find_in_batches(options = {}, &block)
182+
yield [:a, :b]
183+
end
184+
185+
def update_batch(batch)
186+
batch.collect { |b| b.to_s + '!' }
187+
end
188+
end
189+
end
190+
191+
it 'applies the preprocessing method' do
192+
DummyClassForActiveRecord.__find_in_batches(preprocess: :update_batch) do |batch|
193+
expect(batch).to match(['a!', 'b!'])
194+
end
195+
end
196+
end
197+
198+
context 'if the query does not return results' do
199+
200+
before do
201+
class << DummyClassForActiveRecord
202+
def find_in_batches(options = {}, &block)
203+
yield [:a, :b]
204+
end
205+
206+
def update_batch(batch)
207+
[]
208+
end
209+
end
210+
end
211+
212+
it 'applies the preprocessing method' do
213+
DummyClassForActiveRecord.__find_in_batches(preprocess: :update_batch) do |batch|
214+
expect(batch).to match([])
215+
end
216+
end
217+
end
218+
end
219+
220+
context 'when transforming models' do
221+
222+
let(:instance) do
223+
model.tap do |inst|
224+
allow(inst).to receive(:id).and_return(1)
225+
allow(inst).to receive(:__elasticsearch__).and_return(double('object', id: 1, as_indexed_json: {}))
226+
end
227+
end
228+
229+
it 'returns an proc' do
230+
expect(DummyClassForActiveRecord.__transform.respond_to?(:call)).to be(true)
231+
end
232+
233+
it 'provides a default transformation' do
234+
expect(DummyClassForActiveRecord.__transform.call(instance)).to eq(index: { _id: 1, data: {} })
235+
end
236+
end
237+
end
238+
end

0 commit comments

Comments
 (0)