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,28 @@
1
+ Feature: Include matcher
2
+ In order to validate that a value is one of several permitted
3
+ I want to be able to use the include matcher to set the permitted values
4
+
5
+ # +one_of+ is also available as +included_in+
6
+
7
+ Background:
8
+ Given a class with a 'level' attribute
9
+ And using a validation set like
10
+ """
11
+ object.level.is.one_of([60, 70, 80])
12
+
13
+ """
14
+
15
+ Scenario Outline: When the attribute value matches the expected value
16
+ When the instance 'level' attribute is '<level>'
17
+ Then the validation set should pass
18
+
19
+ Examples:
20
+ | level |
21
+ | 60 |
22
+ | 70 |
23
+ | 80 |
24
+
25
+ Scenario: When the attribute value does not match the expected value
26
+ When the instance 'level' attribute is '61'
27
+ Then the validation set should fail
28
+ And the error on 'level' should be 'Level should be 60, 70, or 80'
@@ -0,0 +1,42 @@
1
+ Feature: Validating objects with an "is" keyword
2
+ In order provide a more natural DSL
3
+ I want to be able to use the is keyword
4
+
5
+ Background:
6
+ Given a class with a 'name' attribute
7
+
8
+ Scenario: With no arguments, a matcher, and a valid value
9
+ When using a validation set like
10
+ """
11
+ object.name.is.equal_to('Samuel L. Chang')
12
+
13
+ """
14
+ And the instance 'name' attribute is 'Samuel L. Chang'
15
+ Then the validation set should pass
16
+
17
+ Scenario: With no arguments, a matcher, and an invalid value
18
+ When using a validation set like
19
+ """
20
+ object.name.is.equal_to('Samuel L. Chang')
21
+
22
+ """
23
+ And the instance 'name' attribute is 'Dwigt'
24
+ Then the validation set should fail
25
+
26
+ Scenario: With an argument and a valid value
27
+ When using a validation set like
28
+ """
29
+ object.name.is('Samuel L. Chang')
30
+
31
+ """
32
+ And the instance 'name' attribute is 'Samuel L. Chang'
33
+ Then the validation set should pass
34
+
35
+ Scenario: With an argument and an invalid value
36
+ When using a validation set like
37
+ """
38
+ object.name.is('Samuel L. Chang')
39
+
40
+ """
41
+ And the instance 'name' attribute is 'Dwigt'
42
+ Then the validation set should fail
@@ -0,0 +1,62 @@
1
+ Feature: Validating objects with an "is_not" or "does_not" keyword
2
+ In order to give users greater control over their validators
3
+ I want be able to use the is_not and does_not keyword to negate what follows
4
+
5
+ Background:
6
+ Given a class with a 'name' attribute
7
+
8
+ Scenario Outline: With no arguments, a matcher, and a valid value
9
+ When using a validation set like
10
+ """
11
+ object.name.<keyword>.equal_to('Samuel L. Chang')
12
+
13
+ """
14
+ And the instance 'name' attribute is 'Samuel L. Chang'
15
+ Then the validation set should fail
16
+
17
+ Examples:
18
+ | keyword |
19
+ | is_not |
20
+ | does_not |
21
+
22
+ Scenario Outline: With no arguments, a matcher, and an invalid value
23
+ When using a validation set like
24
+ """
25
+ object.name.<keyword>.equal_to('Samuel L. Chang')
26
+
27
+ """
28
+ And the instance 'name' attribute is 'Dwigt'
29
+ Then the validation set should pass
30
+
31
+ Examples:
32
+ | keyword |
33
+ | is_not |
34
+ | does_not |
35
+
36
+ Scenario Outline: With an argument and a valid value
37
+ When using a validation set like
38
+ """
39
+ object.name.<keyword>('Samuel L. Chang')
40
+
41
+ """
42
+ And the instance 'name' attribute is 'Samuel L. Chang'
43
+ Then the validation set should fail
44
+
45
+ Examples:
46
+ | keyword |
47
+ | is_not |
48
+ | does_not |
49
+
50
+ Scenario Outline: With an argument and an invalid value
51
+ When using a validation set like
52
+ """
53
+ object.name.<keyword>('Samuel L. Chang')
54
+
55
+ """
56
+ And the instance 'name' attribute is 'Dwigt'
57
+ Then the validation set should pass
58
+
59
+ Examples:
60
+ | keyword |
61
+ | is_not |
62
+ | does_not |
@@ -0,0 +1,49 @@
1
+ Feature: Match matcher
2
+ In order to ensure that a attribute conforms to a certain format
3
+ I want be able to validate attributes against a regular expression
4
+
5
+ Background:
6
+ Given a class with a 'name' attribute
7
+
8
+ Scenario Outline: When the expected value is a regexp and the actual value matches
9
+ When using a validation set like
10
+ """
11
+ object.name.matches(/Michael/)
12
+
13
+ """
14
+ And the instance 'name' attribute is '<value>'
15
+ Then the validation set should pass
16
+
17
+ Examples:
18
+ | value |
19
+ | Michael |
20
+ | Michael Scarn |
21
+
22
+ Scenario: When the expected value is a regexp and the actual value does not match
23
+ When using a validation set like
24
+ """
25
+ object.name.matches(/Michael/)
26
+
27
+ """
28
+ And the instance 'name' attribute is 'Dwigt'
29
+ Then the validation set should fail
30
+ And the error on 'name' should be 'Name format is invalid'
31
+
32
+ Scenario: When the expected value is a String and the actual value matches
33
+ When using a validation set like
34
+ """
35
+ object.name.matches('Michael')
36
+
37
+ """
38
+ And the instance 'name' attribute is 'Michael'
39
+ Then the validation set should pass
40
+
41
+ Scenario: When the expected value is a String and the actual value does not match
42
+ When using a validation set like
43
+ """
44
+ object.name.matches('Michael')
45
+
46
+ """
47
+ And the instance 'name' attribute is 'Dwigt'
48
+ Then the validation set should fail
49
+ And the error on 'name' should be 'Name format is invalid'
@@ -0,0 +1,29 @@
1
+ Feature: Objects which have multiple validators in the same scenario
2
+ In order to allow users to thoroughly test their objects
3
+ I want be able to have multiple validators in the same scenario
4
+
5
+ Background:
6
+ Given a class with a 'name' attribute
7
+ And the class also has a 'job' attribute
8
+ When validating the 'name' attribute
9
+ And validating the 'job' attribute
10
+
11
+ Scenario: When all attributes are valid
12
+ When the instance 'name' attribute is valid
13
+ And the instance 'job' attribute is valid
14
+ Then the validation set should pass
15
+ And there should be no validation errors
16
+
17
+ Scenario: When one attribute is invalid
18
+ When the instance 'name' attribute is invalid
19
+ And the instance 'job' attribute is valid
20
+ Then the validation set should fail
21
+ And there should be 1 validation error on 'name'
22
+ And there should be no validation errors on 'job'
23
+
24
+ Scenario: When both attributes are invalid
25
+ When the instance 'name' attribute is invalid
26
+ And the instance 'job' attribute is invalid
27
+ Then the validation set should fail
28
+ And there should be 1 validation error on 'name'
29
+ And there should be 1 validation error on 'job'
@@ -0,0 +1,25 @@
1
+ Feature: Nil matcher
2
+ In order to validate that an attribute is nil
3
+ I want to be able to use the nil matcher
4
+
5
+ Background:
6
+ Given a class with a 'storage' attribute
7
+ And using a validation set like
8
+ """
9
+ object.storage.is.nil
10
+
11
+ """
12
+
13
+ Scenario: When the attribute value is nil
14
+ When the instance 'storage' attribute is 'nil'
15
+ Then the validation set should pass
16
+
17
+ Scenario: When the attribute value is not nil
18
+ When the instance 'storage' attribute is '500'
19
+ Then the validation set should fail
20
+ And the error on 'storage' should be 'Storage should be nil'
21
+
22
+ Scenario: When the attribute value is false
23
+ When the instance 'storage' attribute is 'false'
24
+ Then the validation set should fail
25
+ And the error on 'storage' should be 'Storage should be nil'
@@ -0,0 +1,23 @@
1
+ Feature: Predicate matcher
2
+ In order to validate objects with predicate methods
3
+ I want to be able to seem to call the predicate in the validation block
4
+
5
+ Background:
6
+ Given a class with a 'important?' attribute
7
+ And using a validation set like
8
+ """
9
+ object.is.important?
10
+
11
+ """
12
+
13
+ Scenario: When the attribute value is true
14
+ When the instance 'important?' attribute is 'true'
15
+ Then the validation set should pass
16
+
17
+ Scenario: When the attribute value is nil
18
+ When the instance 'important?' attribute is 'nil'
19
+ Then the validation set should fail
20
+
21
+ Scenario: When the attribute value is false
22
+ When the instance 'important?' attribute is 'false'
23
+ Then the validation set should fail
@@ -0,0 +1,59 @@
1
+ Feature: Present matcher
2
+ In order to validate that an attribute has a value
3
+ I want to be able to use the present matcher
4
+
5
+ Background:
6
+ Given a class with a 'charisma' attribute
7
+ And using a validation set like
8
+ """
9
+ object.charisma.is.present
10
+
11
+ """
12
+
13
+ Scenario: When the attribute value is nil
14
+ When the instance 'charisma' attribute is 'nil'
15
+ Then the validation set should fail
16
+
17
+ Scenario: When the attribute value is true
18
+ When the instance 'charisma' attribute is 'true'
19
+ Then the validation set should pass
20
+
21
+ Scenario: When the attribute value is false
22
+ When the instance 'charisma' attribute is 'false'
23
+ Then the validation set should fail
24
+
25
+ Scenario: When the attribute value is a Symbol
26
+ When the instance 'charisma' attribute is ':yes'
27
+ Then the validation set should pass
28
+
29
+ Scenario: When the attribute value is a zero
30
+ When the instance 'charisma' attribute is '0'
31
+ Then the validation set should pass
32
+
33
+ Scenario: When the attribute value is a positive number
34
+ When the instance 'charisma' attribute is '1'
35
+ Then the validation set should pass
36
+
37
+ Scenario: When the attribute value is a negative number
38
+ When the instance 'charisma' attribute is '-1'
39
+ Then the validation set should pass
40
+
41
+ Scenario: When the attribute value is a non-empty string
42
+ When the instance 'charisma' attribute is 'Amazing'
43
+ Then the validation set should pass
44
+
45
+ Scenario: When the attribute value is a whitespace-only string
46
+ When the instance 'charisma' attribute is '" \t\r\n"'
47
+ Then the validation set should fail
48
+
49
+ Scenario: When the attribute value is an empty string
50
+ When the instance 'charisma' attribute is ''
51
+ Then the validation set should fail
52
+
53
+ Scenario: When the attribute value responds to #empty and is not empty
54
+ When the instance 'charisma' attribute is '[1]'
55
+ Then the validation set should pass
56
+
57
+ Scenario: When the attribute value responds to #empty and is empty
58
+ When the instance 'charisma' attribute is '[]'
59
+ Then the validation set should fail
@@ -0,0 +1,80 @@
1
+
2
+ Feature: Satisfy matcher
3
+ In order run arbitrary validations on the object
4
+ I want to be able validate that an attribute satisfies a given expression
5
+
6
+ Background:
7
+ Given a class with a 'name' attribute
8
+
9
+ Scenario: Matching with just the attribute value
10
+ When using a validation set like
11
+ """
12
+ object.name.satisfies { |name| name.reverse == 'nracS leahciM' }
13
+ # better: object.name.reverse.is('nracS leahciM')
14
+
15
+ """
16
+ And the instance 'name' attribute is 'Michael Scarn'
17
+ Then the validation set should pass
18
+
19
+ Scenario: Negatively matching with just the attribute value
20
+ When using a validation set like
21
+ """
22
+ object.name.does_not.satisfy { |name| name.reverse == 'nracS leahciM' }
23
+
24
+ """
25
+ And the instance 'name' attribute is 'Michael Scott'
26
+ Then the validation set should pass
27
+
28
+ Scenario: Failing to match with just the attribute value
29
+ When using a validation set like
30
+ """
31
+ object.name.satisfies { |name| name.reverse == 'nracS leahciM' }
32
+
33
+ """
34
+ And the instance 'name' attribute is 'Michael Scott'
35
+ Then the validation set should fail
36
+ And the error on 'name' should be 'Name is invalid'
37
+
38
+ Scenario: Failing to match by returning nil
39
+ When using a validation set like
40
+ """
41
+ object.name.satisfies { |name| nil }
42
+
43
+ """
44
+ And the instance 'name' attribute is 'Michael Scott'
45
+ Then the validation set should fail
46
+ And the error on 'name' should be 'Name is invalid'
47
+
48
+ Scenario: Failing to match and returning a specific error message
49
+ When using a validation set like
50
+ """
51
+ object.name.satisfies do |name|
52
+ [false, "An error"]
53
+ end
54
+
55
+ """
56
+ Then the validation set should fail
57
+ And the error on 'name' should be 'An error'
58
+
59
+ Scenario: Matching with the attribute value and record
60
+ When using a validation set like
61
+ """
62
+ object.name.satisfies do |name, record|
63
+ record.name.reverse == 'nracS leahciM'
64
+ end
65
+
66
+ """
67
+ And the instance 'name' attribute is 'Michael Scarn'
68
+ Then the validation set should pass
69
+
70
+ Scenario: Failing to match with the attribute value and record
71
+ When using a validation set like
72
+ """
73
+ object.name.satisfies do |name, record|
74
+ record.name.reverse == 'nracS leahciM'
75
+ end
76
+
77
+ """
78
+ And the instance 'name' attribute is 'Dwigt'
79
+ Then the validation set should fail
80
+ And the error on 'name' should be 'Name is invalid'
@@ -0,0 +1,81 @@
1
+ Feature: Validating objects in different scenarios
2
+ In order to allow a user to alter the validators for an object
3
+ I want to be able to define validators to run only at certain times
4
+
5
+ Background:
6
+ Given a class with a 'given_name' attribute
7
+ And the class also has a 'family_name' attribute
8
+ When validating the 'given_name' attribute
9
+ And validating the 'family_name' attribute in the 'family' scenario
10
+
11
+ #
12
+ # With no explicit scenario when validating.
13
+ #
14
+
15
+ Scenario: Passing with no explicit scenario when all values are valid
16
+ When the instance 'given_name' attribute is valid
17
+ When the instance 'family_name' attribute is valid
18
+ Then the validation set should pass
19
+
20
+ Scenario: Passing with no explicit scenario when :family scenario values are invalid
21
+ When the instance 'given_name' attribute is valid
22
+ When the instance 'family_name' attribute is invalid
23
+ Then the validation set should pass
24
+
25
+ Scenario: Failing with no explicit scenario when all values are invalid
26
+ When the instance 'given_name' attribute is invalid
27
+ When the instance 'family_name' attribute is invalid
28
+ Then the validation set should fail
29
+
30
+ Scenario: Failing with no explicit scenario when :family scenario values are valid
31
+ When the instance 'given_name' attribute is invalid
32
+ When the instance 'family_name' attribute is valid
33
+ Then the validation set should fail
34
+
35
+ #
36
+ # With an explicit :default scenario when validating.
37
+ #
38
+
39
+ Scenario: Passing when using the :default scenario when all values are valid
40
+ When the instance 'given_name' attribute is valid
41
+ When the instance 'family_name' attribute is valid
42
+ Then the validation set should pass when using the 'default' scenario
43
+
44
+ Scenario: Passing when using :default scenario when :family scenario values are invalid
45
+ When the instance 'given_name' attribute is valid
46
+ When the instance 'family_name' attribute is invalid
47
+ Then the validation set should pass when using the 'default' scenario
48
+
49
+ Scenario: Failing when using :default scenario when all values are invalid
50
+ When the instance 'given_name' attribute is invalid
51
+ When the instance 'family_name' attribute is invalid
52
+ Then the validation set should fail when using the 'default' scenario
53
+
54
+ Scenario: Failing when using :default scenario when :family scenario values are valid
55
+ When the instance 'given_name' attribute is invalid
56
+ When the instance 'family_name' attribute is valid
57
+ Then the validation set should fail when using the 'default' scenario
58
+
59
+ #
60
+ # With an explicit :family scenario when validating.
61
+ #
62
+
63
+ Scenario: Passing when using :family scenario when all values are valid
64
+ When the instance 'given_name' attribute is valid
65
+ When the instance 'family_name' attribute is valid
66
+ Then the validation set should pass when using the 'family' scenario
67
+
68
+ Scenario: Passing when using :family scenario when :default scenario values are invalid
69
+ When the instance 'given_name' attribute is invalid
70
+ When the instance 'family_name' attribute is valid
71
+ Then the validation set should pass when using the 'family' scenario
72
+
73
+ Scenario: Failing when using :family scenario when all values are invalid
74
+ When the instance 'given_name' attribute is invalid
75
+ When the instance 'family_name' attribute is invalid
76
+ Then the validation set should fail when using the 'family' scenario
77
+
78
+ Scenario: Failing when using :family scenario when :default scenario values are valid
79
+ When the instance 'given_name' attribute is valid
80
+ When the instance 'family_name' attribute is invalid
81
+ Then the validation set should fail when using the 'family' scenario