contracts 0.12.0 → 0.16.1

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