contracts 0.12.0 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,278 +3,304 @@ RSpec.describe "Contracts:" do
3
3
  @o = GenericExample.new
4
4
  end
5
5
 
6
+ def fails(&some)
7
+ expect { some.call }.to raise_error(ContractError)
8
+ end
9
+
10
+ def passes(&some)
11
+ expect { some.call }.to_not raise_error
12
+ end
13
+
14
+ describe "DescendantOf:" do
15
+ it "should pass for Array" do
16
+ passes { @o.enumerable_descendant_test(Array) }
17
+ end
18
+
19
+ it "should pass for a hash" do
20
+ passes { @o.enumerable_descendant_test(Hash) }
21
+ end
22
+
23
+ it "should fail for a number class" do
24
+ fails { @o.enumerable_descendant_test(Integer) }
25
+ end
26
+
27
+ it "should fail for a non-class" do
28
+ fails { @o.enumerable_descendant_test(1) }
29
+ end
30
+ end
31
+
6
32
  describe "Num:" do
7
33
  it "should pass for Fixnums" do
8
- expect { @o.double(2) }.to_not raise_error
34
+ passes { @o.double(2) }
9
35
  end
10
36
 
11
37
  it "should pass for Floats" do
12
- expect { @o.double(2.2) }.to_not raise_error
38
+ passes { @o.double(2.2) }
13
39
  end
14
40
 
15
41
  it "should fail for nil and other data types" do
16
- expect { @o.double(nil) }.to raise_error(ContractError)
17
- expect { @o.double(:x) }.to raise_error(ContractError)
18
- expect { @o.double("x") }.to raise_error(ContractError)
19
- expect { @o.double(/x/) }.to raise_error(ContractError)
42
+ fails { @o.double(nil) }
43
+ fails { @o.double(:x) }
44
+ fails { @o.double("x") }
45
+ fails { @o.double(/x/) }
20
46
  end
21
47
  end
22
48
 
23
49
  describe "Pos:" do
24
50
  it "should pass for positive numbers" do
25
- expect { @o.pos_test(1) }.to_not raise_error
26
- expect { @o.pos_test(1.6) }.to_not raise_error
51
+ passes { @o.pos_test(1) }
52
+ passes { @o.pos_test(1.6) }
27
53
  end
28
54
 
29
55
  it "should fail for 0" do
30
- expect { @o.pos_test(0) }.to raise_error(ContractError)
56
+ fails { @o.pos_test(0) }
31
57
  end
32
58
 
33
59
  it "should fail for negative numbers" do
34
- expect { @o.pos_test(-1) }.to raise_error(ContractError)
35
- expect { @o.pos_test(-1.6) }.to raise_error(ContractError)
60
+ fails { @o.pos_test(-1) }
61
+ fails { @o.pos_test(-1.6) }
36
62
  end
37
63
 
38
64
  it "should fail for nil and other data types" do
39
- expect { @o.pos_test(nil) }.to raise_error(ContractError)
40
- expect { @o.pos_test(:x) }.to raise_error(ContractError)
41
- expect { @o.pos_test("x") }.to raise_error(ContractError)
42
- expect { @o.pos_test(/x/) }.to raise_error(ContractError)
65
+ fails { @o.pos_test(nil) }
66
+ fails { @o.pos_test(:x) }
67
+ fails { @o.pos_test("x") }
68
+ fails { @o.pos_test(/x/) }
43
69
  end
44
70
  end
45
71
 
46
72
  describe "Neg:" do
47
73
  it "should pass for negative numbers" do
48
- expect { @o.neg_test(-1) }.to_not raise_error
49
- expect { @o.neg_test(-1.6) }.to_not raise_error
74
+ passes { @o.neg_test(-1) }
75
+ passes { @o.neg_test(-1.6) }
50
76
  end
51
77
 
52
78
  it "should fail for 0" do
53
- expect { @o.neg_test(0) }.to raise_error(ContractError)
79
+ fails { @o.neg_test(0) }
54
80
  end
55
81
 
56
82
  it "should fail for positive numbers" do
57
- expect { @o.neg_test(1) }.to raise_error(ContractError)
58
- expect { @o.neg_test(1.6) }.to raise_error(ContractError)
83
+ fails { @o.neg_test(1) }
84
+ fails { @o.neg_test(1.6) }
59
85
  end
60
86
 
61
87
  it "should fail for nil and other data types" do
