must_be 1.0.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.
@@ -0,0 +1,952 @@
1
+ require 'spec_helper'
2
+
3
+ describe MustBe do
4
+ include MustBeExampleHelper
5
+
6
+ describe ContainerNote do
7
+ describe '#to_s' do
8
+ context "when original_note has no assertion" do
9
+ it "should just use original_note's message" do
10
+ note = ContainerNote.new(Note.new("message"))
11
+ note.to_s.should == Note.new("message").to_s
12
+ end
13
+ end
14
+ end
15
+
16
+ describe '#backtrace' do
17
+ context "when #must_only_ever_contain has been called" do
18
+ subject do
19
+ note = ContainerNote.new(Note.new("nothing"),
20
+ [].must_only_ever_contain)
21
+ note.set_backtrace([])
22
+ note
23
+ end
24
+
25
+ its(:backtrace) { should include("=== caused by container ===")}
26
+ end
27
+
28
+ context "when #must_only_ever_contain has not been called" do
29
+ subject do
30
+ note = ContainerNote.new(Note.new("nothing"), [])
31
+ note.set_backtrace([])
32
+ note
33
+ end
34
+
35
+ its(:backtrace) { should_not include("=== caused by container ===")}
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '#must_only_contain' do
41
+ context "when called on an array" do
42
+ subject { [11, :sin, 'cos'] }
43
+
44
+ it "should not notify if every member matches one of the cases" do
45
+ subject.must_only_contain(Symbol, Numeric, String).should == subject
46
+ should_not notify
47
+ end
48
+
49
+ it "should notify if any member matches none of the cases" do
50
+ subject.must_only_contain(Symbol, Numeric).should == subject
51
+ should notify("must_only_contain: \"cos\".must_be(Symbol, Numeric),"\
52
+ " but matches String in container [11, :sin, \"cos\"]")
53
+ end
54
+
55
+ context "when there are no cases" do
56
+ it "should notify if any member is false or nil" do
57
+ [false, nil].must_only_contain
58
+ should notify
59
+ end
60
+
61
+ it "should not notify if every member is neither false nor nil" do
62
+ [0, [], ""].must_only_contain
63
+ should_not notify
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "when called on a hash" do
69
+ subject { {:key => :value, :another => 'thing', 12 => 43} }
70
+
71
+ describe "note message" do
72
+ it "should include \"does not match\"" do
73
+ subject = {:key => :value}
74
+ subject.must_only_contain(Symbol => [String, Numeric])
75
+ should notify("must_only_contain: pair {:key=>:value} does"\
76
+ " not match [{Symbol=>[String, Numeric]}] in container"\
77
+ " {:key=>:value}")
78
+ end
79
+ end
80
+
81
+ context "when called with no arguments" do
82
+ it "should not notifiy if every key and value is non-nil" do
83
+ subject = {:key => :value}
84
+ subject.must_only_contain
85
+ should_not notify
86
+ end
87
+
88
+ it "should notify if any pair contains a nil key" do
89
+ subject = {nil => :value}
90
+ subject.must_only_contain
91
+ should notify
92
+ end
93
+
94
+ it "should notify if any pair contains a nil value" do
95
+ subject = {:key => nil}
96
+ subject.must_only_contain
97
+ should notify
98
+ end
99
+ end
100
+
101
+ context "when called with a single hash" do
102
+ it "should not notify if every pair matches one of the cases" do
103
+ subject.must_only_contain(Symbol => [Symbol, String],
104
+ Numeric => Numeric).should == subject
105
+ should_not notify
106
+ end
107
+
108
+ it "should notify if any pair matches none of the cases" do
109
+ subject.must_only_contain(Symbol => Symbol, Symbol => String,
110
+ String => Numeric).should == subject
111
+ should notify
112
+ end
113
+ end
114
+
115
+ context "when called with multiple hashes" do
116
+ it "should not notify if every pair matches one of the cases" do
117
+ subject.must_only_contain({Symbol => Symbol}, {Symbol => String},
118
+ {Numeric => Numeric}).should == subject
119
+ should_not notify
120
+ end
121
+
122
+ it "should notify if any pair matches none of the cases" do
123
+ subject.must_only_contain({Symbol => Symbol}, {Symbol => String},
124
+ {String => Numeric}).should == subject
125
+ should notify
126
+ end
127
+ end
128
+
129
+ context "when called with array keys and values" do
130
+ it "should not notify if every pair matches one of the cases" do
131
+ subject.must_only_contain([Symbol, Numeric] => [Symbol, String,
132
+ Numeric]).should == subject
133
+ should_not notify
134
+ end
135
+
136
+ it "should notify if any pair does not match any of the cases" do
137
+ subject.must_only_contain([Symbol, Numeric] => [Symbol,
138
+ Numeric]).should == subject
139
+ should notify
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ describe '#must_not_contain' do
146
+ context "when called on an array" do
147
+ subject { [11, :sin, 'cos'] }
148
+
149
+ it "should not notify if no member matches any of the cases" do
150
+ subject.must_not_contain(Float, Range).should == subject
151
+ should_not notify
152
+ end
153
+
154
+ it "should notify if any member matches one of the cases" do
155
+ subject.must_not_contain(Range, Numeric).should == subject
156
+ should notify("must_not_contain: 11.must_not_be(Range, Numeric),"\
157
+ " but matches Fixnum in container [11, :sin, \"cos\"]")
158
+ end
159
+
160
+ context "when there are no cases" do
161
+ it "should not notify if every member is false or nil" do
162
+ [false, nil].must_not_contain
163
+ should_not notify
164
+ end
165
+
166
+ it "should notify if any member is neither false nor nil" do
167
+ [0, [], ""].must_not_contain
168
+ should notify
169
+ end
170
+ end
171
+ end
172
+
173
+ context "when called on a hash" do
174
+ subject { {:key => :value, :another => 'thing', 12 => 43} }
175
+
176
+ context "when called with no arguments" do
177
+ it "should not notifiy if every key and value"\
178
+ " is false or nil" do
179
+ subject = {nil => false, false => nil}
180
+ subject.must_not_contain
181
+ should_not notify
182
+ end
183
+
184
+ it "should notify if any key or value is conitionally true" do
185
+ subject = {nil => :value}
186
+ subject.must_not_contain
187
+ should notify
188
+ end
189
+ end
190
+
191
+ describe "note message" do
192
+ it "should include \"does match\"" do
193
+ subject = {:key => :value}
194
+ subject.must_not_contain(Symbol => [String, Symbol])
195
+ should notify("must_not_contain: pair {:key=>:value} matches"\
196
+ " [{Symbol=>[String, Symbol]}] in container {:key=>:value}")
197
+ end
198
+ end
199
+
200
+ context "when called with a single hash" do
201
+ it "should notify if any pair matches one of the cases" do
202
+ subject.must_not_contain(Symbol => [Symbol, String],
203
+ Numeric => Numeric).should == subject
204
+ should notify
205
+ end
206
+
207
+ it "should_not notify if no pair matches any of the cases" do
208
+ subject.must_not_contain(Symbol => Numeric, String => String,
209
+ Range => Numeric).should == subject
210
+ should_not notify
211
+ end
212
+ end
213
+
214
+ context "when called with multiple hashes" do
215
+ it "should not notify if no pair matches any of the cases" do
216
+ subject.must_not_contain({Symbol => Numeric}, {String => String},
217
+ {String => Numeric}).should == subject
218
+ should_not notify
219
+ end
220
+
221
+ it "should notify if any pair matches any of the cases" do
222
+ subject.must_not_contain({Symbol => Symbol}, {Symbol => String},
223
+ {String => Numeric}).should == subject
224
+ should notify
225
+ end
226
+ end
227
+
228
+ context "when called with array keys and values" do
229
+ it "should not notify if no pair matches any of the cases" do
230
+ subject.must_not_contain([Range, Numeric] => [Symbol, String,
231
+ Float]).should == subject
232
+ should_not notify
233
+ end
234
+
235
+ it "should notify if any pair matches one of the cases" do
236
+ subject.must_not_contain([Symbol, Numeric] => [Symbol,
237
+ Numeric]).should == subject
238
+ should notify
239
+ end
240
+ end
241
+ end
242
+ end
243
+
244
+ shared_examples_for "custom MustOnlyEverContain" do
245
+ class Box
246
+ include Enumerable
247
+
248
+ attr_accessor :contents
249
+
250
+ def initialize(contents = nil)
251
+ self.contents = contents
252
+ end
253
+
254
+ def each_called?
255
+ @each_called
256
+ end
257
+
258
+ def each
259
+ @each_called = true
260
+ yield(contents) unless contents.nil?
261
+ end
262
+
263
+ def empty!
264
+ self.contents = nil
265
+ end
266
+ end
267
+
268
+ subject { Box.new(:contents) }
269
+
270
+ def self.register_before_and_unregister_after
271
+ before do
272
+ MustOnlyEverContain.register(Box) do
273
+ def self.must_only_contain_check(object, cases, negate = false)
274
+ if negate
275
+ object.contents.must_not_be(*cases)
276
+ else
277
+ object.contents.must_be(*cases)
278
+ end
279
+ end
280
+
281
+ def contents=(contents)
282
+ must_check_member(contents)
283
+ super
284
+ end
285
+
286
+ must_check_contents_after :empty!
287
+ end
288
+ end
289
+
290
+ after do
291
+ MustOnlyEverContain.unregister(Box)
292
+ end
293
+ end
294
+ end
295
+
296
+ describe '#must_only_ever_contain' do
297
+ context "when called on an array" do
298
+ subject { [1, 2, 3, 4] }
299
+
300
+ before do
301
+ subject.must_only_ever_contain
302
+ end
303
+
304
+ it "should notify if initially contains a non-matching member" do
305
+ array = [:oops]
306
+ array.must_only_ever_contain(String)
307
+ should notify("must_only_ever_contain: :oops.must_be(String), but"\
308
+ " matches Symbol in container [:oops]")
309
+ end
310
+
311
+ context "after disabling" do
312
+ before do
313
+ @enabled_array = [].must_only_ever_contain(Fixnum)
314
+ end
315
+
316
+ before_disable_after_enable
317
+
318
+ context "when #must_only_ever_contain was called while still"\
319
+ " enabled" do
320
+ it "should not notify" do
321
+ @enabled_array << 3.2
322
+ should_not notify
323
+ end
324
+
325
+ it "should continue to have singleton methods" do
326
+ @enabled_array.singleton_methods.should_not be_empty
327
+ end
328
+
329
+ context "after being re-enabled" do
330
+ before do
331
+ MustBe.enable
332
+ end
333
+
334
+ it "should notify again" do
335
+ @enabled_array << 3.2
336
+ should notify(/must_only_ever_contain: Array#<<\(3.2\)/)
337
+ end
338
+ end
339
+ end
340
+
341
+ context "when #must_only_ever_contain is called" do
342
+ before do
343
+ @disabled_array = [].must_only_ever_contain(Fixnum)
344
+ end
345
+
346
+ it "should not notify" do
347
+ @disabled_array << 3.2
348
+ should_not notify
349
+ end
350
+
351
+ it "should not have singleton methods" do
352
+ @disabled_array.singleton_methods.should be_empty
353
+ end
354
+
355
+ context "after being re-enabled" do
356
+ before do
357
+ MustBe.enable
358
+ end
359
+
360
+ it "should still not notify" do
361
+ @disabled_array << 3.2
362
+ should_not notify
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ describe '#<<' do
369
+ it "should not notify if obj is non-nil" do
370
+ subject << 5
371
+ should_not notify
372
+ end
373
+
374
+ it "should notify if obj is nil" do
375
+ subject << nil
376
+ should notify("must_only_ever_contain: Array#<<(nil):"\
377
+ " nil.must_be, but matches NilClass in container"\
378
+ " [1, 2, 3, 4, nil]")
379
+ end
380
+ end
381
+
382
+ describe '#[]=' do
383
+ context "when called with index" do
384
+ it "should not notify if obj is non-nil" do
385
+ subject[2] = 5
386
+ should_not notify
387
+ end
388
+
389
+ it "should notify if obj is nil" do
390
+ subject[2] = nil
391
+ should notify
392
+ end
393
+ end
394
+
395
+ context "when called with start and length" do
396
+ it "should not notify if obj is non-nil" do
397
+ subject[2, 2] = 5
398
+ should_not notify
399
+ end
400
+
401
+ it "should not notify if obj is nil" do
402
+ subject[2, 2] = nil
403
+ should_not notify
404
+ end
405
+
406
+ it "should not notify if obj is compact array" do
407
+ subject[2, 2] = [8, 9, 0]
408
+ end
409
+
410
+ it "should notify if obj is array containing nil" do
411
+ subject[2, 2] = [8, nil, 0]
412
+ should notify("must_only_ever_contain:"\
413
+ " Array#[]=(2, 2, [8, nil, 0]): nil.must_be,"\
414
+ " but matches NilClass in"\
415
+ " container [1, 2, 8, nil, 0]")
416
+ end
417
+ end
418
+
419
+ context "when called with range" do
420
+ it "should not notify if obj is non-nil obj" do
421
+ subject[2..4] = 5
422
+ should_not notify
423
+ end
424
+
425
+ it "should not notify if obj is nil" do
426
+ subject[2..4] = nil
427
+ should_not notify
428
+ end
429
+
430
+ it "should not notify if obj is compact array" do
431
+ subject[2..4] = [8, 9, 0]
432
+ end
433
+
434
+ it "should notify if obj is array containing nil" do
435
+ subject[2..4] = [8, nil, 0]
436
+ should notify
437
+ end
438
+ end
439
+ end
440
+
441
+ describe '#collect!' do
442
+ it "should not notify if all new values are non-nil" do
443
+ subject.collect! {|v| v }
444
+ should_not notify
445
+ end
446
+
447
+ it "should notify if any new values are nil" do
448
+ subject.collect! {|v| v == 3 ? nil : v }
449
+ should notify
450
+ end
451
+ end
452
+
453
+ describe '#map!' do
454
+ it "should not notify if all new values are non-nil" do
455
+ subject.map! {|v| v }
456
+ should_not notify
457
+ end
458
+
459
+ it "should notify if any new values are nil" do
460
+ subject.map! {|v| v == 3 ? nil : v }
461
+ should notify("must_only_ever_contain: Array#map! {}:"\
462
+ " nil.must_be, but matches NilClass in container [1, 2, nil, 4]")
463
+ end
464
+ end
465
+
466
+ describe '#concat' do
467
+ it "should not notify if all members in other_array are non-nil" do
468
+ subject.concat([6, 7, 8, 9])
469
+ should_not notify
470
+ end
471
+
472
+ it "should notify if any member in other_array is nil" do
473
+ subject.concat([6, 7, nil, 9])
474
+ should notify
475
+ end
476
+ end
477
+
478
+ describe '#fill' do
479
+ context "when called without a block" do
480
+ it "should not notify if obj is non-nil" do
481
+ subject.fill(3)
482
+ should_not notify
483
+ end
484
+
485
+ it "should notify if obj is nil" do
486
+ subject.fill(nil)
487
+ should notify("must_only_ever_contain: Array#fill(nil):"\
488
+ " nil.must_be, but matches NilClass in container"\
489
+ " [nil, nil, nil, nil]")
490
+ end
491
+ end
492
+
493
+ context "when called with a block" do
494
+ it "should not notify if block never returns nil" do
495
+ subject.fill {|v| v }
496
+ should_not notify
497
+ end
498
+
499
+ it "should notify if block ever returns nil" do
500
+ subject.fill {|v| v == 3 ? nil : v }
501
+ should notify
502
+ end
503
+ end
504
+ end
505
+
506
+ describe '#flatten!' do
507
+ it "should not notify if does not contain an array with"\
508
+ " nil members" do
509
+ subject << [[6, 7], [8, 9]]
510
+ subject.flatten!
511
+ should_not notify
512
+ end
513
+
514
+ it "should notify if contains an array with any nil members" do
515
+ subject << [[6, 7], [nil, 9]]
516
+ subject.flatten!
517
+ should notify
518
+ end
519
+ end
520
+
521
+ describe '#insert' do
522
+ it "should not notify if all objs are non-nil" do
523
+ subject.insert(2, 6, 7, 8, 9)
524
+ should_not notify
525
+ end
526
+
527
+ it "should notify if any objs are nil" do
528
+ subject.insert(2, 6, 7, nil, 9)
529
+ should notify
530
+ end
531
+ end
532
+
533
+ describe '#push' do
534
+ it "should not notify if all objs are non-nil" do
535
+ subject.push(6, 7, 8, 9)
536
+ should_not notify
537
+ end
538
+
539
+ it "should notify if any objs are nil" do
540
+ subject.push(6, 7, nil, 9)
541
+ should notify("must_only_ever_contain: Array#push(6, 7, nil, 9):"\
542
+ " nil.must_be, but matches NilClass in container"\
543
+ " [6, 7, nil, 9]")
544
+ end
545
+ end
546
+
547
+ describe '#replace' do
548
+ it "should not notify if all members in other_array are non-nil" do
549
+ subject.replace([6, 7, 8, 9])
550
+ should_not notify
551
+ end
552
+
553
+ it "should notify if any members in other_array are nil" do
554
+ subject.replace([6, 7, nil, 9])
555
+ should notify
556
+ end
557
+ end
558
+
559
+ describe '#unshift' do
560
+ it "should not notify if all objs are non-nil" do
561
+ subject.unshift(6, 7, 8, 9)
562
+ should_not notify
563
+ end
564
+
565
+ it "should notify if any objs are nil" do
566
+ subject.unshift(6, 7, nil, 9)
567
+ should notify
568
+ end
569
+ end
570
+ end
571
+
572
+ context "when called on a hash" do
573
+ subject { {} }
574
+
575
+ context "when called with no arguments" do
576
+ before do
577
+ subject.must_only_ever_contain
578
+ end
579
+
580
+ example "must_only_ever_contain_cases should == []" do
581
+ subject.must_only_ever_contain_cases.should == []
582
+ end
583
+
584
+ it "should notify if inserting a nil value" do
585
+ subject[:nil] = nil
586
+ should notify
587
+ end
588
+
589
+ it "should notify if inserting a false key" do
590
+ subject[false] = :false
591
+ should notify("must_only_ever_contain: Hash#[]=(false, :false):"\
592
+ " pair {false=>:false} does not match [] in container"\
593
+ " {false=>:false}")
594
+ end
595
+
596
+ it "should not notify if inserting a regular pair" do
597
+ subject[:key] = :value
598
+ should_not notify
599
+ end
600
+ end
601
+
602
+ context "when called with a hash" do
603
+ before do
604
+ subject.must_only_ever_contain(Symbol => Integer, Integer => Symbol)
605
+ end
606
+
607
+ it "should notify if inserting a non-matching key" do
608
+ subject["six"] = 6
609
+ subject["six"].should == 6
610
+ should notify("must_only_ever_contain: Hash#[]=(\"six\", 6):"\
611
+ " pair {\"six\"=>6} does not match"\
612
+ " [{Symbol=>Integer, Integer=>Symbol}] in container {\"six\"=>6}")
613
+ end
614
+
615
+ it "should notify if inserting a matching value" do
616
+ subject[:six] = :six
617
+ subject[:six].should == :six
618
+ should notify
619
+ end
620
+
621
+ it "should not notify if inserting a non-matching pair" do
622
+ subject[:six] = 6
623
+ subject[:six].should == 6
624
+ should_not notify
625
+ end
626
+
627
+ it "should not notify if replaced with an acceptable hash" do
628
+ subject[:six] = 6
629
+ subject.replace({:sym => 343}).should == subject
630
+ subject[:six].should be_nil
631
+ subject[:sym].should == 343
632
+ should_not notify
633
+ end
634
+
635
+ it "should notify if merged with an unacceptable hash" do
636
+ subject.merge!({3 => 1})
637
+ should notify("must_only_ever_contain: Hash#merge!({3=>1}):"\
638
+ " pair {3=>1} does not match"\
639
+ " [{Symbol=>Integer, Integer=>Symbol}] in container {3=>1}")
640
+ end
641
+
642
+ it "should not notify if updated with an acceptable hash" do
643
+ subject.update({:yes => 1})
644
+ should_not notify
645
+ end
646
+
647
+ it "should notify if storing a matching key" do
648
+ subject.store(2.3, :float)
649
+ should notify
650
+ end
651
+ end
652
+
653
+ describe '#must_only_ever_contain_cases' do
654
+ before do
655
+ subject.must_only_ever_contain(Symbol => Symbol)
656
+ end
657
+
658
+ example "must_only_ever_contain_cases"\
659
+ " should == [{Symbol => Symbol}]" do
660
+ subject.must_only_ever_contain_cases.should == [{Symbol => Symbol}]
661
+ end
662
+
663
+ it "should not notify if inserting Symbol => Symbol pair" do
664
+ subject[:hello] = :granny
665
+ should_not notify
666
+ end
667
+
668
+ it "should notify if inserting Symbol => Integer pair" do
669
+ subject[:hello] = 970
670
+ should notify
671
+ end
672
+
673
+ it "should notify if inserting Integer => Integer pair" do
674
+ subject[3984] = 970
675
+ should notify("must_only_ever_contain: Hash#[]=(3984, 970):"\
676
+ " pair {3984=>970} does not match [{Symbol=>Symbol}] in"\
677
+ " container {3984=>970}")
678
+ end
679
+
680
+ context "when #must_only_ever_contain_cases is updated" do
681
+ let(:cases) { [{Symbol => Symbol}, {Symbol => Integer}] }
682
+
683
+ before do
684
+ subject.must_only_ever_contain_cases = cases
685
+ end
686
+
687
+ example "must_only_ever_contain_cases should =="\
688
+ " [{Symbol => Symbol}, {Symbol => Integer}]" do
689
+ subject.must_only_ever_contain_cases.should == cases
690
+ end
691
+
692
+ it "should not notify if inserting Symbol => Symbol pair" do
693
+ subject[:hello] = :granny
694
+ should_not notify
695
+ end
696
+
697
+ it "should not notify if inserting Symbol => Integer pair" do
698
+ subject[:hello] = 970
699
+ should_not notify
700
+ end
701
+
702
+ it "should notify if inserting Integer => Integer pair" do
703
+ subject[3984] = 970
704
+ should notify
705
+ end
706
+ end
707
+ end
708
+
709
+ context "when it is initially non-empty" do
710
+ before do
711
+ subject[:hello] = :world
712
+ end
713
+
714
+ it "should not notify if any cases match" do
715
+ subject.must_only_ever_contain(Symbol => Symbol)
716
+ should_not notify
717
+ end
718
+
719
+ it "should notify if cases do not match" do
720
+ subject.must_only_ever_contain(Symbol => String)
721
+ should notify("must_only_ever_contain: pair {:hello=>:world} does"\
722
+ " not match [{Symbol=>String}] in container {:hello=>:world}")
723
+ end
724
+ end
725
+ end
726
+
727
+ describe "custom" do
728
+ it_should_behave_like "custom MustOnlyEverContain"
729
+
730
+ context "without MustOnlyEverContain.registered_class" do
731
+ describe '#must_only_contain' do
732
+ it "should use each to check the contents" do
733
+ subject.must_only_contain(String)
734
+ subject.should be_each_called
735
+ should notify
736
+ end
737
+ end
738
+
739
+ describe '#must_only_ever_contain' do
740
+ it "should raise TypeError" do
741
+ expect do
742
+ subject.must_only_ever_contain(Symbol)
743
+ end.should raise_error(TypeError,
744
+ /No MustOnlyEverContain.registered_class for .*Box/)
745
+ end
746
+ end
747
+ end
748
+
749
+ context "with MustOnlyEverContain.registered_class" do
750
+ register_before_and_unregister_after
751
+
752
+ context "when subject already has singleton methods" do
753
+ it "should raise ArgumentError" do
754
+ expect do
755
+ class <<subject
756
+ def singleton_method
757
+ end
758
+ end
759
+ subject.must_only_ever_contain(Symbol)
760
+ end.should raise_error(ArgumentError,
761
+ /must_only_ever_contain adds singleton methods but receiver .*/)
762
+ end
763
+ end
764
+
765
+ context "when updating contents" do
766
+ it "should notify if does not match must_only_ever_contain_cases" do
767
+ subject.must_only_ever_contain(Symbol)
768
+ subject.contents = 435
769
+ should notify
770
+ end
771
+
772
+ it "should not notify if matches must_only_ever_contain_cases" do
773
+ subject.must_only_ever_contain(Symbol)
774
+ subject.contents = :another_symbol
775
+ should_not notify
776
+ end
777
+ end
778
+
779
+ context "when emptied" do
780
+ it "should notify if nil does not match"\
781
+ " must_only_ever_contain_cases" do
782
+ subject.must_only_ever_contain(Symbol)
783
+ subject.empty!
784
+ subject.should_not be_each_called
785
+ should notify
786
+ end
787
+ end
788
+
789
+ describe "when called with bad arguments" do
790
+ it "should raise when trying to register a non-class" do
791
+ expect do
792
+ MustOnlyEverContain.register(:not_a_class)
793
+ end.should raise_error(ArgumentError)
794
+ end
795
+
796
+ it "should raise when trying to register a class more than once" do
797
+ expect do
798
+ MustOnlyEverContain.register(Box)
799
+ end.should raise_error(ArgumentError)
800
+ end
801
+ end
802
+ end
803
+ end
804
+ end
805
+
806
+ describe '#must_never_ever_contain' do
807
+ context "when called on an array" do
808
+ subject { [nil] }
809
+
810
+ before do
811
+ subject.must_never_ever_contain
812
+ end
813
+
814
+ it "should notify if initially contains a matching member" do
815
+ array = [:oops]
816
+ array.must_never_ever_contain
817
+ should notify("must_never_ever_contain: :oops.must_not_be, but"\
818
+ " matches Symbol in container [:oops]")
819
+ end
820
+
821
+ describe '#<<' do
822
+ it "should not notify if obj is nil" do
823
+ subject << nil
824
+ should_not notify
825
+ end
826
+
827
+ it "should notify if obj is non-nil" do
828
+ subject << 5
829
+ should notify("must_never_ever_contain: Array#<<(5):"\
830
+ " 5.must_not_be, but matches Fixnum in container"\
831
+ " [nil, 5]")
832
+ end
833
+ end
834
+
835
+ describe '#collect!' do
836
+ it "should not notify if all new values are nil" do
837
+ subject.collect! {|v| v }
838
+ should_not notify
839
+ end
840
+
841
+ it "should notify if any new values are non-nil" do
842
+ subject.collect! {|v| 5 }
843
+ should notify
844
+ end
845
+ end
846
+ end
847
+
848
+ context "when called on a hash" do
849
+ subject { {} }
850
+
851
+ context "when called with a hash" do
852
+ before do
853
+ subject.must_never_ever_contain(Symbol => Integer,
854
+ Integer => Symbol)
855
+ end
856
+
857
+ it "should notify if inserting a non-matching value" do
858
+ subject[:six] = 6
859
+ subject[:six].should == 6
860
+ should notify
861
+ end
862
+
863
+ it "should not notify if inserting a matching pair" do
864
+ subject[:six] = :six
865
+ subject[:six].should == :six
866
+ should_not notify
867
+ end
868
+ end
869
+
870
+ context "when it is initially non-empty" do
871
+ before do
872
+ subject[:hello] = :world
873
+ end
874
+
875
+ it "should not notify if no cases match" do
876
+ subject.must_never_ever_contain(Symbol => String)
877
+ should_not notify
878
+ end
879
+
880
+ it "should notify if any cases match" do
881
+ subject.must_never_ever_contain(Symbol => Symbol)
882
+ should notify("must_never_ever_contain: pair {:hello=>:world}"\
883
+ " matches [{Symbol=>Symbol}] in container {:hello=>:world}")
884
+ end
885
+ end
886
+ end
887
+
888
+ describe "custom" do
889
+ it_should_behave_like "custom MustOnlyEverContain"
890
+
891
+ describe "without MustOnlyEverContain.registered_class" do
892
+ describe '#must_not_contain' do
893
+ it "should use each to check the contents" do
894
+ subject.must_not_contain(Symbol)
895
+ subject.should be_each_called
896
+ should notify
897
+ end
898
+ end
899
+
900
+ describe '#must_never_ever_contain' do
901
+ it "should raise TypeError" do
902
+ expect do
903
+ subject.must_never_ever_contain(String)
904
+ end.should raise_error(TypeError,
905
+ /No MustOnlyEverContain.registered_class for .*Box/)
906
+ end
907
+ end
908
+ end
909
+
910
+ describe "with MustOnlyEverContain.registered_class" do
911
+ register_before_and_unregister_after
912
+
913
+ context "when subject already has singleton methods" do
914
+ it "should raise ArgumentError" do
915
+ expect do
916
+ class <<subject
917
+ def singleton_method
918
+ end
919
+ end
920
+ subject.must_never_ever_contain(Symbol)
921
+ end.should raise_error(ArgumentError,
922
+ /must_never_ever_contain adds singleton methods but .*/)
923
+ end
924
+ end
925
+
926
+ context "when updating contents" do
927
+ it "should notify if matches must_only_ever_contain_cases" do
928
+ subject.must_only_ever_contain(Numeric)
929
+ subject.contents = 435
930
+ should notify
931
+ end
932
+
933
+ it "should not notify if does not match"\
934
+ " must_only_ever_contain_cases" do
935
+ subject.must_never_ever_contain(Numeric)
936
+ subject.contents = :another_symbol
937
+ should_not notify
938
+ end
939
+ end
940
+
941
+ context "when emptied" do
942
+ it "should notify if nil matches must_never_ever_contain_cases" do
943
+ subject.must_never_ever_contain(nil)
944
+ subject.empty!
945
+ subject.should_not be_each_called
946
+ should notify
947
+ end
948
+ end
949
+ end
950
+ end
951
+ end
952
+ end