mongoid 7.0.5 → 7.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,6 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
5
5
 
6
6
  require "mongoid"
7
- require "rspec"
8
7
 
9
8
  # MRI 2.5 and JRuby 9.2 change visibility of Object#pp when 'pp' is required,
10
9
  # which happens when RSpec reports anything. This creates an issue for tests
@@ -36,6 +35,10 @@ else
36
35
  end
37
36
 
38
37
  RSpec.configure do |config|
38
+ config.expect_with(:rspec) do |c|
39
+ c.syntax = [:should, :expect]
40
+ end
41
+
39
42
  if SpecConfig.instance.ci?
40
43
  config.add_formatter(RSpec::Core::Formatters::JsonFormatter, File.join(File.dirname(__FILE__), '../tmp/rspec.json'))
41
44
  end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require "spec_helper"
5
+
6
+ describe Mongoid::Attributes::Dynamic do
7
+ shared_examples_for 'dynamic field' do
8
+ let(:raw_attributes) do
9
+ {attr_name => 'foo bar'}
10
+ end
11
+
12
+ context 'when reading attributes' do
13
+ context 'an unsaved model' do
14
+ it 'can be read' do
15
+ bar = Bar.new(raw_attributes)
16
+ expect(bar.send(attr_name)).to eq('foo bar')
17
+ end
18
+ end
19
+
20
+ context 'saved model' do
21
+ it 'can be read' do
22
+ bar = Bar.new(raw_attributes)
23
+ bar.save!
24
+
25
+ bar = Bar.find(bar.id)
26
+ expect(bar.send(attr_name)).to eq('foo bar')
27
+ end
28
+ end
29
+
30
+ context 'when attribute is not set' do
31
+ it 'cannot be read' do
32
+ bar = Bar.new
33
+ expect do
34
+ bar.send(attr_name)
35
+ end.to raise_error(NoMethodError)
36
+ end
37
+
38
+ context 'reading via read_attribute' do
39
+ it 'returns nil' do
40
+ bar = Bar.new
41
+ expect(bar.read_attribute(:foo)).to be nil
42
+ end
43
+ end
44
+
45
+ context 'reading via []' do
46
+ it 'returns nil' do
47
+ bar = Bar.new
48
+ expect(bar[:foo]).to be nil
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'when writing attributes via constructor' do
55
+ it 'can be written' do
56
+ bar = Bar.new(raw_attributes)
57
+ bar.save!
58
+
59
+ bar = Bar.find(bar.id)
60
+ expect(bar.send(attr_name)).to eq('foo bar')
61
+ end
62
+ end
63
+
64
+ context 'when writing attributes via attributes=' do
65
+ it 'can be written' do
66
+ bar = Bar.new
67
+ bar.attributes = raw_attributes
68
+ bar.save!
69
+
70
+ bar = Bar.find(bar.id)
71
+ expect(bar.send(attr_name)).to eq('foo bar')
72
+ end
73
+ end
74
+
75
+ context 'when writing attributes via write_attribute' do
76
+ it 'can be written' do
77
+ bar = Bar.new
78
+ bar.write_attribute(attr_name, 'foo bar')
79
+ bar.save!
80
+
81
+ bar = Bar.find(bar.id)
82
+ expect(bar.send(attr_name)).to eq('foo bar')
83
+ end
84
+ end
85
+
86
+ context 'when writing attributes via []=' do
87
+ context 'string key' do
88
+ it 'can be written' do
89
+ bar = Bar.new
90
+ bar[attr_name.to_s] = 'foo bar'
91
+ bar.save!
92
+
93
+ bar = Bar.find(bar.id)
94
+ expect(bar.send(attr_name)).to eq('foo bar')
95
+ end
96
+ end
97
+
98
+ context 'symbol key' do
99
+ it 'can be written' do
100
+ bar = Bar.new
101
+ bar[attr_name.to_sym] = 'foo bar'
102
+ bar.save!
103
+
104
+ bar = Bar.find(bar.id)
105
+ expect(bar.send(attr_name)).to eq('foo bar')
106
+ end
107
+ end
108
+ end
109
+
110
+ context 'when writing attributes via #{attribute}=' do
111
+ context 'when attribute is not already set' do
112
+ let(:bar) { Bar.new }
113
+
114
+ it 'cannot be written' do
115
+ expect do
116
+ bar.send("#{attr_name}=", 'foo bar')
117
+ bar.save!
118
+ end.to raise_error(NoMethodError)
119
+ end
120
+ end
121
+
122
+ context 'when attribute is already set' do
123
+ let(:bar) { Bar.new(attr_name => 'foo bar') }
124
+
125
+ it 'can be written' do
126
+ bar.send("#{attr_name}=", 'new foo bar')
127
+ bar.save!
128
+
129
+ _bar = Bar.find(bar.id)
130
+ expect(_bar.send(attr_name)).to eq('new foo bar')
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ context 'when attribute name is alphanumeric' do
137
+ let(:attr_name) { 'foo' }
138
+
139
+ it_behaves_like 'dynamic field'
140
+ end
141
+
142
+ context 'when attribute name contains spaces' do
143
+ let(:attr_name) { 'hello world' }
144
+
145
+ it_behaves_like 'dynamic field'
146
+ end
147
+
148
+ context 'when attribute name contains special characters' do
149
+ let(:attr_name) { 'hello%world' }
150
+
151
+ it_behaves_like 'dynamic field'
152
+ end
153
+ end
@@ -1346,10 +1346,16 @@ describe Mongoid::Attributes do
1346
1346
  context "when attribute is a Hash" do