62
- expect { @o.neg_test(nil) }.to raise_error(ContractError)
63
- expect { @o.neg_test(:x) }.to raise_error(ContractError)
64
- expect { @o.neg_test("x") }.to raise_error(ContractError)
65
- expect { @o.neg_test(/x/) }.to raise_error(ContractError)
88
+ fails { @o.neg_test(nil) }
89
+ fails { @o.neg_test(:x) }
90
+ fails { @o.neg_test("x") }
91
+ fails { @o.neg_test(/x/) }
66
92
  end
67
93
  end
68
94
 
69
95
  describe "Nat:" do
70
96
  it "should pass for 0" do
71
- expect { @o.nat_test(0) }.to_not raise_error
97
+ passes { @o.nat_test(0) }
72
98
  end
73
99
 
74
100
  it "should pass for positive whole numbers" do
75
- expect { @o.nat_test(1) }.to_not raise_error
101
+ passes { @o.nat_test(1) }
76
102
  end
77
103
 
78
104
  it "should fail for positive non-whole numbers" do
79
- expect { @o.nat_test(1.5) }.to raise_error(ContractError)
105
+ fails { @o.nat_test(1.5) }
80
106
  end
81
107
 
82
108
  it "should fail for negative numbers" do
83
- expect { @o.nat_test(-1) }.to raise_error(ContractError)
84
- expect { @o.nat_test(-1.6) }.to raise_error(ContractError)
109
+ fails { @o.nat_test(-1) }
110
+ fails { @o.nat_test(-1.6) }
85
111
  end
86
112
 
87
113
  it "should fail for nil and other data types" do
88
- expect { @o.nat_test(nil) }.to raise_error(ContractError)
89
- expect { @o.nat_test(:x) }.to raise_error(ContractError)
90
- expect { @o.nat_test("x") }.to raise_error(ContractError)
91
- expect { @o.nat_test(/x/) }.to raise_error(ContractError)
114
+ fails { @o.nat_test(nil) }
115
+ fails { @o.nat_test(:x) }
116
+ fails { @o.nat_test("x") }
117
+ fails { @o.nat_test(/x/) }
92
118
  end
93
119
  end
94
120
 
95
121
  describe "Any:" do
96
122
  it "should pass for numbers" do
97
- expect { @o.show(1) }.to_not raise_error
123
+ passes { @o.show(1) }
98
124
  end
99
125
  it "should pass for strings" do
100
- expect { @o.show("bad") }.to_not raise_error
126
+ passes { @o.show("bad") }
101
127
  end
102
128
  it "should pass for procs" do
103
- expect { @o.show(lambda {}) }.to_not raise_error
129
+ passes { @o.show(lambda {}) }
104
130
  end
105
131
  it "should pass for nil" do
106
- expect { @o.show(nil) }.to_not raise_error
132
+ passes { @o.show(nil) }
107
133
  end
108
134
  end
109
135
 
110
136
  describe "None:" do
111
137
  it "should fail for numbers" do
112
- expect { @o.fail_all(1) }.to raise_error(ContractError)
138
+ fails { @o.fail_all(1) }
113
139
  end
114
140
  it "should fail for strings" do
115
- expect { @o.fail_all("bad") }.to raise_error(ContractError)
141
+ fails { @o.fail_all("bad") }
116
142
  end
117
143
  it "should fail for procs" do
118
- expect { @o.fail_all(lambda {}) }.to raise_error(ContractError)
144
+ fails { @o.fail_all(lambda {}) }
119
145
  end
120
146
  it "should fail for nil" do
121
- expect { @o.fail_all(nil) }.to raise_error(ContractError)
147
+ fails { @o.fail_all(nil) }
122
148
  end
123
149
  end
124
150
 
125
151
  describe "Or:" do
126
152
  it "should pass for nums" do
127
- expect { @o.num_or_string(1) }.to_not raise_error
153
+ passes { @o.num_or_string(1) }
128
154
  end
129
155
 
130
156
  it "should pass for strings" do
131
- expect { @o.num_or_string("bad") }.to_not raise_error
157
+ passes { @o.num_or_string("bad") }
132
158
  end
133
159
 
134
160
  it "should fail for nil" do
135
- expect { @o.num_or_string(nil) }.to raise_error(ContractError)
161
+ fails { @o.num_or_string(nil) }
136
162
  end
137
163
  end
138
164
 
139
165
  describe "Xor:" do
140
166
  it "should pass for an object with a method :good" do
141
- expect { @o.xor_test(A.new) }.to_not raise_error
167
+ passes { @o.xor_test(A.new) }
142
168
  end
143
169
 
