ward 0.1.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/.document +5 -0
- data/.gitignore +28 -0
- data/LICENSE +19 -0
- data/README.markdown +99 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/features/acceptance_matcher.feature +78 -0
- data/features/attribute_keyword.feature +13 -0
- data/features/close_to_matcher.feature +130 -0
- data/features/context_arguments.feature +47 -0
- data/features/equal_to_matcher.feature +25 -0
- data/features/error_messages.feature +69 -0
- data/features/external_validation.feature +15 -0
- data/features/has_matcher.feature +72 -0
- data/features/has_matcher_initialized_with_expectation.feature +94 -0
- data/features/has_matcher_relativities.feature +171 -0
- data/features/include_matcher.feature +28 -0
- data/features/is_keyword.feature +42 -0
- data/features/is_not_keyword.feature +62 -0
- data/features/match_matcher.feature +49 -0
- data/features/multiple_validators.feature +29 -0
- data/features/nil_matcher.feature +25 -0
- data/features/predicate_matcher.feature +23 -0
- data/features/present_matcher.feature +59 -0
- data/features/satisfy_matcher.feature +80 -0
- data/features/scenario_validation.feature +81 -0
- data/features/step_definitions/external_validation_steps.rb +69 -0
- data/features/step_definitions/generic_validation_steps.rb +33 -0
- data/features/step_definitions/object_definition_steps.rb +43 -0
- data/features/support/env.rb +12 -0
- data/features/support/object_builder.rb +33 -0
- data/features/support/struct.rb +38 -0
- data/lang/en.yml +56 -0
- data/lib/ward.rb +26 -0
- data/lib/ward/context.rb +70 -0
- data/lib/ward/context_chain.rb +87 -0
- data/lib/ward/dsl.rb +7 -0
- data/lib/ward/dsl/validation_block.rb +73 -0
- data/lib/ward/dsl/validation_builder.rb +190 -0
- data/lib/ward/errors.rb +213 -0
- data/lib/ward/matchers.rb +97 -0
- data/lib/ward/matchers/acceptance.rb +43 -0
- data/lib/ward/matchers/close_to.rb +60 -0
- data/lib/ward/matchers/equal_to.rb +33 -0
- data/lib/ward/matchers/has.rb +283 -0
- data/lib/ward/matchers/include.rb +54 -0
- data/lib/ward/matchers/match.rb +29 -0
- data/lib/ward/matchers/matcher.rb +68 -0
- data/lib/ward/matchers/nil.rb +30 -0
- data/lib/ward/matchers/predicate.rb +31 -0
- data/lib/ward/matchers/present.rb +56 -0
- data/lib/ward/matchers/satisfy.rb +65 -0
- data/lib/ward/spec.rb +17 -0
- data/lib/ward/spec/matcher_matcher.rb +114 -0
- data/lib/ward/support.rb +7 -0
- data/lib/ward/support/basic_object.rb +55 -0
- data/lib/ward/support/result.rb +49 -0
- data/lib/ward/validator.rb +147 -0
- data/lib/ward/validator_set.rb +115 -0
- data/lib/ward/version.rb +3 -0
- data/spec/lib/has_matcher_relativity_examples.rb +15 -0
- data/spec/lib/have_public_method_defined.rb +22 -0
- data/spec/rcov.opts +8 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/ward/context_chain_spec.rb +178 -0
- data/spec/ward/context_spec.rb +57 -0
- data/spec/ward/dsl/validation_block_spec.rb +27 -0
- data/spec/ward/dsl/validation_builder_spec.rb +212 -0
- data/spec/ward/errors_spec.rb +149 -0
- data/spec/ward/matchers/acceptance_spec.rb +16 -0
- data/spec/ward/matchers/close_to_spec.rb +57 -0
- data/spec/ward/matchers/equal_to_spec.rb +16 -0
- data/spec/ward/matchers/has_spec.rb +175 -0
- data/spec/ward/matchers/include_spec.rb +41 -0
- data/spec/ward/matchers/match_spec.rb +21 -0
- data/spec/ward/matchers/matcher_spec.rb +54 -0
- data/spec/ward/matchers/nil_spec.rb +16 -0
- data/spec/ward/matchers/predicate_spec.rb +19 -0
- data/spec/ward/matchers/present_spec.rb +16 -0
- data/spec/ward/matchers/satisfy_spec.rb +68 -0
- data/spec/ward/matchers_spec.rb +51 -0
- data/spec/ward/spec/have_public_method_defined_spec.rb +31 -0
- data/spec/ward/spec/matcher_matcher_spec.rb +217 -0
- data/spec/ward/validator_set_spec.rb +178 -0
- data/spec/ward/validator_spec.rb +264 -0
- data/tasks/features.rake +15 -0
- data/tasks/rcov.rake +24 -0
- data/tasks/spec.rake +18 -0
- data/tasks/yard.rake +9 -0
- data/ward.gemspec +176 -0
- metadata +239 -0
@@ -0,0 +1,178 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
# @todo
|
4
|
+
# Replace all cases of ValidatorSet.new with the DSL.
|
5
|
+
|
6
|
+
describe Ward::ValidatorSet do
|
7
|
+
subject { Ward::ValidatorSet }
|
8
|
+
|
9
|
+
#
|
10
|
+
# .build
|
11
|
+
#
|
12
|
+
|
13
|
+
describe '.build' do
|
14
|
+
describe 'when no initial set is provided' do
|
15
|
+
it 'should add the validators to the set' do
|
16
|
+
dsl = Ward::ValidatorSet.build do |object|
|
17
|
+
object.name.matches(/abc/)
|
18
|
+
object.name.length.is.equal_to(3)
|
19
|
+
end
|
20
|
+
|
21
|
+
# ValidatorSet doesn't have a size method, but does implement Enumerable
|
22
|
+
dsl.inject(0) { |c, *| c += 1 }.should == 2
|
23
|
+
end
|
24
|
+
end # when no initial set is provided
|
25
|
+
|
26
|
+
describe 'when an initial set is provided' do
|
27
|
+
before(:all) do
|
28
|
+
@initial = Ward::ValidatorSet.build do |object|
|
29
|
+
object.name.matches(/abc/)
|
30
|
+
object.name.length.is.equal_to(3)
|
31
|
+
end
|
32
|
+
|
33
|
+
@set = Ward::ValidatorSet.build(@initial) do |object|
|
34
|
+
object.name.present
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should add the new validators to a copy of the initial set' do
|
39
|
+
# ValidatorSet doesn't have a size method, but does implement Enumerable
|
40
|
+
@set.inject(0) { |c, *| c += 1 }.should == 3
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should return a copy of the initial set' do
|
44
|
+
@set.should_not == @initial
|
45
|
+
@initial.inject(0) { |c, *| c += 1 }.should == 2
|
46
|
+
end
|
47
|
+
end # when an initial set is provided
|
48
|
+
end # .build
|
49
|
+
|
50
|
+
#
|
51
|
+
# enumeration
|
52
|
+
#
|
53
|
+
|
54
|
+
it 'should be enumerable' do
|
55
|
+
Ward::ValidatorSet.ancestors.should include(Enumerable)
|
56
|
+
end
|
57
|
+
|
58
|
+
it { should have_public_method_defined(:each) }
|
59
|
+
it { should have_public_method_defined(:to_a) }
|
60
|
+
|
61
|
+
#
|
62
|
+
# push
|
63
|
+
#
|
64
|
+
|
65
|
+
it { should have_public_method_defined(:push) }
|
66
|
+
it { should have_public_method_defined(:<<) }
|
67
|
+
|
68
|
+
describe '#push' do
|
69
|
+
it 'should add validator to the set' do
|
70
|
+
set = Ward::ValidatorSet.new
|
71
|
+
new_validator = Ward::Validator.new(nil, nil)
|
72
|
+
set.to_a.should be_empty
|
73
|
+
set.push(new_validator)
|
74
|
+
set.should include(new_validator)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# valid?
|
80
|
+
#
|
81
|
+
|
82
|
+
it { should have_public_method_defined(:valid?) }
|
83
|
+
|
84
|
+
describe '#valid?' do
|
85
|
+
describe 'with two validators, both of which pass' do
|
86
|
+
it 'should return true' do
|
87
|
+
set = Ward::ValidatorSet.build do |object|
|
88
|
+
object.length.is.equal_to(1)
|
89
|
+
object.length.is.present
|
90
|
+
end
|
91
|
+
|
92
|
+
set.valid?('a').should be_true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'with two validators, both of which fail' do
|
97
|
+
before(:each) do
|
98
|
+
@set = Ward::ValidatorSet.build do |object|
|
99
|
+
object.length.is.equal_to(1)
|
100
|
+
object.length.is.equal_to(2)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should return false' do
|
105
|
+
@set.valid?('').should be_false
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should run all the validators' do
|
109
|
+
@set.each do |validator|
|
110
|
+
validator.should_receive(:validate).and_return([false])
|
111
|
+
end
|
112
|
+
|
113
|
+
lambda { @set.valid?('') }.should_not raise_exception
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'with two validators, one of which fails' do
|
118
|
+
before(:each) do
|
119
|
+
@set = Ward::ValidatorSet.build do |object|
|
120
|
+
object.length.is.equal_to(1) # false
|
121
|
+
object.length.is.equal_to(2) # true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should return false' do
|
126
|
+
@set.valid?('ab').should be_false
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should run all the validators' do
|
130
|
+
@set.to_a[0].should_receive(:validate).and_return([false])
|
131
|
+
@set.to_a[1].should_receive(:validate).and_return([true])
|
132
|
+
|
133
|
+
lambda { @set.valid?('ab') }.should_not raise_exception
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end # valid?
|
137
|
+
|
138
|
+
#
|
139
|
+
# merge!
|
140
|
+
#
|
141
|
+
|
142
|
+
it { should have_public_method_defined(:merge!) }
|
143
|
+
|
144
|
+
describe '#merge!' do
|
145
|
+
before(:each) do
|
146
|
+
@set = Ward::ValidatorSet.build do |object|
|
147
|
+
object.length.is.equal_to(1)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should return self' do
|
152
|
+
@set.merge!(Ward::ValidatorSet.new).should == @set
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should add the argument's validators to the receiver" do
|
156
|
+
other = Ward::ValidatorSet.new
|
157
|
+
other << Ward::Validator.new(nil, nil)
|
158
|
+
running = lambda { @set.merge!(other) }
|
159
|
+
|
160
|
+
# select is used here since ValidatorSet doesn't have a size method, but
|
161
|
+
# does implement Enumerable.
|
162
|
+
running.should change { @set.select { |*| true }.size }.by(1)
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should not merge validators already contained in the set' do
|
166
|
+
pending do
|
167
|
+
other = Ward::ValidatorSet.new
|
168
|
+
other << @set.to_a.first.dup
|
169
|
+
running = lambda { @set.merge!(other) }
|
170
|
+
|
171
|
+
# select is used here since ValidatorSet doesn't have a size method, but
|
172
|
+
# does implement Enumerable.
|
173
|
+
running.should_not change { @set.select { |*| true }.size }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Ward::Validator do
|
4
|
+
subject { Ward::Validator }
|
5
|
+
|
6
|
+
#
|
7
|
+
# initialize
|
8
|
+
#
|
9
|
+
|
10
|
+
describe '#initialize' do
|
11
|
+
describe 'scenarios' do
|
12
|
+
it 'should be [:default] when no scenarios option is given' do
|
13
|
+
Ward::Validator.new(nil, nil).scenarios.should == [:default]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should be [:scenario] when the scenarios option is [:scenario]' do
|
17
|
+
validator = Ward::Validator.new(nil, nil, :scenarios => [:scenario])
|
18
|
+
validator.scenarios.should == [:scenario]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be [:scenario] when the scenarios option is :scenario' do
|
22
|
+
validator = Ward::Validator.new(nil, nil, :scenarios => :scenario)
|
23
|
+
validator.scenarios.should == [:scenario]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# context
|
30
|
+
#
|
31
|
+
|
32
|
+
it { should have_public_method_defined(:context) }
|
33
|
+
|
34
|
+
describe '#context' do
|
35
|
+
before(:all) do
|
36
|
+
@context = Ward::Validator.new('context', 'matcher').context
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should return the context' do
|
40
|
+
@context.should == 'context'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# matcher
|
46
|
+
#
|
47
|
+
|
48
|
+
it { should have_public_method_defined(:matcher) }
|
49
|
+
|
50
|
+
describe '#matcher' do
|
51
|
+
before(:all) do
|
52
|
+
@matcher = Ward::Validator.new('context', 'matcher').matcher
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should return the matcher' do
|
56
|
+
@matcher.should == 'matcher'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# validate
|
62
|
+
#
|
63
|
+
|
64
|
+
it { should have_public_method_defined(:validate) }
|
65
|
+
|
66
|
+
describe '#validate' do
|
67
|
+
describe 'when the validator is positive' do
|
68
|
+
before(:all) do
|
69
|
+
@validator = Ward::Validator.new(Ward::Context.new(:name),
|
70
|
+
Ward::Matchers::Nil.new, :negative => false)
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'when the matcher passes' do
|
74
|
+
it 'should return true' do
|
75
|
+
@validator.validate(mock(:name => nil)).should be_true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'when the matcher fails' do
|
80
|
+
before(:all) do
|
81
|
+
@result = @validator.validate(mock(:name => ''))
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should return Array[false, ...]' do
|
85
|
+
@result.first.should be_false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'when the matcher fails and return an error' do
|
90
|
+
before(:all) do
|
91
|
+
@validator.matcher.stub(:matches?).and_return([false, :error])
|
92
|
+
@result = @validator.validate(mock(:name => ''))
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should return Array[false, ...]' do
|
96
|
+
@result.first.should be_false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Rubinius.
|
101
|
+
describe 'when the matcher returns a non-array which responds to #to_a' do
|
102
|
+
before(:all) do
|
103
|
+
@validator.matcher.stub(:matches?).and_return(mock(:to_a => []))
|
104
|
+
@result = @validator.validate(mock(:name => ''))
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should return Array[true, ...]' do
|
108
|
+
@result.first.should be_true
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should return Array[..., nil]' do
|
112
|
+
@result[1].should be_nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end # when the matcher is positive
|
116
|
+
|
117
|
+
describe 'when the validator is negative' do
|
118
|
+
before(:all) do
|
119
|
+
@validator = Ward::Validator.new(Ward::Context.new(:name),
|
120
|
+
Ward::Matchers::Nil.new, :negative => true)
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'when the matcher passes' do
|
124
|
+
it 'should return Array[false, ...]' do
|
125
|
+
@validator.validate(mock(:name => nil)).first.should be_false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'when the matcher fails' do
|
130
|
+
before(:all) do
|
131
|
+
@result = @validator.validate(mock(:name => ''))
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should return Array[true, ...]' do
|
135
|
+
@result.first.should be_true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'when the matcher fails and return an error' do
|
140
|
+
before(:all) do
|
141
|
+
@validator.matcher.stub(:matches?).and_return([false, :error])
|
142
|
+
@result = @validator.validate(mock(:name => ''))
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should return Array[true, ...]' do
|
146
|
+
@result.first.should be_true
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Rubinius.
|
151
|
+
describe 'when the matcher returns a non-array which responds to #to_a' do
|
152
|
+
before(:all) do
|
153
|
+
@validator.matcher.stub(:matches?).and_return(mock(:to_a => []))
|
154
|
+
@result = @validator.validate(mock(:name => ''))
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should return Array[false, ...]' do
|
158
|
+
@result.first.should be_false
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should return Array[..., an_error]' do
|
162
|
+
@result[1].should_not be_nil
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end # when the matcher is negative
|
166
|
+
|
167
|
+
#
|
168
|
+
# argument counts
|
169
|
+
#
|
170
|
+
|
171
|
+
describe 'when matcher #matches? accepts' do
|
172
|
+
describe 'one argument' do
|
173
|
+
it 'should supply the attribute' do
|
174
|
+
value = ''
|
175
|
+
|
176
|
+
Ward::Validator.new(Ward::Context.new(:name),
|
177
|
+
Class.new do
|
178
|
+
def matches?(arg1)
|
179
|
+
arg1.should == ''
|
180
|
+
end
|
181
|
+
end.new
|
182
|
+
).validate(mock(:name => value))
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'two arguments' do
|
187
|
+
it 'should supply the attribute and record' do
|
188
|
+
value = ''
|
189
|
+
record = mock(:name => value)
|
190
|
+
|
191
|
+
Ward::Validator.new(Ward::Context.new(:name),
|
192
|
+
Class.new do
|
193
|
+
include Spec::Matchers
|
194
|
+
def matches?(arg1, arg2)
|
195
|
+
arg1.should == ''
|
196
|
+
arg2.should be_a(Spec::Mocks::Mock)
|
197
|
+
end
|
198
|
+
end.new
|
199
|
+
).validate(record)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end # when matcher #matches? accepts (one|two) arguments?
|
203
|
+
|
204
|
+
end # validate
|
205
|
+
|
206
|
+
#
|
207
|
+
# scenarios
|
208
|
+
#
|
209
|
+
|
210
|
+
it { should have_public_method_defined(:scenarios) }
|
211
|
+
|
212
|
+
describe '#scenarios' do
|
213
|
+
before(:all) do
|
214
|
+
@matcher = Ward::Validator.new('context', 'matcher').scenarios
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should return an array' do
|
218
|
+
@matcher.should be_an(Array)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
#
|
223
|
+
# scenario?
|
224
|
+
#
|
225
|
+
|
226
|
+
it { should have_public_method_defined(:scenario?) }
|
227
|
+
|
228
|
+
describe '#scenario?' do
|
229
|
+
it 'should return true when the validator exists in a given scenario' do
|
230
|
+
validator = Ward::Validator.new(nil, nil, :scenarios => [:update])
|
231
|
+
validator.scenario?(:update).should be_true
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should return true when the validator does not exist in a given scenario' do
|
235
|
+
validator = Ward::Validator.new(nil, nil)
|
236
|
+
validator.scenario?(:update).should be_false
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
#
|
241
|
+
# negative?
|
242
|
+
#
|
243
|
+
|
244
|
+
it { should have_public_method_defined(:negative?) }
|
245
|
+
|
246
|
+
describe 'negative?' do
|
247
|
+
it 'should return true when the validator requires that the matcher ' \
|
248
|
+
'does not match the actual value' do
|
249
|
+
validator = Ward::Validator.new(nil, nil, :negative => true)
|
250
|
+
validator.should be_negative
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should return false when the validator requires that the matcher ' \
|
254
|
+
'matches the actual value' do
|
255
|
+
validator = Ward::Validator.new(nil, nil, :negative => false)
|
256
|
+
validator.should_not be_negative
|
257
|
+
|
258
|
+
validator = Ward::Validator.new(nil, nil)
|
259
|
+
validator.should_not be_negative
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
end
|
data/tasks/features.rake
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
begin
|
2
|
+
require 'cucumber/rake/task'
|
3
|
+
|
4
|
+
Cucumber::Rake::Task.new(:features) do |features|
|
5
|
+
features.cucumber_opts = '--format progress --tag ~@pending'
|
6
|
+
end
|
7
|
+
|
8
|
+
task :features => :check_dependencies
|
9
|
+
|
10
|
+
rescue LoadError
|
11
|
+
task :features do
|
12
|
+
abort "Cucumber is not available. In order to run features, you must: " \
|
13
|
+
"gem install cucumber"
|
14
|
+
end
|
15
|
+
end
|