cuprum-collections 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -0
- data/DEVELOPMENT.md +2 -2
- data/README.md +13 -11
- data/lib/cuprum/collections/association.rb +256 -0
- data/lib/cuprum/collections/associations/belongs_to.rb +32 -0
- data/lib/cuprum/collections/associations/has_many.rb +23 -0
- data/lib/cuprum/collections/associations/has_one.rb +23 -0
- data/lib/cuprum/collections/associations.rb +10 -0
- data/lib/cuprum/collections/basic/collection.rb +39 -74
- data/lib/cuprum/collections/basic/commands/find_many.rb +1 -1
- data/lib/cuprum/collections/basic/commands/find_matching.rb +1 -1
- data/lib/cuprum/collections/basic/repository.rb +9 -33
- data/lib/cuprum/collections/basic.rb +1 -0
- data/lib/cuprum/collections/collection.rb +154 -0
- data/lib/cuprum/collections/commands/associations/find_many.rb +161 -0
- data/lib/cuprum/collections/commands/associations/require_many.rb +48 -0
- data/lib/cuprum/collections/commands/associations.rb +13 -0
- data/lib/cuprum/collections/commands/find_one_matching.rb +1 -1
- data/lib/cuprum/collections/commands.rb +1 -0
- data/lib/cuprum/collections/errors/abstract_find_error.rb +1 -1
- data/lib/cuprum/collections/relation.rb +401 -0
- data/lib/cuprum/collections/repository.rb +71 -4
- data/lib/cuprum/collections/resource.rb +65 -0
- data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +2137 -0
- data/lib/cuprum/collections/rspec/contracts/basic/command_contracts.rb +484 -0
- data/lib/cuprum/collections/rspec/contracts/basic.rb +11 -0
- data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +429 -0
- data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +1462 -0
- data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +1093 -0
- data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +1381 -0
- data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +605 -0
- data/lib/cuprum/collections/rspec/contracts.rb +23 -0
- data/lib/cuprum/collections/rspec/fixtures.rb +85 -82
- data/lib/cuprum/collections/rspec.rb +4 -1
- data/lib/cuprum/collections/version.rb +1 -1
- data/lib/cuprum/collections.rb +9 -4
- metadata +23 -19
- data/lib/cuprum/collections/base.rb +0 -11
- data/lib/cuprum/collections/basic/rspec/command_contract.rb +0 -392
- data/lib/cuprum/collections/rspec/assign_one_command_contract.rb +0 -168
- data/lib/cuprum/collections/rspec/build_one_command_contract.rb +0 -93
- data/lib/cuprum/collections/rspec/collection_contract.rb +0 -190
- data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +0 -108
- data/lib/cuprum/collections/rspec/find_many_command_contract.rb +0 -407
- data/lib/cuprum/collections/rspec/find_matching_command_contract.rb +0 -194
- data/lib/cuprum/collections/rspec/find_one_command_contract.rb +0 -157
- data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +0 -84
- data/lib/cuprum/collections/rspec/query_builder_contract.rb +0 -92
- data/lib/cuprum/collections/rspec/query_contract.rb +0 -650
- data/lib/cuprum/collections/rspec/querying_contract.rb +0 -298
- data/lib/cuprum/collections/rspec/repository_contract.rb +0 -235
- data/lib/cuprum/collections/rspec/update_one_command_contract.rb +0 -80
- data/lib/cuprum/collections/rspec/validate_one_command_contract.rb +0 -96
@@ -1,650 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cuprum/collections/rspec'
|
4
|
-
require 'cuprum/collections/rspec/fixtures'
|
5
|
-
require 'cuprum/collections/rspec/querying_contract'
|
6
|
-
|
7
|
-
module Cuprum::Collections::RSpec # rubocop:disable Style/Documentation
|
8
|
-
default_operators = Cuprum::Collections::Queries::Operators.values
|
9
|
-
|
10
|
-
# Contract validating the behavior of a Query implementation.
|
11
|
-
QUERY_CONTRACT = lambda do |operators: default_operators.freeze|
|
12
|
-
operators = Set.new(operators.map(&:to_sym))
|
13
|
-
|
14
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTEXTS
|
15
|
-
|
16
|
-
shared_context 'when the query has composed filters' do
|
17
|
-
let(:scoped_query) do
|
18
|
-
super()
|
19
|
-
.where { { author: 'Ursula K. LeGuin' } }
|
20
|
-
.where { { series: not_equal('Earthsea') } }
|
21
|
-
end
|
22
|
-
let(:matching_data) do
|
23
|
-
super()
|
24
|
-
.select { |item| item['author'] == 'Ursula K. LeGuin' }
|
25
|
-
.reject { |item| item['series'] == 'Earthsea' }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:scoped_query) do
|
30
|
-
# :nocov:
|
31
|
-
scoped =
|
32
|
-
if filter.is_a?(Proc)
|
33
|
-
query.where(&filter)
|
34
|
-
elsif !filter.nil?
|
35
|
-
query.where(filter)
|
36
|
-
else
|
37
|
-
query
|
38
|
-
end
|
39
|
-
# :nocov:
|
40
|
-
scoped = scoped.limit(limit) if limit
|
41
|
-
scoped = scoped.offset(offset) if offset
|
42
|
-
scoped = scoped.order(order) if order
|
43
|
-
|
44
|
-
scoped
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should be enumerable' do
|
48
|
-
expect(described_class).to be < Enumerable
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#count' do
|
52
|
-
let(:data) { [] }
|
53
|
-
let(:matching_data) { data }
|
54
|
-
let(:expected_data) do
|
55
|
-
defined?(super()) ? super() : matching_data
|
56
|
-
end
|
57
|
-
|
58
|
-
it { expect(query).to respond_to(:count).with(0).arguments }
|
59
|
-
|
60
|
-
it { expect(query.count).to be == expected_data.count }
|
61
|
-
|
62
|
-
wrap_context 'when the query has composed filters' do
|
63
|
-
it { expect(scoped_query.count).to be == expected_data.count }
|
64
|
-
end
|
65
|
-
|
66
|
-
context 'when the collection data changes' do
|
67
|
-
let(:item) { BOOKS_FIXTURES.first }
|
68
|
-
|
69
|
-
before(:example) do
|
70
|
-
query.count # Cache query results.
|
71
|
-
|
72
|
-
add_item_to_collection(item)
|
73
|
-
end
|
74
|
-
|
75
|
-
it { expect(query.count).to be == expected_data.count }
|
76
|
-
end
|
77
|
-
|
78
|
-
context 'when the collection has many items' do
|
79
|
-
let(:data) { BOOKS_FIXTURES }
|
80
|
-
|
81
|
-
it { expect(query.count).to be == expected_data.count }
|
82
|
-
|
83
|
-
wrap_context 'when the query has composed filters' do
|
84
|
-
it { expect(scoped_query.count).to be == expected_data.count }
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'when the collection data changes' do
|
88
|
-
let(:data) { BOOKS_FIXTURES[0...-1] }
|
89
|
-
let(:item) { BOOKS_FIXTURES.last }
|
90
|
-
|
91
|
-
before(:example) do
|
92
|
-
query.count # Cache query results.
|
93
|
-
|
94
|
-
add_item_to_collection(item)
|
95
|
-
end
|
96
|
-
|
97
|
-
it { expect(query.count).to be == expected_data.count }
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#criteria' do
|
103
|
-
include_examples 'should have reader', :criteria, []
|
104
|
-
|
105
|
-
wrap_context 'when the query has where: a simple block filter' do
|
106
|
-
let(:expected) { [['author', :equal, 'Ursula K. LeGuin']] }
|
107
|
-
|
108
|
-
it { expect(scoped_query.criteria).to be == expected }
|
109
|
-
end
|
110
|
-
|
111
|
-
wrap_context 'when the query has where: a complex block filter' do
|
112
|
-
let(:expected) do
|
113
|
-
[
|
114
|
-
['author', :equal, 'Ursula K. LeGuin'],
|
115
|
-
['series', :not_equal, 'Earthsea']
|
116
|
-
]
|
117
|
-
end
|
118
|
-
|
119
|
-
if operators.include?(OPERATORS::EQUAL) &&
|
120
|
-
operators.include?(OPERATORS::NOT_EQUAL)
|
121
|
-
it { expect(scoped_query.criteria).to be == expected }
|
122
|
-
else
|
123
|
-
# :nocov:
|
124
|
-
pending
|
125
|
-
# :nocov:
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
wrap_context 'when the query has composed filters' do
|
130
|
-
let(:expected) do
|
131
|
-
[
|
132
|
-
['author', :equal, 'Ursula K. LeGuin'],
|
133
|
-
['series', :not_equal, 'Earthsea']
|
134
|
-
]
|
135
|
-
end
|
136
|
-
|
137
|
-
it { expect(scoped_query.criteria).to be == expected }
|
138
|
-
end
|
139
|
-
|
140
|
-
wrap_context 'when the query has where: an equal block filter' do
|
141
|
-
let(:expected) { [['author', :equal, 'Ursula K. LeGuin']] }
|
142
|
-
|
143
|
-
if operators.include?(OPERATORS::EQUAL)
|
144
|
-
it { expect(scoped_query.criteria).to be == expected }
|
145
|
-
else
|
146
|
-
# :nocov:
|
147
|
-
pending
|
148
|
-
# :nocov:
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
wrap_context 'when the query has where: a not_equal block filter' do
|
153
|
-
let(:expected) { [['author', :not_equal, 'Ursula K. LeGuin']] }
|
154
|
-
|
155
|
-
if operators.include?(OPERATORS::NOT_EQUAL)
|
156
|
-
it { expect(scoped_query.criteria).to be == expected }
|
157
|
-
else
|
158
|
-
# :nocov:
|
159
|
-
pending
|
160
|
-
# :nocov:
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
describe '#each' do
|
166
|
-
shared_examples 'should enumerate the matching data' do
|
167
|
-
describe 'with no arguments' do
|
168
|
-
it { expect(scoped_query.each).to be_a Enumerator }
|
169
|
-
|
170
|
-
it { expect(scoped_query.each.count).to be == matching_data.size }
|
171
|
-
|
172
|
-
it { expect(scoped_query.each.to_a).to deep_match expected_data }
|
173
|
-
end
|
174
|
-
|
175
|
-
describe 'with a block' do
|
176
|
-
it 'should yield each matching item' do
|
177
|
-
expect { |block| scoped_query.each(&block) }
|
178
|
-
.to yield_successive_args(*expected_data)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
let(:data) { [] }
|
184
|
-
let(:matching_data) { data }
|
185
|
-
let(:expected_data) do
|
186
|
-
defined?(super()) ? super() : matching_data
|
187
|
-
end
|
188
|
-
|
189
|
-
it { expect(query).to respond_to(:each).with(0).arguments }
|
190
|
-
|
191
|
-
include_examples 'should enumerate the matching data'
|
192
|
-
|
193
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTRACT,
|
194
|
-
block: lambda {
|
195
|
-
include_examples 'should enumerate the matching data'
|
196
|
-
},
|
197
|
-
operators: operators
|
198
|
-
|
199
|
-
wrap_context 'when the query has composed filters' do
|
200
|
-
include_examples 'should enumerate the matching data'
|
201
|
-
end
|
202
|
-
|
203
|
-
context 'when the collection data changes' do
|
204
|
-
let(:item) { BOOKS_FIXTURES.first }
|
205
|
-
|
206
|
-
before(:example) do
|
207
|
-
query.each {} # Cache query results.
|
208
|
-
|
209
|
-
add_item_to_collection(item)
|
210
|
-
end
|
211
|
-
|
212
|
-
include_examples 'should enumerate the matching data'
|
213
|
-
end
|
214
|
-
|
215
|
-
context 'when the collection has many items' do
|
216
|
-
let(:data) { BOOKS_FIXTURES }
|
217
|
-
|
218
|
-
include_examples 'should enumerate the matching data'
|
219
|
-
|
220
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTRACT,
|
221
|
-
block: lambda {
|
222
|
-
include_examples 'should enumerate the matching data'
|
223
|
-
},
|
224
|
-
operators: operators
|
225
|
-
|
226
|
-
wrap_context 'when the query has composed filters' do
|
227
|
-
include_examples 'should enumerate the matching data'
|
228
|
-
end
|
229
|
-
|
230
|
-
context 'when the collection data changes' do
|
231
|
-
let(:data) { BOOKS_FIXTURES[0...-1] }
|
232
|
-
let(:item) { BOOKS_FIXTURES.last }
|
233
|
-
|
234
|
-
before(:example) do
|
235
|
-
query.each {} # Cache query results.
|
236
|
-
|
237
|
-
add_item_to_collection(item)
|
238
|
-
end
|
239
|
-
|
240
|
-
include_examples 'should enumerate the matching data'
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
describe '#exists?' do
|
246
|
-
shared_examples 'should check the existence of matching data' do
|
247
|
-
it { expect(query.exists?).to be == !matching_data.empty? }
|
248
|
-
end
|
249
|
-
|
250
|
-
let(:data) { [] }
|
251
|
-
let(:matching_data) { data }
|
252
|
-
|
253
|
-
include_examples 'should define predicate', :exists?
|
254
|
-
|
255
|
-
include_examples 'should check the existence of matching data'
|
256
|
-
|
257
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTRACT,
|
258
|
-
block: lambda {
|
259
|
-
include_examples 'should check the existence of matching data'
|
260
|
-
},
|
261
|
-
operators: operators
|
262
|
-
|
263
|
-
wrap_context 'when the query has composed filters' do
|
264
|
-
include_examples 'should check the existence of matching data'
|
265
|
-
end
|
266
|
-
|
267
|
-
context 'when the collection has many items' do
|
268
|
-
let(:data) { BOOKS_FIXTURES }
|
269
|
-
|
270
|
-
include_examples 'should check the existence of matching data'
|
271
|
-
|
272
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTRACT,
|
273
|
-
block: lambda {
|
274
|
-
include_examples 'should check the existence of matching data'
|
275
|
-
},
|
276
|
-
operators: operators
|
277
|
-
|
278
|
-
wrap_context 'when the query has composed filters' do
|
279
|
-
include_examples 'should check the existence of matching data'
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
describe '#limit' do
|
285
|
-
it { expect(query).to respond_to(:limit).with(0..1).arguments }
|
286
|
-
|
287
|
-
describe 'with no arguments' do
|
288
|
-
it { expect(query.limit).to be nil }
|
289
|
-
end
|
290
|
-
|
291
|
-
describe 'with nil' do
|
292
|
-
let(:error_message) { 'limit must be a non-negative integer' }
|
293
|
-
|
294
|
-
it 'should raise an exception' do
|
295
|
-
expect { query.limit nil }
|
296
|
-
.to raise_error ArgumentError, error_message
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
describe 'with an object' do
|
301
|
-
let(:error_message) { 'limit must be a non-negative integer' }
|
302
|
-
|
303
|
-
it 'should raise an exception' do
|
304
|
-
expect { query.limit Object.new.freeze }
|
305
|
-
.to raise_error ArgumentError, error_message
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
describe 'with a negative integer' do
|
310
|
-
let(:error_message) { 'limit must be a non-negative integer' }
|
311
|
-
|
312
|
-
it 'should raise an exception' do
|
313
|
-
expect { query.limit(-1) }
|
314
|
-
.to raise_error ArgumentError, error_message
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
describe 'with zero' do
|
319
|
-
it { expect(query.limit 0).to be_a described_class }
|
320
|
-
|
321
|
-
it { expect(query.limit 0).not_to be query }
|
322
|
-
|
323
|
-
it { expect(query.limit(0).limit).to be 0 }
|
324
|
-
end
|
325
|
-
|
326
|
-
describe 'with a positive integer' do
|
327
|
-
it { expect(query.limit 3).to be_a described_class }
|
328
|
-
|
329
|
-
it { expect(query.limit 3).not_to be query }
|
330
|
-
|
331
|
-
it { expect(query.limit(3).limit).to be 3 }
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
describe '#offset' do
|
336
|
-
it { expect(query).to respond_to(:offset).with(0..1).argument }
|
337
|
-
|
338
|
-
describe 'with no arguments' do
|
339
|
-
it { expect(query.offset).to be nil }
|
340
|
-
end
|
341
|
-
|
342
|
-
describe 'with nil' do
|
343
|
-
let(:error_message) { 'offset must be a non-negative integer' }
|
344
|
-
|
345
|
-
it 'should raise an exception' do
|
346
|
-
expect { query.offset nil }
|
347
|
-
.to raise_error ArgumentError, error_message
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
describe 'with an object' do
|
352
|
-
let(:error_message) { 'offset must be a non-negative integer' }
|
353
|
-
|
354
|
-
it 'should raise an exception' do
|
355
|
-
expect { query.offset Object.new.freeze }
|
356
|
-
.to raise_error ArgumentError, error_message
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
describe 'with a negative integer' do
|
361
|
-
let(:error_message) { 'offset must be a non-negative integer' }
|
362
|
-
|
363
|
-
it 'should raise an exception' do
|
364
|
-
expect { query.offset(-1) }
|
365
|
-
.to raise_error ArgumentError, error_message
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
describe 'with zero' do
|
370
|
-
it { expect(query.offset 0).to be_a described_class }
|
371
|
-
|
372
|
-
it { expect(query.offset 0).not_to be query }
|
373
|
-
|
374
|
-
it { expect(query.offset(0).offset).to be 0 }
|
375
|
-
end
|
376
|
-
|
377
|
-
describe 'with a positive integer' do
|
378
|
-
it { expect(query.offset 3).to be_a described_class }
|
379
|
-
|
380
|
-
it { expect(query.offset 3).not_to be query }
|
381
|
-
|
382
|
-
it { expect(query.offset(3).offset).to be 3 }
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
describe '#order' do
|
387
|
-
let(:default_order) { defined?(super()) ? super() : {} }
|
388
|
-
let(:error_message) do
|
389
|
-
'order must be a list of attribute names and/or a hash of attribute ' \
|
390
|
-
'names with values :asc or :desc'
|
391
|
-
end
|
392
|
-
|
393
|
-
it 'should define the method' do
|
394
|
-
expect(query)
|
395
|
-
.to respond_to(:order)
|
396
|
-
.with(0).arguments
|
397
|
-
.and_unlimited_arguments
|
398
|
-
end
|
399
|
-
|
400
|
-
it { expect(query).to have_aliased_method(:order).as(:order_by) }
|
401
|
-
|
402
|
-
describe 'with no arguments' do
|
403
|
-
it { expect(query.order).to be == default_order }
|
404
|
-
end
|
405
|
-
|
406
|
-
describe 'with a hash with invalid keys' do
|
407
|
-
it 'should raise an exception' do
|
408
|
-
expect { query.order({ nil => :asc }) }
|
409
|
-
.to raise_error ArgumentError, error_message
|
410
|
-
end
|
411
|
-
end
|
412
|
-
|
413
|
-
describe 'with a hash with empty string keys' do
|
414
|
-
it 'should raise an exception' do
|
415
|
-
expect { query.order({ '' => :asc }) }
|
416
|
-
.to raise_error ArgumentError, error_message
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
describe 'with a hash with empty symbol keys' do
|
421
|
-
it 'should raise an exception' do
|
422
|
-
expect { query.order({ '': :asc }) }
|
423
|
-
.to raise_error ArgumentError, error_message
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
describe 'with a hash with nil value' do
|
428
|
-
it 'should raise an exception' do
|
429
|
-
expect { query.order({ title: nil }) }
|
430
|
-
.to raise_error ArgumentError, error_message
|
431
|
-
end
|
432
|
-
end
|
433
|
-
|
434
|
-
describe 'with a hash with object value' do
|
435
|
-
it 'should raise an exception' do
|
436
|
-
expect { query.order({ title: Object.new.freeze }) }
|
437
|
-
.to raise_error ArgumentError, error_message
|
438
|
-
end
|
439
|
-
end
|
440
|
-
|
441
|
-
describe 'with a hash with empty value' do
|
442
|
-
it 'should raise an exception' do
|
443
|
-
expect { query.order({ title: '' }) }
|
444
|
-
.to raise_error ArgumentError, error_message
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
|
-
describe 'with a hash with invalid value' do
|
449
|
-
it 'should raise an exception' do
|
450
|
-
expect { query.order({ title: 'wibbly' }) }
|
451
|
-
.to raise_error ArgumentError, error_message
|
452
|
-
end
|
453
|
-
end
|
454
|
-
|
455
|
-
describe 'with a valid ordering' do
|
456
|
-
let(:expected) do
|
457
|
-
{ title: :asc }
|
458
|
-
end
|
459
|
-
|
460
|
-
it { expect(query.order :title).to be_a described_class }
|
461
|
-
|
462
|
-
it { expect(query.order :title).not_to be query }
|
463
|
-
|
464
|
-
it { expect(query.order(:title).order).to be == expected }
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
describe '#reset' do
|
469
|
-
let(:data) { [] }
|
470
|
-
let(:matching_data) { data }
|
471
|
-
let(:expected_data) do
|
472
|
-
defined?(super()) ? super() : matching_data
|
473
|
-
end
|
474
|
-
|
475
|
-
it { expect(query).to respond_to(:reset).with(0).arguments }
|
476
|
-
|
477
|
-
it { expect(query.reset).to be_a query.class }
|
478
|
-
|
479
|
-
it { expect(query.reset).not_to be query }
|
480
|
-
|
481
|
-
it { expect(query.reset.to_a).to be == query.to_a }
|
482
|
-
|
483
|
-
context 'when the collection data changes' do
|
484
|
-
let(:item) { BOOKS_FIXTURES.first }
|
485
|
-
let(:matching_data) { [item] }
|
486
|
-
|
487
|
-
before(:example) do
|
488
|
-
query.to_a # Cache query results.
|
489
|
-
|
490
|
-
add_item_to_collection(item)
|
491
|
-
end
|
492
|
-
|
493
|
-
it { expect(query.reset.count).to be expected_data.size }
|
494
|
-
|
495
|
-
it { expect(query.reset.to_a).to deep_match expected_data }
|
496
|
-
end
|
497
|
-
|
498
|
-
context 'when the collection has many items' do
|
499
|
-
let(:data) { BOOKS_FIXTURES }
|
500
|
-
|
501
|
-
it { expect(query.reset).to be_a query.class }
|
502
|
-
|
503
|
-
it { expect(query.reset).not_to be query }
|
504
|
-
|
505
|
-
it { expect(query.reset.to_a).to be == query.to_a }
|
506
|
-
|
507
|
-
context 'when the collection data changes' do
|
508
|
-
let(:data) { BOOKS_FIXTURES[0...-1] }
|
509
|
-
let(:item) { BOOKS_FIXTURES.last }
|
510
|
-
let(:matching_data) { [*data, item] }
|
511
|
-
|
512
|
-
before(:example) do
|
513
|
-
query.to_a # Cache query results.
|
514
|
-
|
515
|
-
add_item_to_collection(item)
|
516
|
-
end
|
517
|
-
|
518
|
-
it { expect(query.reset.count).to be expected_data.size }
|
519
|
-
|
520
|
-
it { expect(query.reset.to_a).to deep_match expected_data }
|
521
|
-
end
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
|
-
describe '#to_a' do
|
526
|
-
let(:data) { [] }
|
527
|
-
let(:matching_data) { data }
|
528
|
-
let(:expected_data) do
|
529
|
-
defined?(super()) ? super() : matching_data
|
530
|
-
end
|
531
|
-
|
532
|
-
it { expect(query).to respond_to(:to_a).with(0).arguments }
|
533
|
-
|
534
|
-
it { expect(query.to_a).to deep_match expected_data }
|
535
|
-
|
536
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTRACT,
|
537
|
-
block: lambda {
|
538
|
-
it { expect(scoped_query.to_a).to deep_match expected_data }
|
539
|
-
},
|
540
|
-
operators: operators
|
541
|
-
|
542
|
-
wrap_context 'when the query has composed filters' do
|
543
|
-
it { expect(scoped_query.to_a).to deep_match expected_data }
|
544
|
-
end
|
545
|
-
|
546
|
-
context 'when the collection data changes' do
|
547
|
-
let(:item) { BOOKS_FIXTURES.first }
|
548
|
-
|
549
|
-
before(:example) do
|
550
|
-
query.to_a # Cache query results.
|
551
|
-
|
552
|
-
add_item_to_collection(item)
|
553
|
-
end
|
554
|
-
|
555
|
-
it { expect(query.to_a).to deep_match expected_data }
|
556
|
-
end
|
557
|
-
|
558
|
-
context 'when the collection has many items' do
|
559
|
-
let(:data) { BOOKS_FIXTURES }
|
560
|
-
|
561
|
-
it { expect(query.to_a).to deep_match expected_data }
|
562
|
-
|
563
|
-
include_contract Cuprum::Collections::RSpec::QUERYING_CONTRACT,
|
564
|
-
block: lambda {
|
565
|
-
it { expect(scoped_query.to_a).to deep_match expected_data }
|
566
|
-
},
|
567
|
-
operators: operators
|
568
|
-
|
569
|
-
wrap_context 'when the query has composed filters' do
|
570
|
-
it { expect(scoped_query.to_a).to deep_match expected_data }
|
571
|
-
end
|
572
|
-
|
573
|
-
context 'when the collection data changes' do
|
574
|
-
let(:data) { BOOKS_FIXTURES[0...-1] }
|
575
|
-
let(:item) { BOOKS_FIXTURES.last }
|
576
|
-
|
577
|
-
before(:example) do
|
578
|
-
query.to_a # Cache query results.
|
579
|
-
|
580
|
-
add_item_to_collection(item)
|
581
|
-
end
|
582
|
-
|
583
|
-
it { expect(query.to_a).to deep_match expected_data }
|
584
|
-
end
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
describe '#where' do
|
589
|
-
let(:block) { -> { { title: 'The Caves of Steel' } } }
|
590
|
-
|
591
|
-
it 'should define the method' do
|
592
|
-
expect(query)
|
593
|
-
.to respond_to(:where)
|
594
|
-
.with(0..1).arguments
|
595
|
-
.and_keywords(:strategy)
|
596
|
-
.and_a_block
|
597
|
-
end
|
598
|
-
|
599
|
-
describe 'with no arguments' do
|
600
|
-
it { expect(query.where).to be_a described_class }
|
601
|
-
|
602
|
-
it { expect(query.where).not_to be query }
|
603
|
-
end
|
604
|
-
|
605
|
-
describe 'with a block' do
|
606
|
-
it { expect(query.where(&block)).to be_a described_class }
|
607
|
-
|
608
|
-
it { expect(query.where(&block)).not_to be query }
|
609
|
-
end
|
610
|
-
|
611
|
-
describe 'with a valid strategy' do
|
612
|
-
it 'should return a query instance' do
|
613
|
-
expect(query.where(strategy: :block, &block)).to be_a described_class
|
614
|
-
end
|
615
|
-
|
616
|
-
it { expect(query.where(strategy: :block, &block)).not_to be query }
|
617
|
-
end
|
618
|
-
|
619
|
-
describe 'with parameters that do not match a strategy' do
|
620
|
-
let(:error_class) { Cuprum::Collections::QueryBuilder::ParseError }
|
621
|
-
let(:error_message) { 'unable to parse query with strategy nil' }
|
622
|
-
|
623
|
-
it 'should raise an exception' do
|
624
|
-
expect { query.where(%w[ichi ni san]) }
|
625
|
-
.to raise_error error_class, error_message
|
626
|
-
end
|
627
|
-
end
|
628
|
-
|
629
|
-
describe 'with an invalid strategy' do
|
630
|
-
let(:error_class) { Cuprum::Collections::QueryBuilder::ParseError }
|
631
|
-
let(:error_message) { 'unable to parse query with strategy :random' }
|
632
|
-
|
633
|
-
it 'should raise an exception' do
|
634
|
-
expect { query.where(strategy: :random) }
|
635
|
-
.to raise_error error_class, error_message
|
636
|
-
end
|
637
|
-
end
|
638
|
-
|
639
|
-
describe 'with invalid parameters for a strategy' do
|
640
|
-
let(:error_class) { Cuprum::Collections::QueryBuilder::ParseError }
|
641
|
-
let(:error_message) { 'unable to parse query with strategy :block' }
|
642
|
-
|
643
|
-
it 'should raise an exception' do
|
644
|
-
expect { query.where(strategy: :block) }
|
645
|
-
.to raise_error error_class, error_message
|
646
|
-
end
|
647
|
-
end
|
648
|
-
end
|
649
|
-
end
|
650
|
-
end
|