1347
1347
  let(:person) { Person.new map: { somekey: "somevalue" } }
1348
1348
 
1349
- it "raises an error when try to set an invalid value" do
1350
- expect {
1349
+ it "raises an error when trying to set a value of invalid type - array" do
1350
+ expect do
1351
1351
  person.map = []
1352
- }.to raise_error(Mongoid::Errors::InvalidValue)
1352
+ end.to raise_error(Mongoid::Errors::InvalidValue, /Value of type Array cannot be written to a field of type Hash/)
1353
+ end
1354
+
1355
+ it "raises an error when trying to set a value of invalid type - boolean" do
1356
+ expect do
1357
+ person.map = false
1358
+ end.to raise_error(Mongoid::Errors::InvalidValue, /Value of type FalseClass cannot be written to a field of type Hash/)
1353
1359
  end
1354
1360
 
1355
1361
  it "can set a Hash value" do
@@ -1364,10 +1370,16 @@ describe Mongoid::Attributes do
1364
1370
  expect(person.aliases).to eq([ :alias_1 ])
1365
1371
  end
1366
1372
 
1367
- it "raises an error when try to set an invalid value" do
1368
- expect {
1373
+ it "raises an error when trying to set a value of invalid type - hash" do
1374
+ expect do
1369
1375
  person.aliases = {}
1370
- }.to raise_error(Mongoid::Errors::InvalidValue)
1376
+ end.to raise_error(Mongoid::Errors::InvalidValue, /Value of type Hash cannot be written to a field of type Array/)
1377
+ end
1378
+
1379
+ it "raises an error when trying to set a value of invalid type - boolean" do
1380
+ expect do
1381
+ person.aliases = false
1382
+ end.to raise_error(Mongoid::Errors::InvalidValue, /Value of type FalseClass cannot be written to a field of type Array/)
1371
1383
  end
1372
1384
  end
1373
1385
 
@@ -1422,7 +1434,7 @@ describe Mongoid::Attributes do
1422
1434
  end
1423
1435
 
1424
1436
  describe "#typed_attributes" do
1425
-
1437
+
1426
1438
  let(:date_time) do
1427
1439
  DateTime.current
1428
1440
  end