144
170
  it "should pass for an object with a method :bad" do
145
- expect { @o.xor_test(B.new) }.to_not raise_error
171
+ passes { @o.xor_test(B.new) }
146
172
  end
147
173
 
148
174
  it "should fail for an object with neither method" do
149
- expect { @o.xor_test(1) }.to raise_error(ContractError)
175
+ fails { @o.xor_test(1) }
150
176
  end
151
177
 
152
178
  it "should fail for an object with both methods :good and :bad" do
153
- expect { @o.xor_test(F.new) }.to raise_error(ContractError)
179
+ fails { @o.xor_test(F.new) }
154
180
  end
155
181
  end
156
182
 
157
183
  describe "And:" do
158
184
  it "should pass for an object of class A that has a method :good" do
159
- expect { @o.and_test(A.new) }.to_not raise_error
185
+ passes { @o.and_test(A.new) }
160
186
  end
161
187
 
162
188
  it "should fail for an object that has a method :good but isn't of class A" do
163
- expect { @o.and_test(F.new) }.to raise_error(ContractError)
189
+ fails { @o.and_test(F.new) }
164
190
  end
165
191
  end
166
192
 
167
193
  describe "Enum:" do
168
194
  it "should pass for an object that is included" do
169
- expect { @o.enum_test(:a) }.to_not raise_error
195
+ passes { @o.enum_test(:a) }
170
196
  end
171
197
 
172
198
  it "should fail for an object that is not included" do
173
- expect { @o.enum_test(:z) }.to raise_error(ContractError)
199
+ fails { @o.enum_test(:z) }
174
200
  end
175
201
  end
176
202
 
177
203
  describe "RespondTo:" do
178
204
  it "should pass for an object that responds to :good" do
179
- expect { @o.responds_test(A.new) }.to_not raise_error
205
+ passes { @o.responds_test(A.new) }
180
206
  end
181
207
 
182
208
  it "should fail for an object that doesn't respond to :good" do
183
- expect { @o.responds_test(B.new) }.to raise_error(ContractError)
209
+ fails { @o.responds_test(B.new) }
184
210
  end
185
211
  end
186
212
 
187
213
  describe "Send:" do
188
214
  it "should pass for an object that returns true for method :good" do
189
- expect { @o.send_test(A.new) }.to_not raise_error
215
+ passes { @o.send_test(A.new) }
190
216
  end
191
217
 
192
218
  it "should fail for an object that returns false for method :good" do
193
- expect { @o.send_test(F.new) }.to raise_error(ContractError)
219
+ fails { @o.send_test(F.new) }
194
220
  end
195
221
  end
196
222
 
197
223
  describe "Exactly:" do
198
224
  it "should pass for an object that is exactly a Parent" do
199
- expect { @o.exactly_test(Parent.new) }.to_not raise_error
225
+ passes { @o.exactly_test(Parent.new) }
200
226
  end
201
227
 
202
228
  it "should fail for an object that inherits from Parent" do
203
- expect { @o.exactly_test(Child.new) }.to raise_error(ContractError)
229
+ fails { @o.exactly_test(Child.new) }
204
230
  end
205
231
 
206
232
  it "should fail for an object that is not related to Parent at all" do
207
- expect { @o.exactly_test(A.new) }.to raise_error(ContractError)
233
+ fails { @o.exactly_test(A.new) }
208
234
  end
209
235
  end
210
236
 
211
237
  describe "Eq:" do
212
238
  it "should pass for a class" do
213
- expect { @o.eq_class_test(Foo) }
239
+ passes { @o.eq_class_test(Foo) }
214
240
  end
215
241
 
216
242
  it "should pass for a module" do
217
- expect { @o.eq_module_test(Bar) }
243
+ passes { @o.eq_module_test(Bar) }
218
244
  end
219
245
 
220
246
  it "should pass for other values" do
221
- expect { @o.eq_value_test(Baz) }
247
+ passes { @o.eq_value_test(Baz) }
222
248
  end
223
249
 
224
250
  it "should fail when not equal" do
225
- expect { @o.eq_class_test(Bar) }.to raise_error(ContractError)
251
+ fails { @o.eq_class_test(Bar) }
226
252
  end
227
253
 
228
254
  it "should fail when given instance of class" do
229
- expect { @o.eq_class_test(Foo.new) }.to raise_error(ContractError)
255
+ fails { @o.eq_class_test(Foo.new) }
230
256
  end
231
257
  end
232
258
 
233
259
  describe "Not:" do
