ward 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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