@@ -0,0 +1,762 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require "spec_helper"
5
+
6
+ describe Mongoid::Criteria::Queryable::Selectable do
7
+
8
+ let(:query) do
9
+ Mongoid::Query.new("id" => "_id")
10
+ end
11
+
12
+ describe "#and" do
13
+
14
+ context "when provided no criterion" do
15
+
16
+ let(:selection) do
17
+ query.and
18
+ end
19
+
20
+ it "does not add any criterion" do
21
+ expect(selection.selector).to eq({})
22
+ end
23
+
24
+ it "returns the query" do
25
+ expect(selection).to eq(query)
26
+ end
27
+
28
+ it "returns a cloned query" do
29
+ expect(selection).to_not equal(query)
30
+ end
31
+ end
32
+
33
+ context "when provided nil" do
34
+
35
+ let(:selection) do
36
+ query.and(nil)
37
+ end
38
+
39
+ it "does not add any criterion" do
40
+ expect(selection.selector).to eq({})
41
+ end
42
+
43
+ it "returns the query" do
44
+ expect(selection).to eq(query)
45
+ end
46
+
47
+ it "returns a cloned query" do
48
+ expect(selection).to_not equal(query)
49
+ end
50
+ end
51
+
52
+ context "when provided a single criterion" do
53
+
54
+ let(:selection) do
55
+ query.and(field: [ 1, 2 ])
56
+ end
57
+
58
+ it "adds the $and selector" do
59
+ expect(selection.selector).to eq({
60
+ "$and" => [{ "field" => [ 1, 2 ] }]
61
+ })
62
+ end
63
+
64
+ it "returns a cloned query" do
65
+ expect(selection).to_not equal(query)
66
+ end
67
+ end
68
+
69
+ context "when provided a nested criterion" do
70
+
71
+ let(:selection) do
72
+ query.and(:test.elem_match => { :field.in => [ 1, 2 ] })
73
+ end
74
+
75
+ it "adds the $and selector" do
76
+ expect(selection.selector).to eq({
77
+ "$and" => [{ "test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}}]
78
+ })
79
+ end
80
+
81
+ it "returns a cloned query" do
82
+ expect(selection).to_not equal(query)
83
+ end
84
+ end
85
+
86
+ context "when provided multiple criterion" do
87
+
88
+ context "when the criterion is already included" do
89
+
90
+ let(:selection) do
91
+ query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
92
+ end
93
+
94
+ it "does not duplicate the $and selector" do
95
+ expect(selection.selector).to eq({
96
+ "$and" => [
97
+ { "first" => [ 1, 2 ] }
98
+ ]
99
+ })
100
+ end
101
+
102
+ it "returns a cloned query" do
103
+ expect(selection).to_not equal(query)
104
+ end
105
+ end
106
+
107
+ context "when the criterion are for different fields" do
108
+
109
+ let(:selection) do
110
+ query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
111
+ end
112
+
113
+ it "adds the $and selector" do
114
+ expect(selection.selector).to eq({
115
+ "$and" => [
116
+ { "first" => [ 1, 2 ] },
117
+ { "second" => [ 3, 4 ] }
118
+ ]
119
+ })
120
+ end
121
+
122
+ it "returns a cloned query" do
123
+ expect(selection).to_not equal(query)
124
+ end
125
+ end
126
+
127
+ context "when the criterion are on the same field" do
128
+
129
+ let(:selection) do
130
+ query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
131
+ end
132
+
133
+ it "appends both $and expressions" do
134
+ expect(selection.selector).to eq({
135
+ "$and" => [
136
+ { "first" => [ 1, 2 ] },
137
+ { "first" => [ 3, 4 ] }
138
+ ]
139
+ })
140
+ end
141
+
142
+ it "returns a cloned query" do
143
+ expect(selection).to_not equal(query)
144
+ end
145
+ end
146
+ end
147
+
148
+ context "when chaining the criterion" do
149
+
150
+ context "when the criterion are for different fields" do
151
+
152
+ let(:selection) do
153
+ query.and(first: [ 1, 2 ]).and(second: [ 3, 4 ])
154
+ end
155
+
156
+ it "adds the $and selectors" do
157
+ expect(selection.selector).to eq({
158
+ "$and" => [
159
+ { "first" => [ 1, 2 ] },
160
+ { "second" => [ 3, 4 ] }
161
+ ]
162
+ })
163
+ end
164
+
165
+ it "returns a cloned query" do
166
+ expect(selection).to_not equal(query)
167
+ end
168
+ end
169
+
170
+ context "when the criterion are on the same field" do
171
+
172
+ let(:selection) do
173
+ query.and(first: [ 1, 2 ]).and(first: [ 3, 4 ])
174
+ end
175
+
176
+ it "appends both $and expressions" do
177
+ expect(selection.selector).to eq({
178
+ "$and" => [
179
+ { "first" => [ 1, 2 ] },
180
+ { "first" => [ 3, 4 ] }
181
+ ]
182
+ })
183
+ end
184
+
185
+ it "returns a cloned query" do
186
+ expect(selection).to_not equal(query)
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ describe "#or" do
193
+
194
+ context "when provided no criterion" do
195
+
196
+ let(:selection) do
197
+ query.or
198
+ end
199
+
200
+ it "does not add any criterion" do
201
+ expect(selection.selector).to eq({})
202
+ end
203
+
204
+ it "returns the query" do
205
+ expect(selection).to eq(query)
206
+ end
207
+
208
+ it "returns a cloned query" do
209
+ expect(selection).to_not equal(query)
210
+ end
211
+ end
212
+
213
+ context "when provided nil" do
214
+
215
+ let(:selection) do
216
+ query.or(nil)
217
+ end
218
+
219
+ it "does not add any criterion" do
220
+ expect(selection.selector).to eq({})
221
+ end
222
+
223
+ it "returns the query" do
224
+ expect(selection).to eq(query)
225
+ end
226
+
227
+ it "returns a cloned query" do
228
+ expect(selection).to_not equal(query)
229
+ end
230
+ end
231
+
232
+ context "when provided a single criterion" do
233
+
234
+ let(:selection) do
235
+ query.or(field: [ 1, 2 ])
236
+ end
237
+
238
+ it "adds the $or selector" do
239
+ expect(selection.selector).to eq({
240
+ "$or" => [{ "field" => [ 1, 2 ] }]
241
+ })
242
+ end
243
+
244
+ it "returns a cloned query" do
245
+ expect(selection).to_not equal(query)
246
+ end
247
+ end
248
+
249
+ context "when provided multiple criterion" do
250
+
251
+ context "when the criterion are for different fields" do
252
+
253
+ let(:selection) do
254
+ query.or({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
255
+ end
256
+
257
+ it "adds the $or selector" do
258
+ expect(selection.selector).to eq({
259
+ "$or" => [
260
+ { "first" => [ 1, 2 ] },
261
+ { "second" => [ 3, 4 ] }
262
+ ]
263
+ })
264
+ end
265
+
266
+ it "returns a cloned query" do
267
+ expect(selection).to_not equal(query)
268
+ end
269
+ end
270
+
271
+ context "when a criterion has a selectable key" do
272
+
273
+ let(:selection) do
274
+ query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
275
+ end
276
+
277
+ it "adds the $or selector" do
278
+ expect(selection.selector).to eq({
279
+ "$or" => [
280
+ { "first" => [ 1, 2 ] },
281
+ { "second" => { "$gt" => 3 }}
282
+ ]
283
+ })
284
+ end
285
+
286
+ it "returns a cloned query" do
287
+ expect(selection).to_not equal(query)
288
+ end
289
+ end
290
+
291
+ context "when the criterion has an aliased field" do
292
+
293
+ let(:selection) do
294
+ query.or({ id: 1 })
295
+ end
296
+
297
+ it "adds the $or selector and aliases the field" do
298
+ expect(selection.selector).to eq({
299
+ "$or" => [ { "_id" => 1 } ]
300
+ })
301
+ end
302
+
303
+ it "returns a cloned query" do
304
+ expect(selection).to_not equal(query)
305
+ end
306
+ end
307
+
308
+ context "when a criterion is wrapped in an array" do
309
+
310
+ let(:selection) do
311
+ query.or([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
312
+ end
313
+
314
+ it "adds the $or selector" do
315
+ expect(selection.selector).to eq({
316
+ "$or" => [
317
+ { "first" => [ 1, 2 ] },
318
+ { "second" => { "$gt" => 3 }}
319
+ ]
320
+ })
321
+ end
322
+
323
+ it "returns a cloned query" do
324
+ expect(selection).to_not equal(query)
325
+ end
326
+ end
327
+
328
+ context "when the criterion are on the same field" do
329
+
330
+ let(:selection) do
331
+ query.or({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
332
+ end
333
+
334
+ it "appends both $or expressions" do
335
+ expect(selection.selector).to eq({
336
+ "$or" => [
337
+ { "first" => [ 1, 2 ] },
338
+ { "first" => [ 3, 4 ] }
339
+ ]
340
+ })
341
+ end
342
+
343
+ it "returns a cloned query" do
344
+ expect(selection).to_not equal(query)
345
+ end
346
+ end
347
+ end
348
+
349
+ context "when chaining the criterion" do
350
+
351
+ context "when the criterion are for different fields" do
352
+
353
+ let(:selection) do
354
+ query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
355
+ end
356
+
357
+ it "adds the $or selectors" do
358
+ expect(selection.selector).to eq({
359
+ "$or" => [
360
+ { "first" => [ 1, 2 ] },
361
+ { "second" => [ 3, 4 ] }
362
+ ]
363
+ })
364
+ end
365
+
366
+ it "returns a cloned query" do
367
+ expect(selection).to_not equal(query)
368
+ end
369
+ end
370
+
371
+ context "when the criterion are on the same field" do
372
+
373
+ let(:selection) do
374
+ query.or(first: [ 1, 2 ]).or(first: [ 3, 4 ])
375
+ end
376
+
377
+ it "appends both $or expressions" do
378
+ expect(selection.selector).to eq({
379
+ "$or" => [
380
+ { "first" => [ 1, 2 ] },
381
+ { "first" => [ 3, 4 ] }
382
+ ]
383
+ })
384
+ end
385
+
386
+ it "returns a cloned query" do
387
+ expect(selection).to_not equal(query)
388
+ end
389
+ end
390
+ end
391
+ end
392
+
393
+ describe "#nor" do
394
+
395
+ context "when provided no criterion" do
396
+
397
+ let(:selection) do
398
+ query.nor
399
+ end
400
+
401
+ it "does not add any criterion" do
402
+ expect(selection.selector).to eq({})
403
+ end
404
+
405
+ it "returns the query" do
406
+ expect(selection).to eq(query)
407
+ end
408
+
409
+ it "returns a cloned query" do
410
+ expect(selection).to_not equal(query)
411
+ end
412
+ end
413
+
414
+ context "when provided nil" do
415
+
416
+ let(:selection) do
417
+ query.nor(nil)
418
+ end
419
+
420
+ it "does not add any criterion" do
421
+ expect(selection.selector).to eq({})
422
+ end
423
+
424
+ it "returns the query" do
425
+ expect(selection).to eq(query)
426
+ end
427
+
428
+ it "returns a cloned query" do
429
+ expect(selection).to_not equal(query)
430
+ end
431
+ end
432
+
433
+ context "when provided a single criterion" do
434
+
435
+ let(:selection) do
436
+ query.nor(field: [ 1, 2 ])
437
+ end
438
+
439
+ it "adds the $nor selector" do
440
+ expect(selection.selector).to eq({
441
+ "$nor" => [{"field" => [ 1, 2 ] }]
442
+ })
443
+ end
444
+
445
+ it "returns a cloned query" do
446
+ expect(selection).to_not equal(query)
447
+ end
448
+ end
449
+
450
+ context "when provided multiple criterion" do
451
+
452
+ context "when the criterion are fnor different fields" do
453
+
454
+ let(:selection) do
455
+ query.nor({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
456
+ end
457
+
458
+ it "adds the $nor selector" do
459
+ expect(selection.selector).to eq({
460
+ "$nor" => [
461
+ { "first" => [ 1, 2 ] },
462
+ { "second" => [ 3, 4 ] }
463
+ ]
464
+ })
465
+ end
466
+
467
+ it "returns a cloned query" do
468
+ expect(selection).to_not equal(query)
469
+ end
470
+ end
471
+
472
+ context "when the criterion are on the same field" do
473
+
474
+ let(:selection) do
475
+ query.nor({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
476
+ end
477
+
478
+ it "appends both $nor expressions" do
479
+ expect(selection.selector).to eq({
480
+ "$nor" => [
481
+ { "first" => [ 1, 2 ] },
482
+ { "first" => [ 3, 4 ] }
483
+ ]
484
+ })
485
+ end
486
+
487
+ it "returns a cloned query" do
488
+ expect(selection).to_not equal(query)
489
+ end
490
+ end
491
+ end
492
+
493
+ context "when chaining the criterion" do
494
+
495
+ context "when the criterion are fnor different fields" do
496
+
497
+ let(:selection) do
498
+ query.nor(first: [ 1, 2 ]).nor(second: [ 3, 4 ])
499
+ end
500
+
501
+ it "adds the $nor selectors" do
502
+ expect(selection.selector).to eq({
503
+ "$nor" => [
504
+ { "first" => [ 1, 2 ] },
505
+ { "second" => [ 3, 4 ] }
506
+ ]
507
+ })
508
+ end
509
+
510
+ it "returns a cloned query" do
511
+ expect(selection).to_not equal(query)
512
+ end
513
+ end
514
+
515
+ context "when the criterion are on the same field" do
516
+
517
+ let(:selection) do
518
+ query.nor(first: [ 1, 2 ]).nor(first: [ 3, 4 ])
519
+ end
520
+
521
+ it "appends both $nor expressions" do
522
+ expect(selection.selector).to eq({
523
+ "$nor" => [
524
+ { "first" => [ 1, 2 ] },
525
+ { "first" => [ 3, 4 ] }
526
+ ]
527
+ })
528
+ end
529
+
530
+ it "returns a cloned query" do
531
+ expect(selection).to_not equal(query)
532
+ end
533
+ end
534
+ end
535
+ end
536
+
537
+ describe "#not" do
538
+
539
+ context "when provided no criterion" do
540
+
541
+ let(:selection) do
542
+ query.not
543
+ end
544
+
545
+ it "does not add any criterion" do
546
+ expect(selection.selector).to eq({})
547
+ end
548
+
549
+ it "returns the query" do
550
+ expect(selection).to eq(query)
551
+ end
552
+
553
+ it "returns a cloned query" do
554
+ expect(selection).not_to equal(query)
555
+ end
556
+
557
+ it 'does not mutate receiver' do
558
+ expect(query.negating).to be nil
559
+
560
+ selection
561
+ expect(query.negating).to be nil
562
+ end
563
+
564
+ context "when the following criteria is a query method" do
565
+
566
+ let(:selection) do
567
+ query.not.all(field: [ 1, 2 ])
568
+ end
569
+
570
+ it "negates the all selection" do
571
+ expect(selection.selector).to eq(
572
+ { "field" => { "$not" => { "$all" => [ 1, 2 ] }}}
573
+ )
574
+ end
575
+
576
+ it "returns a cloned query" do
577
+ expect(selection).to_not equal(query)
578
+ end
579
+
580
+ it "removes the negation on the clone" do
581
+ expect(selection).to_not be_negating
582
+ end
583
+ end
584
+
585
+ context "when the following criteria is a gt method" do
586
+
587
+ let(:selection) do
588
+ query.not.gt(age: 50)
589
+ end
590
+
591
+ it "negates the gt selection" do
592
+ expect(selection.selector).to eq(
593
+ { "age" => { "$not" => { "$gt" => 50 }}}
594
+ )
595
+ end
596
+
597
+ it "returns a coned query" do
598
+ expect(selection).to_not eq(query)
599
+ end
600
+
601
+ it "removes the negation on the clone" do
602
+ expect(selection).to_not be_negating
603
+ end
604
+ end
605
+
606
+ context "when the following criteria is a where" do
607
+
608
+ let(:selection) do
609
+ query.not.where(field: 1, :other.in => [ 1, 2 ])
610
+ end
611
+
612
+ it "negates the selection with an operator" do
613
+ expect(selection.selector).to eq(
614
+ { "field" => { "$ne" => 1 }, "other" => { "$not" => { "$in" => [ 1, 2 ] }}}
615
+ )
616
+ end
617
+
618
+ it "returns a cloned query" do
619
+ expect(selection).to_not equal(query)
620
+ end
621
+
622
+ it "removes the negation on the clone" do
623
+ expect(selection).to_not be_negating
624
+ end
625
+ end
626
+
627
+ context "when the following criteria is a where with a regexp" do
628
+
629
+ let(:selection) do
630
+ query.not.where(field: 1, other: /test/)
631
+ end
632
+
633
+ it "negates the selection with an operator" do
634
+ expect(selection.selector).to eq(
635
+ { "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
636
+ )
637
+ end
638
+
639
+ it "returns a cloned query" do
640
+ expect(selection).to_not equal(query)
641
+ end
642
+
643
+ it "removes the negation on the clone" do
644
+ expect(selection).to_not be_negating
645
+ end
646
+
647
+ end
648
+ end
649
+
650
+ context "when provided nil" do
651
+
652
+ let(:selection) do
653
+ query.not(nil)
654
+ end
655
+
656
+ it "does not add any criterion" do
657
+ expect(selection.selector).to eq({})
658
+ end
659
+
660
+ it "returns the query" do
661
+ expect(selection).to eq(query)
662
+ end
663
+
664
+ it "returns a cloned query" do
665
+ expect(selection).to_not equal(query)
666
+ end
667
+ end
668
+
669
+ context "when provided a single criterion" do
670
+
671
+ let(:selection) do
672
+ query.not(field: /test/)
673
+ end
674
+
675
+ it "adds the $not selector" do
676
+ expect(selection.selector).to eq({
677
+ "field" => { "$not" => /test/ }
678
+ })
679
+ end
680
+
681
+ it "returns a cloned query" do
682
+ expect(selection).to_not equal(query)
683
+ end
684
+ end
685
+
686
+ context "when provided multiple criterion" do
687
+
688
+ context "when the criterion are for different fields" do
689
+
690
+ let(:selection) do
691
+ query.not(first: /1/, second: /2/)
692
+ end
693
+
694
+ it "adds the $not selectors" do
695
+ expect(selection.selector).to eq({
696
+ "first" => { "$not" => /1/ },
697
+ "second" => { "$not" => /2/ }
698
+ })
699
+ end
700
+
701
+ it "returns a cloned query" do
702
+ expect(selection).to_not equal(query)
703
+ end
704
+ end
705
+ end
706
+
707
+ context "when chaining the criterion" do
708
+
709
+ context "when the criterion are for different fields" do
710
+
711
+ let(:selection) do
712
+ query.not(first: /1/).not(second: /2/)
713
+ end
714
+
715
+ it "adds the $not selectors" do
716
+ expect(selection.selector).to eq({
717
+ "first" => { "$not" => /1/ },
718
+ "second" => { "$not" => /2/ }
719
+ })
720
+ end
721
+
722
+ it "returns a cloned query" do
723
+ expect(selection).to_not equal(query)
724
+ end
725
+ end
726
+
727
+ context "when the criterion are on the same field" do
728
+
729
+ let(:selection) do
730
+ query.not(first: /1/).not(first: /2/)
731
+ end
732
+
733
+ it "overwrites the first $not selector" do
734
+ expect(selection.selector).to eq({
735
+ "first" => { "$not" => /2/ }
736
+ })
737
+ end
738
+
739
+ it "returns a cloned query" do
740
+ expect(selection).to_not equal(query)
741
+ end
742
+ end
743
+
744
+ context "when the criterion are a double negative" do
745
+
746
+ let(:selection) do
747
+ query.not.where(:first.not => /1/)
748
+ end
749
+
750
+ it "does not double the $not selector" do
751
+ expect(selection.selector).to eq({
752
+ "first" => { "$not" => /1/ }
753
+ })
754
+ end
755
+
756
+ it "returns a cloned query" do
757
+ expect(selection).to_not equal(query)
758
+ end
759
+ end
760
+ end
761
+ end
762
+ end