234
260
  it "should pass for an argument that isn't nil" do
235
- expect { @o.not_nil(1) }.to_not raise_error
261
+ passes { @o.not_nil(1) }
236
262
  end
237
263
 
238
264
  it "should fail for nil" do
239
- expect { @o.not_nil(nil) }.to raise_error(ContractError)
265
+ fails { @o.not_nil(nil) }
240
266
  end
241
267
  end
242
268
 
243
269
  describe "ArrayOf:" do
244
270
  it "should pass for an array of nums" do
245
- expect { @o.product([1, 2, 3]) }.to_not raise_error
271
+ passes { @o.product([1, 2, 3]) }
246
272
  end
247
273
 
248
274
  it "should fail for an array with one non-num" do
249
- expect { @o.product([1, 2, 3, "bad"]) }.to raise_error(ContractError)
275
+ fails { @o.product([1, 2, 3, "bad"]) }
250
276
  end
251
277
 
252
278
  it "should fail for a non-array" do
253
- expect { @o.product(1) }.to raise_error(ContractError)
279
+ fails { @o.product(1) }
254
280
  end
255
281
  end
256
282
 
257
283
  describe "RangeOf:" do
258
284
  require "date"
259
285
  it "should pass for a range of nums" do
260
- expect { @o.first_in_range_num(3..10) }.to_not raise_error
286
+ passes { @o.first_in_range_num(3..10) }
261
287
  end
262
288
 
263
289
  it "should pass for a range of dates" do
264
290
  d1 = Date.today
265
291
  d2 = d1 + 18
266
- expect { @o.first_in_range_date(d1..d2) }.to_not raise_error
292
+ passes { @o.first_in_range_date(d1..d2) }
267
293
  end
268
294
 
269
295
  it "should fail for a non-range" do
270
- expect { @o.first_in_range_num("foo") }.to raise_error(ContractError)
271
- expect { @o.first_in_range_num(:foo) }.to raise_error(ContractError)
272
- expect { @o.first_in_range_num(5) }.to raise_error(ContractError)
273
- expect { @o.first_in_range_num(nil) }.to raise_error(ContractError)
296
+ fails { @o.first_in_range_num("foo") }
297
+ fails { @o.first_in_range_num(:foo) }
298
+ fails { @o.first_in_range_num(5) }
299
+ fails { @o.first_in_range_num(nil) }
274
300
  end
275
301
 
276
302
  it "should fail for a range with incorrect data type" do
277
- expect { @o.first_in_range_num("a".."z") }.to raise_error(ContractError)
303
+ fails { @o.first_in_range_num("a".."z") }
278
304
  end
279
305
 
280
306
  it "should fail for a badly-defined range" do
@@ -284,8 +310,8 @@ RSpec.describe "Contracts:" do
284
310
  # This test guards against ranges with inconsistent data types.
285
311
  begin
286
312
  d1 = Date.today
287
- expect { @o.first_in_range_date(d1..10).to raise_error(ContractError) }
288
- expect { @o.first_in_range_num(d1..10).to raise_error(ContractError) }
313
+ fails { @o.first_in_range_date(d1..10) }
314
+ fails { @o.first_in_range_num(d1..10) }
289
315
  rescue ArgumentError
290
316
  # If Ruby doesn't like the range, we ignore the test.
291
317
  :nop
@@ -295,26 +321,26 @@ RSpec.describe "Contracts:" do
295
321
 
296
322
  describe "SetOf:" do
297
323
  it "should pass for a set of nums" do
298
- expect { @o.product_from_set(Set.new([1, 2, 3])) }.to_not raise_error
324
+ passes { @o.product_from_set(Set.new([1, 2, 3])) }
299
325
  end
300
326
 
301
327
  it "should fail for an array with one non-num" do
302
- expect { @o.product_from_set(Set.new([1, 2, 3, "bad"])) }.to raise_error(ContractError)
328
+ fails { @o.product_from_set(Set.new([1, 2, 3, "bad"])) }
303
329
  end
304
330
 
305
331
  it "should fail for a non-array" do
306
- expect { @o.product_from_set(1) }.to raise_error(ContractError)
332
+ fails { @o.product_from_set(1) }
307
333
  end
308
334
  end
309
335
 
310
336
  describe "Bool:" do
311
337
  it "should pass for an argument that is a boolean" do
312
- expect { @o.bool_test(true) }.to_not raise_error
313
- expect { @o.bool_test(false) }.to_not raise_error
338
+ passes { @o.bool_test(true) }
339
+ passes { @o.bool_test(false) }
314
340
  end
