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.
- data/.gitignore +2 -0
- data/README.md +348 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/doc/readme/examples.rb +262 -0
- data/doc/readme/run_examples.rb +47 -0
- data/lib/must_be/attr_typed.rb +78 -0
- data/lib/must_be/basic.rb +120 -0
- data/lib/must_be/containers.rb +291 -0
- data/lib/must_be/containers_registered_classes.rb +83 -0
- data/lib/must_be/core.rb +247 -0
- data/lib/must_be/nonstandard_control_flow.rb +159 -0
- data/lib/must_be/proxy.rb +62 -0
- data/lib/must_be.rb +9 -0
- data/must_be.gemspec +71 -0
- data/spec/must_be/attr_typed_spec.rb +225 -0
- data/spec/must_be/basic_spec.rb +578 -0
- data/spec/must_be/containers_spec.rb +952 -0
- data/spec/must_be/core_spec.rb +675 -0
- data/spec/must_be/nonstandard_control_flow_spec.rb +845 -0
- data/spec/must_be/proxy_spec.rb +194 -0
- data/spec/notify_matcher_spec.rb +59 -0
- data/spec/spec_helper.rb +180 -0
- data/spec/typical_usage_spec.rb +176 -0
- metadata +98 -0
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MustBe do
|
4
|
+
include MustBeExampleHelper
|
5
|
+
|
6
|
+
describe 'Module#attr_typed' do
|
7
|
+
context "when updating" do
|
8
|
+
module ModuleWhoUsesAttrTyped
|
9
|
+
attr_typed :int, Bignum, Fixnum
|
10
|
+
attr_typed :positive_int, Bignum, Fixnum do |n|
|
11
|
+
n > 0
|
12
|
+
end
|
13
|
+
attr_typed :non_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
class UsesAttrTyped
|
17
|
+
include ModuleWhoUsesAttrTyped
|
18
|
+
|
19
|
+
attr_typed :float, Float
|
20
|
+
attr_typed :empty, &:empty?
|
21
|
+
attr_typed :collection, Array, Hash, Range
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { UsesAttrTyped.new }
|
25
|
+
|
26
|
+
context "against one type constraint" do
|
27
|
+
it "should not notify if new value has the type" do
|
28
|
+
subject.float = 23.3
|
29
|
+
subject.float.should == 23.3
|
30
|
+
should_not notify
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should notify if new value does not have the type" do
|
34
|
+
subject.float = 23
|
35
|
+
should notify("attribute `float' must be a Float,"\
|
36
|
+
" but value 23 is a Fixnum")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "against two type constraints" do
|
41
|
+
it "should not notify if new value matches one of the constraints" do
|
42
|
+
subject.int = 56
|
43
|
+
should_not notify
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should notify if new value does not match either constraint " do
|
47
|
+
subject.int = 56.6
|
48
|
+
should notify("attribute `int' must be a Bignum or Fixnum,"\
|
49
|
+
" but value 56.6 is a Float")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "against multiple type constraints" do
|
54
|
+
it "should not notify if new value matches last constraint" do
|
55
|
+
subject.collection = 1..3
|
56
|
+
should_not notify
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should notify if new value matches none of the constraints" do
|
60
|
+
subject.collection = :scalar
|
61
|
+
should notify("attribute `collection' must be a one of"\
|
62
|
+
" [Array, Hash, Range], but value :scalar is a Symbol")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "against a block constraint" do
|
67
|
+
it "should not notify if block[value] is true" do
|
68
|
+
subject.empty = []
|
69
|
+
should_not notify
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should notify if block[value] is not true" do
|
73
|
+
subject.empty = [:not, :empty]
|
74
|
+
should notify("attribute `empty' cannot be [:not, :empty]")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "against two types and a block constraint" do
|
79
|
+
it "should not notify if new value matches one of the types"\
|
80
|
+
" and block[value] is true" do
|
81
|
+
subject.positive_int = 45
|
82
|
+
should_not notify
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should notify if new value does not match one of the types" do
|
86
|
+
subject.positive_int = 87.6
|
87
|
+
should notify("attribute `positive_int' must be a Bignum"\
|
88
|
+
" or Fixnum, but value 87.6 is a Float")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should notify if block[value] is not true" do
|
92
|
+
subject.positive_int = -11
|
93
|
+
should notify("attribute `positive_int' cannot be -11")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "against no listed contraint" do
|
98
|
+
it "should not notify if new value is non-nil" do
|
99
|
+
subject.non_nil = false
|
100
|
+
should_not notify
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should notify if new value is nil" do
|
104
|
+
subject.non_nil = nil
|
105
|
+
should notify("attribute `non_nil' cannot be nil")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when called twice with the same symbol" do
|
111
|
+
class AttrTypedCalledTwiceForSameSymbol
|
112
|
+
attr_typed :twice, Symbol
|
113
|
+
attr_typed :twice, String
|
114
|
+
end
|
115
|
+
|
116
|
+
subject { AttrTypedCalledTwiceForSameSymbol.new }
|
117
|
+
|
118
|
+
it "second call should override first" do
|
119
|
+
subject.twice = :symbol
|
120
|
+
should notify("attribute `twice' must be a String,"\
|
121
|
+
" but value :symbol is a Symbol")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "when called with bad arguments" do
|
126
|
+
subject { Class.new }
|
127
|
+
|
128
|
+
context "when symbol is bad" do
|
129
|
+
it "should raise if symbol cannot be converted #to_sym" do
|
130
|
+
expect do
|
131
|
+
subject.attr_typed [], Object
|
132
|
+
end.should raise_error(TypeError, "[] is not a symbol")
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should raise if symbol is a Fixnum" do
|
136
|
+
expect do
|
137
|
+
subject.attr_typed 111, Object
|
138
|
+
end.should raise_error(TypeError, "111 is not a symbol")
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should be fine if symbol is a String" do
|
142
|
+
expect do
|
143
|
+
subject.attr_typed "string", Object
|
144
|
+
end.should_not raise_error
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "when types is bad" do
|
149
|
+
it "should raise if any type is an array" do
|
150
|
+
expect do
|
151
|
+
subject.attr_typed :prop, [Array, Object]
|
152
|
+
end.should raise_error(TypeError, "class or module required")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should raise if any type is a String" do
|
156
|
+
expect do
|
157
|
+
subject.attr_typed :prop, "string"
|
158
|
+
end.should raise_error(TypeError, "class or module required")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "after disabling" do
|
164
|
+
before do
|
165
|
+
@enabled_class = Class.new
|
166
|
+
@enabled_class.attr_typed :prop, Symbol
|
167
|
+
@enabled_instance = @enabled_class.new
|
168
|
+
end
|
169
|
+
|
170
|
+
before_disable_after_enable
|
171
|
+
|
172
|
+
context "when .attr_typed was called while still enabled" do
|
173
|
+
it "should not notify" do
|
174
|
+
@enabled_instance.prop = 91
|
175
|
+
@enabled_instance.prop.should == 91
|
176
|
+
should_not notify
|
177
|
+
end
|
178
|
+
|
179
|
+
context "after being re-enabled" do
|
180
|
+
before do
|
181
|
+
MustBe.enable
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should notify again" do
|
185
|
+
@enabled_instance.prop = 91
|
186
|
+
should notify("attribute `prop' must be a Symbol,"\
|
187
|
+
" but value 91 is a Fixnum")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context "when .attr_typed is called" do
|
193
|
+
before do
|
194
|
+
@disabled_class = Class.new
|
195
|
+
@disabled_class.attr_typed :prop, Symbol
|
196
|
+
@disabled_instance = @disabled_class.new
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should not notify" do
|
200
|
+
@disabled_instance.prop = 91
|
201
|
+
@disabled_instance.prop.should == 91
|
202
|
+
should_not notify
|
203
|
+
end
|
204
|
+
|
205
|
+
context "after being re-enabled" do
|
206
|
+
before do
|
207
|
+
MustBe.enable
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should still not notify" do
|
211
|
+
@disabled_instance.prop = 91
|
212
|
+
should_not notify
|
213
|
+
end
|
214
|
+
|
215
|
+
it ".attr_typed should be re-enabled" do
|
216
|
+
@disabled_class.attr_typed :prop, Symbol
|
217
|
+
@disabled_instance.prop = 91
|
218
|
+
should notify("attribute `prop' must be a Symbol,"\
|
219
|
+
" but value 91 is a Fixnum")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|