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.
Files changed (92) hide show
  1. data/.document +5 -0
  2. data/.gitignore +28 -0
  3. data/LICENSE +19 -0
  4. data/README.markdown +99 -0
  5. data/Rakefile +47 -0
  6. data/VERSION +1 -0
  7. data/features/acceptance_matcher.feature +78 -0
  8. data/features/attribute_keyword.feature +13 -0
  9. data/features/close_to_matcher.feature +130 -0
  10. data/features/context_arguments.feature +47 -0
  11. data/features/equal_to_matcher.feature +25 -0
  12. data/features/error_messages.feature +69 -0
  13. data/features/external_validation.feature +15 -0
  14. data/features/has_matcher.feature +72 -0
  15. data/features/has_matcher_initialized_with_expectation.feature +94 -0
  16. data/features/has_matcher_relativities.feature +171 -0
  17. data/features/include_matcher.feature +28 -0
  18. data/features/is_keyword.feature +42 -0
  19. data/features/is_not_keyword.feature +62 -0
  20. data/features/match_matcher.feature +49 -0
  21. data/features/multiple_validators.feature +29 -0
  22. data/features/nil_matcher.feature +25 -0
  23. data/features/predicate_matcher.feature +23 -0
  24. data/features/present_matcher.feature +59 -0
  25. data/features/satisfy_matcher.feature +80 -0
  26. data/features/scenario_validation.feature +81 -0
  27. data/features/step_definitions/external_validation_steps.rb +69 -0
  28. data/features/step_definitions/generic_validation_steps.rb +33 -0
  29. data/features/step_definitions/object_definition_steps.rb +43 -0
  30. data/features/support/env.rb +12 -0
  31. data/features/support/object_builder.rb +33 -0
  32. data/features/support/struct.rb +38 -0
  33. data/lang/en.yml +56 -0
  34. data/lib/ward.rb +26 -0
  35. data/lib/ward/context.rb +70 -0
  36. data/lib/ward/context_chain.rb +87 -0
  37. data/lib/ward/dsl.rb +7 -0
  38. data/lib/ward/dsl/validation_block.rb +73 -0
  39. data/lib/ward/dsl/validation_builder.rb +190 -0
  40. data/lib/ward/errors.rb +213 -0
  41. data/lib/ward/matchers.rb +97 -0
  42. data/lib/ward/matchers/acceptance.rb +43 -0
  43. data/lib/ward/matchers/close_to.rb +60 -0
  44. data/lib/ward/matchers/equal_to.rb +33 -0
  45. data/lib/ward/matchers/has.rb +283 -0
  46. data/lib/ward/matchers/include.rb +54 -0
  47. data/lib/ward/matchers/match.rb +29 -0
  48. data/lib/ward/matchers/matcher.rb +68 -0
  49. data/lib/ward/matchers/nil.rb +30 -0
  50. data/lib/ward/matchers/predicate.rb +31 -0
  51. data/lib/ward/matchers/present.rb +56 -0
  52. data/lib/ward/matchers/satisfy.rb +65 -0
  53. data/lib/ward/spec.rb +17 -0
  54. data/lib/ward/spec/matcher_matcher.rb +114 -0
  55. data/lib/ward/support.rb +7 -0
  56. data/lib/ward/support/basic_object.rb +55 -0
  57. data/lib/ward/support/result.rb +49 -0
  58. data/lib/ward/validator.rb +147 -0
  59. data/lib/ward/validator_set.rb +115 -0
  60. data/lib/ward/version.rb +3 -0
  61. data/spec/lib/has_matcher_relativity_examples.rb +15 -0
  62. data/spec/lib/have_public_method_defined.rb +22 -0
  63. data/spec/rcov.opts +8 -0
  64. data/spec/spec.opts +4 -0
  65. data/spec/spec_helper.rb +19 -0
  66. data/spec/ward/context_chain_spec.rb +178 -0
  67. data/spec/ward/context_spec.rb +57 -0
  68. data/spec/ward/dsl/validation_block_spec.rb +27 -0
  69. data/spec/ward/dsl/validation_builder_spec.rb +212 -0
  70. data/spec/ward/errors_spec.rb +149 -0
  71. data/spec/ward/matchers/acceptance_spec.rb +16 -0
  72. data/spec/ward/matchers/close_to_spec.rb +57 -0
  73. data/spec/ward/matchers/equal_to_spec.rb +16 -0
  74. data/spec/ward/matchers/has_spec.rb +175 -0
  75. data/spec/ward/matchers/include_spec.rb +41 -0
  76. data/spec/ward/matchers/match_spec.rb +21 -0
  77. data/spec/ward/matchers/matcher_spec.rb +54 -0
  78. data/spec/ward/matchers/nil_spec.rb +16 -0
  79. data/spec/ward/matchers/predicate_spec.rb +19 -0
  80. data/spec/ward/matchers/present_spec.rb +16 -0
  81. data/spec/ward/matchers/satisfy_spec.rb +68 -0
  82. data/spec/ward/matchers_spec.rb +51 -0
  83. data/spec/ward/spec/have_public_method_defined_spec.rb +31 -0
  84. data/spec/ward/spec/matcher_matcher_spec.rb +217 -0
  85. data/spec/ward/validator_set_spec.rb +178 -0
  86. data/spec/ward/validator_spec.rb +264 -0
  87. data/tasks/features.rake +15 -0
  88. data/tasks/rcov.rake +24 -0
  89. data/tasks/spec.rake +18 -0
  90. data/tasks/yard.rake +9 -0
  91. data/ward.gemspec +176 -0
  92. 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
@@ -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