315
341
 
316
342
  it "should fail for nil" do
317
- expect { @o.bool_test(nil) }.to raise_error(ContractError)
343
+ fails { @o.bool_test(nil) }
318
344
  end
319
345
  end
320
346
 
@@ -328,27 +354,31 @@ RSpec.describe "Contracts:" do
328
354
  end
329
355
 
330
356
  it "should fail for strings" do
331
- expect { @o.maybe_double("foo") }.to raise_error(ContractError)
357
+ fails { @o.maybe_double("foo") }
332
358
  end
333
359
  end
334
360
 
335
361
  describe "KeywordArgs:" do
336
362
  it "should pass for exact correct input" do
337
- expect { @o.person_keywordargs(:name => "calvin", :age => 10) }.to_not raise_error
363
+ passes { @o.person_keywordargs(:name => "calvin", :age => 10) }
338
364
  end
339
365
 
340
366
  it "should fail if some keys don't have contracts" do
341
- expect { @o.person_keywordargs(:name => "calvin", :age => 10, :foo => "bar") }.to raise_error(ContractError)
367
+ fails { @o.person_keywordargs(:name => "calvin", :age => 10, :foo => "bar") }
342
368
  end
343
369
 
344
370
  it "should fail if a key with a contract on it isn't provided" do
345
- expect { @o.person_keywordargs(:name => "calvin") }.to raise_error(ContractError)
371
+ fails { @o.person_keywordargs(:name => "calvin") }
346
372
  end
347
373
 
348
374
  it "should fail for incorrect input" do
349
- expect { @o.person_keywordargs(:name => 50, :age => 10) }.to raise_error(ContractError)
350
- expect { @o.hash_keywordargs(:hash => nil) }.to raise_error(ContractError)
351
- expect { @o.hash_keywordargs(:hash => 1) }.to raise_error(ContractError)
375
+ fails { @o.person_keywordargs(:name => 50, :age => 10) }
376
+ fails { @o.hash_keywordargs(:hash => nil) }
377
+ fails { @o.hash_keywordargs(:hash => 1) }
378
+ end
379
+
380
+ it "should pass if a method is overloaded with non-KeywordArgs" do
381
+ passes { @o.person_keywordargs("name", 10) }
352
382
  end
353
383
  end
354
384
 
@@ -380,10 +410,10 @@ RSpec.describe "Contracts:" do
380
410
  end
381
411
 
382
412
  context "given an unfulfilled contract" do
383
- it { expect { @o.gives_max_value(:panda => "1", :bamboo => "2") }.to raise_error(ContractError) }
384
- it { expect { @o.gives_max_value(nil) }.to raise_error(ContractError) }
385
- it { expect { @o.gives_max_value(1) }.to raise_error(ContractError) }
386
- it { expect { @o.pretty_gives_max_value(:panda => "1", :bamboo => "2") }.to raise_error(ContractError) }
413
+ it { fails { @o.gives_max_value(:panda => "1", :bamboo => "2") } }
414
+ it { fails { @o.gives_max_value(nil) } }
415
+ it { fails { @o.gives_max_value(1) } }
416
+ it { fails { @o.pretty_gives_max_value(:panda => "1", :bamboo => "2") } }
387
417
  end
388
418
 
389
419
  describe "#to_s" do
@@ -396,4 +426,36 @@ RSpec.describe "Contracts:" do
396
426
  end
397
427
  end
398
428
  end
429
+
430
+ describe "StrictHash:" do
431
+ context "when given an exact correct input" do
432
+ it "does not raise an error" do
433
+ passes { @o.strict_person(:name => "calvin", :age => 10) }
434
+ end
435
+ end
436
+
437
+ context "when given an input with correct keys but wrong types" do
438
+ it "raises an error" do
439
+ fails { @o.strict_person(:name => "calvin", :age => "10") }
440
+ end
441
+ end
442
+
443
+ context "when given an input with missing keys" do
444
+ it "raises an error" do
445
+ fails { @o.strict_person(:name => "calvin") }
446
+ end
447
+ end
448
+
449
+ context "when given an input with extra keys" do
450
+ it "raises an error" do
451
+ fails { @o.strict_person(:name => "calvin", :age => 10, :soft => true) }
452
+ end
453
+ end
454
+
455
+ context "when given not a hash" do
456
+ it "raises an error" do
457
+ fails { @o.strict_person(1337) }
458
+ end
459
+ end
460
+ end
399
461
  end