mongoid 7.0.5 → 7.0.6

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.
@@ -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