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,25 @@
1
+ Feature: EqualTo matcher
2
+ In order to validate that an exact value
3
+ I want to be able to use the equal_to matcher to set the expected value
4
+
5
+ #
6
+ # The equal_to keyword can often be removed in favour of using +is+ with a
7
+ # value. See is_keyword.feature for examples.
8
+ #
9
+
10
+ Background:
11
+ Given a class with an 'name' attribute
12
+ And using a validation set like
13
+ """
14
+ object.name.is.equal_to('Michael Scarn')
15
+
16
+ """
17
+
18
+ Scenario: When the attribute value matches the expected value
19
+ When the instance 'name' attribute is 'Michael Scarn'
20
+ Then the validation set should pass
21
+
22
+ Scenario: When the attribute value does not match the expected value
23
+ When the instance 'name' attribute is 'Michael Scott'
24
+ Then the validation set should fail
25
+ And the error on 'name' should be 'Name should be Michael Scarn'
@@ -0,0 +1,69 @@
1
+ Feature: Error messages when a validation fails
2
+ In order to provide useful information when a validation fails
3
+ I want to be able to retrieve a list of nicely worded error messages
4
+ So that descriptive messages which describe the errors can be displayed
5
+
6
+ Background:
7
+ Given a class with a 'name' attribute
8
+
9
+ Scenario: When validating an attribute of the object
10
+ When using a validation set like
11
+ """
12
+ object.name.is.present
13
+
14
+ """
15
+ When the instance 'name' attribute is ''
16
+ Then the error on 'name' should be 'Name should be present'
17
+
18
+ Scenario: When validating the object itself
19
+ When using a validation set like
20
+ """
21
+ object.is_not.present
22
+
23
+ """
24
+ Then the error on 'base' should be 'Should not be present'
25
+
26
+ Scenario: Interpolating extra values from the matcher
27
+ When using a validation set like
28
+ """
29
+ object.name.has(1).character
30
+
31
+ """
32
+ When the instance 'name' attribute is ''
33
+ Then the error on 'name' should be 'Name should have 1 character'
34
+
35
+ Scenario: When the matcher indicates a specific error key
36
+ When using a validation set like
37
+ """
38
+ object.name.has.between(1..5).characters
39
+
40
+ """
41
+ When the instance 'name' attribute is ''
42
+ Then the error on 'name' should be 'Name should have between 1 and 5 characters'
43
+
44
+ Scenario: Providing a custom error when the validation is defined
45
+ When using a validation set like
46
+ """
47
+ object.name.is.present.message('Whoops!')
48
+
49
+ """
50
+ When the instance 'name' attribute is ''
51
+ Then the error on 'name' should be 'Whoops!'
52
+
53
+ Scenario: Providing a custom error with interpolation
54
+ When using a validation set like
55
+ """
56
+ object.name.is.present.message('%{context} had a whoopsie')
57
+
58
+ """
59
+ When the instance 'name' attribute is ''
60
+ Then the error on 'name' should be 'Name had a whoopsie'
61
+
62
+ Scenario: Providing a custom name for the context
63
+ When using a validation set like
64
+ """
65
+ object.name.is.present.context('you')
66
+
67
+ """
68
+ When the instance 'name' attribute is ''
69
+ Then the error on 'name' should be 'You should be present'
@@ -0,0 +1,15 @@
1
+ Feature: Validating objects without "include"ing any modules
2
+ In order to reduce the impact on a user's environment
3
+ I want to be able to validate an object which knows nothing about Ward
4
+
5
+ Background:
6
+ Given a class with a 'name' attribute
7
+ When validating the 'name' attribute
8
+
9
+ Scenario: Passing validation
10
+ When the instance 'name' attribute is valid
11
+ Then the validation set should pass
12
+
13
+ Scenario: Failing validation
14
+ When the instance 'name' attribute is invalid
15
+ Then the validation set should fail
@@ -0,0 +1,72 @@
1
+ Feature: Has matcher
2
+ In order to validate the length of a collection
3
+ I want to be able to ensure collections have a certain number of members
4
+
5
+ Background:
6
+ Given a class with a 'posts' attribute
7
+
8
+ Scenario: When validating with a collection name and the correct member size
9
+ When using a validation set like
10
+ """
11
+ object.has(2).posts
12
+
13
+ """
14
+ When the instance 'posts' attribute is '[1, 2]'
15
+ Then the validation set should pass
16
+
17
+ Scenario: When validating with a collection name and an incorrect member size
18
+ When using a validation set like
19
+ """
20
+ object.has(2).posts
21
+
22
+ """
23
+ When the instance 'posts' attribute is '[1]'
24
+ Then the validation set should fail
25
+ And the error on 'base' should be 'Should have 2 posts'
26
+
27
+ Scenario: When validating without a collection name and the correct member size
28
+ When using a validation set like
29
+ """
30
+ object.posts.has(2)
31
+
32
+ """
33
+ When the instance 'posts' attribute is '[1, 2]'
34
+ Then the validation set should pass
35
+
36
+ Scenario: When validating without a collection name and an incorrect member size
37
+ When using a validation set like
38
+ """
39
+ object.posts.has(2)
40
+
41
+ """
42
+ When the instance 'posts' attribute is '[1]'
43
+ Then the validation set should fail
44
+ And the error on 'posts' should be 'Posts should have 2 items'
45
+
46
+ Scenario: When validating without a non-responding collection name and the correct member size
47
+ When using a validation set like
48
+ """
49
+ object.posts.has(2).members
50
+
51
+ """
52
+ When the instance 'posts' attribute is '[1, 2]'
53
+ Then the validation set should pass
54
+
55
+ Scenario: When validating without a non-responding collection name and an incorrect member size
56
+ When using a validation set like
57
+ """
58
+ object.posts.has(2).members
59
+
60
+ """
61
+ When the instance 'posts' attribute is '[1]'
62
+ Then the validation set should fail
63
+ And the error on 'posts' should be 'Posts should have 2 members'
64
+
65
+ Scenario: When using a singular collection name and the value responds to the plural
66
+ When using a validation set like
67
+ """
68
+ object.has(1).post
69
+
70
+ """
71
+ When the instance 'posts' attribute is '[1]'
72
+ Then the validation set should pass
@@ -0,0 +1,94 @@
1
+ Feature: Has matcher when initialized with an expected length
2
+ In order allow the has matcher to read more like a natural language
3
+ I want to be able to initialize the matcher with an expectation
4
+
5
+ Background:
6
+ Given a class with a 'posts' attribute
7
+
8
+ Scenario: Initialized with an exact value and the correct member size
9
+ When using a validation set like
10
+ """
11
+ object.has(2).posts
12
+
13
+ """
14
+ When the instance 'posts' attribute is '[1, 2]'
15
+ Then the validation set should pass
16
+
17
+ Scenario: Initialized with an exact value and an incorrect member size
18
+ When using a validation set like
19
+ """
20
+ object.has(2).posts
21
+
22
+ """
23
+ When the instance 'posts' attribute is '[1]'
24
+ Then the validation set should fail
25
+
26
+ Scenario Outline: Initialized with no value and a member size > 0
27
+ When using a validation set like
28
+ """
29
+ object.has.posts
30
+
31
+ """
32
+ When the instance 'posts' attribute is '<posts>'
33
+ Then the validation set should pass
34
+
35
+ Examples:
36
+ | posts |
37
+ | [1] |
38
+ | [1, 2] |
39
+
40
+ Scenario: Initialized with no value and an incorrect member size
41
+ When using a validation set like
42
+ """
43
+ object.has.posts
44
+
45
+ """
46
+ When the instance 'posts' attribute is '[]'
47
+ Then the validation set should fail
48
+
49
+ Scenario: Initialized with :no and the correct member size
50
+ When using a validation set like
51
+ """
52
+ object.has(:no).posts
53
+
54
+ """
55
+ When the instance 'posts' attribute is '[]'
56
+ Then the validation set should pass
57
+
58
+ Scenario: Initialized with :no and an incorrect member size
59
+ When using a validation set like
60
+ """
61
+ object.has(:no).posts
62
+
63
+ """
64
+ When the instance 'posts' attribute is '[1]'
65
+ Then the validation set should fail
66
+
67
+ Scenario Outline: Initialized with a range and the correct member size
68
+ When using a validation set like
69
+ """
70
+ object.has(2..3).posts
71
+
72
+ """
73
+ When the instance 'posts' attribute is '<posts>'
74
+ Then the validation set should pass
75
+
76
+ Examples:
77
+ | posts |
78
+ | [1, 2] |
79
+ | [1, 2, 3] |
80
+
81
+ Scenario Outline: Initialized with a range and an incorrect member size
82
+ When using a validation set like
83
+ """
84
+ object.has(2..3).posts
85
+
86
+ """
87
+ When the instance 'posts' attribute is '<posts>'
88
+ Then the validation set should fail
89
+
90
+ Examples:
91
+ | posts |
92
+ | [] |
93
+ | [1] |
94
+ | [1, 2, 3, 4] |
@@ -0,0 +1,171 @@
1
+ Feature: Has matcher relativities
2
+ In order to validate collections whose length may vary
3
+ I want to be able to validate that it has a minimum or maximum length
4
+
5
+ Background:
6
+ Given a class with a 'name' attribute
7
+
8
+ #
9
+ # 'exactly' is aliased as 'eql' and can also be omitted completely. See
10
+ # has_matcher_with_initialized_expectation feature for examples.
11
+ #
12
+
13
+ Scenario: Passing validation with exactly
14
+ When using a validation set like
15
+ """
16
+ object.name.has.exactly(5).characters
17
+
18
+ """
19
+ When the instance 'name' attribute is 'Dwigt'
20
+ Then the validation set should pass
21
+ And there should be no validation errors
22
+
23
+ Scenario: Failing validation with exactly
24
+ When using a validation set like
25
+ """
26
+ object.name.has.exactly(5).characters
27
+
28
+ """
29
+ When the instance 'name' attribute is ''
30
+ Then the validation set should fail
31
+ And the error on 'name' should be 'Name should have 5 characters'
32
+
33
+ #
34
+ # 'fewer_than' is aliased as 'lt' and 'less_than'
35
+ #
36
+
37
+ Scenario: Passing validation with lte
38
+ When using a validation set like
39
+ """
40
+ object.name.has.fewer_than(6).characters
41
+
42
+ """
43
+ When the instance 'name' attribute is 'Dwigt'
44
+ Then the validation set should pass
45
+ And there should be no validation errors
46
+
47
+ Scenario: Failing validation with lte
48
+ When using a validation set like
49
+ """
50
+ object.name.has.fewer_than(6).characters
51
+
52
+ """
53
+ When the instance 'name' attribute is 'abcdef'
54
+ Then the validation set should fail
55
+ And the error on 'name' should be 'Name should have at most 5 characters'
56
+
57
+ #
58
+ # 'at_most' is aliased as 'lte'
59
+ #
60
+
61
+ Scenario: Passing validation with lte
62
+ When using a validation set like
63
+ """
64
+ object.name.has.at_most(5).characters
65
+
66
+ """
67
+ When the instance 'name' attribute is 'Dwigt'
68
+ Then the validation set should pass
69
+ And there should be no validation errors
70
+
71
+ Scenario: Failing validation with lte
72
+ When using a validation set like
73
+ """
74
+ object.name.has.at_most(5).characters
75
+
76
+ """
77
+ When the instance 'name' attribute is 'abcdef'
78
+ Then the validation set should fail
79
+ And the error on 'name' should be 'Name should have at most 5 characters'
80
+
81
+ #
82
+ # 'at_least' is aliased as 'gte'
83
+ #
84
+
85
+ Scenario: Passing validation with gte
86
+ When using a validation set like
87
+ """
88
+ object.name.has.at_least(5).characters
89
+
90
+ """
91
+ When the instance 'name' attribute is 'Dwigt'
92
+ Then the validation set should pass
93
+ And there should be no validation errors
94
+
95
+ Scenario: Failing validation with gte
96
+ When using a validation set like
97
+ """
98
+ object.name.has.at_least(5).characters
99
+
100
+ """
101
+ When the instance 'name' attribute is ''
102
+ Then the validation set should fail
103
+ And the error on 'name' should be 'Name should have at least 5 characters'
104
+
105
+ #
106
+ # 'greater_than' is aliased as 'gt' and 'more_than'
107
+ #
108
+
109
+ Scenario: Passing validation with gte
110
+ When using a validation set like
111
+ """
112
+ object.name.has.greater_than(4).characters
113
+
114
+ """
115
+ When the instance 'name' attribute is 'Dwigt'
116
+ Then the validation set should pass
117
+ And there should be no validation errors
118
+
119
+ Scenario: Failing validation with gte
120
+ When using a validation set like
121
+ """
122
+ object.name.has.greater_than(4).characters
123
+
124
+ """
125
+ When the instance 'name' attribute is 'abcd'
126
+ Then the validation set should fail
127
+ And the error on 'name' should be 'Name should have at least 5 characters'
128
+
129
+ #
130
+ # between
131
+ #
132
+
133
+ Scenario: Passing validation with between and a range
134
+ When using a validation set like
135
+ """
136
+ object.name.has.between(2..5).characters
137
+
138
+ """
139
+ When the instance 'name' attribute is 'Dwigt'
140
+ Then the validation set should pass
141
+ And there should be no validation errors
142
+
143
+ Scenario: Failing validation with between two values and a range
144
+ When using a validation set like
145
+ """
146
+ object.name.has.between(2..5).characters
147
+
148
+ """
149
+ When the instance 'name' attribute is ''
150
+ Then the validation set should fail
151
+ And the error on 'name' should be 'Name should have between 2 and 5 characters'
152
+
153
+ Scenario: Passing validation with between and two values
154
+ When using a validation set like
155
+ """
156
+ object.name.has.between(2, 5).characters
157
+
158
+ """
159
+ When the instance 'name' attribute is 'Dwigt'
160
+ Then the validation set should pass
161
+ And there should be no validation errors
162
+
163
+ Scenario: Failing validation with between and two values
164
+ When using a validation set like
165
+ """
166
+ object.name.has.between(2, 5).characters
167
+
168
+ """
169
+ When the instance 'name' attribute is ''
170
+ Then the validation set should fail
171
+ And the error on 'name' should be 'Name should have between 2 and 5 characters'