json-spec 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +960 -0
  7. data/Rakefile +10 -0
  8. data/api_documentation.md +611 -0
  9. data/cachivache/.gitignore +1 -0
  10. data/cachivache/Gemfile +4 -0
  11. data/cachivache/README.md +247 -0
  12. data/cachivache/Rakefile +19 -0
  13. data/cachivache/Vagrantfile +70 -0
  14. data/cachivache/cachivache.rb +59 -0
  15. data/cachivache/lib/let-behaviour.rb +27 -0
  16. data/cachivache/lib/rake-helper.rb +131 -0
  17. data/cachivache/lib/sh-file-context.rb +39 -0
  18. data/cachivache/lib/sh-if-context.rb +31 -0
  19. data/cachivache/stuff/.gitkeep +0 -0
  20. data/cachivache/stuff/ruby-json-spec.rb +22 -0
  21. data/examples/example-1-simple.rb +66 -0
  22. data/examples/example-2-default-expectations.rb +63 -0
  23. data/examples/example-3-each-field.rb +104 -0
  24. data/examples/example-4-to-be-as-defined-in.rb +117 -0
  25. data/examples/example-5-custom-expectations.rb +153 -0
  26. data/examples/example-6-custom-messages.rb +36 -0
  27. data/examples/example-7-full-example.rb +231 -0
  28. data/examples/fixtures.rb +77 -0
  29. data/examples/validation-printer.rb +47 -0
  30. data/json-spec.gemspec +29 -0
  31. data/lib/cabeza-de-termo/json-spec/errors/error.rb +6 -0
  32. data/lib/cabeza-de-termo/json-spec/errors/expectation-not-found-error.rb +8 -0
  33. data/lib/cabeza-de-termo/json-spec/errors/modifier-not-found-error.rb +8 -0
  34. data/lib/cabeza-de-termo/json-spec/errors/unkown-json-type-error.rb +8 -0
  35. data/lib/cabeza-de-termo/json-spec/errors/validation-error.rb +8 -0
  36. data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectation-builder.rb +29 -0
  37. data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectations-mapping.rb +54 -0
  38. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/block-expectation-definition.rb +16 -0
  39. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/class-expectation-definition.rb +15 -0
  40. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectation-definition.rb +19 -0
  41. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectations-definition-builder.rb +136 -0
  42. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-all-of-expectation-definition.rb +23 -0
  43. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-any-of-expectation-definition.rb +23 -0
  44. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-expectation-definition.rb +17 -0
  45. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/negating-expectation-definition.rb +16 -0
  46. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-library-definition-builder.rb +35 -0
  47. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/class-modifier-definition.rb +15 -0
  48. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/composing-modifiers-definition.rb +28 -0
  49. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifier-definition.rb +13 -0
  50. data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifiers-definition-builder.rb +73 -0
  51. data/lib/cabeza-de-termo/json-spec/expectations-library/expectations-library.rb +150 -0
  52. data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/default-library-initializer.rb +265 -0
  53. data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/library-initializer.rb +9 -0
  54. data/lib/cabeza-de-termo/json-spec/expectations-library/messages/expectation-messages-mapping.rb +27 -0
  55. data/lib/cabeza-de-termo/json-spec/expectations/abstract-expectation.rb +39 -0
  56. data/lib/cabeza-de-termo/json-spec/expectations/all-expectations-composite.rb +33 -0
  57. data/lib/cabeza-de-termo/json-spec/expectations/any-expectation-composite.rb +33 -0
  58. data/lib/cabeza-de-termo/json-spec/expectations/block-expectation.rb +28 -0
  59. data/lib/cabeza-de-termo/json-spec/expectations/expectation.rb +51 -0
  60. data/lib/cabeza-de-termo/json-spec/expectations/is-email-expectation.rb +16 -0
  61. data/lib/cabeza-de-termo/json-spec/expectations/is-scalar-expectation.rb +17 -0
  62. data/lib/cabeza-de-termo/json-spec/expectations/is-url-expectation.rb +21 -0
  63. data/lib/cabeza-de-termo/json-spec/expectations/negated-expectation.rb +31 -0
  64. data/lib/cabeza-de-termo/json-spec/expectations/runner/abstract-expectations-runner.rb +27 -0
  65. data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-absent-expectations-runner.rb +50 -0
  66. data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-null-expectations-runner.rb +48 -0
  67. data/lib/cabeza-de-termo/json-spec/expectations/runner/expectations-runner.rb +43 -0
  68. data/lib/cabeza-de-termo/json-spec/expressions/json-any-of.rb +62 -0
  69. data/lib/cabeza-de-termo/json-spec/expressions/json-anything.rb +16 -0
  70. data/lib/cabeza-de-termo/json-spec/expressions/json-each-field.rb +58 -0
  71. data/lib/cabeza-de-termo/json-spec/expressions/json-each.rb +58 -0
  72. data/lib/cabeza-de-termo/json-spec/expressions/json-expression.rb +314 -0
  73. data/lib/cabeza-de-termo/json-spec/expressions/json-field-name.rb +16 -0
  74. data/lib/cabeza-de-termo/json-spec/expressions/json-field.rb +76 -0
  75. data/lib/cabeza-de-termo/json-spec/expressions/json-list.rb +40 -0
  76. data/lib/cabeza-de-termo/json-spec/expressions/json-object.rb +82 -0
  77. data/lib/cabeza-de-termo/json-spec/expressions/json-scalar.rb +20 -0
  78. data/lib/cabeza-de-termo/json-spec/expressions/json-spec.rb +174 -0
  79. data/lib/cabeza-de-termo/json-spec/instantiators/abstract-instantiator.rb +9 -0
  80. data/lib/cabeza-de-termo/json-spec/instantiators/all-expectations-composite-instantiator.rb +12 -0
  81. data/lib/cabeza-de-termo/json-spec/instantiators/any-expectation-composite-instantiator.rb +12 -0
  82. data/lib/cabeza-de-termo/json-spec/instantiators/block-expectation-instantiator.rb +16 -0
  83. data/lib/cabeza-de-termo/json-spec/instantiators/composite-instantiator.rb +45 -0
  84. data/lib/cabeza-de-termo/json-spec/instantiators/modifier-composite-instantiator.rb +12 -0
  85. data/lib/cabeza-de-termo/json-spec/instantiators/negated-expectation-instantiator.rb +20 -0
  86. data/lib/cabeza-de-termo/json-spec/instantiators/patial-application-instantiator.rb +26 -0
  87. data/lib/cabeza-de-termo/json-spec/json-spec.rb +2 -0
  88. data/lib/cabeza-de-termo/json-spec/message-formatters/block-message-formatter.rb +15 -0
  89. data/lib/cabeza-de-termo/json-spec/message-formatters/erb-message-formatter.rb +60 -0
  90. data/lib/cabeza-de-termo/json-spec/message-formatters/message-formatter.rb +9 -0
  91. data/lib/cabeza-de-termo/json-spec/metaprogramming/message-send.rb +37 -0
  92. data/lib/cabeza-de-termo/json-spec/metaprogramming/message.rb +37 -0
  93. data/lib/cabeza-de-termo/json-spec/metaprogramming/object-method.rb +14 -0
  94. data/lib/cabeza-de-termo/json-spec/modifiers/can-be-absent-modifier.rb +13 -0
  95. data/lib/cabeza-de-termo/json-spec/modifiers/can-be-null-modifier.rb +13 -0
  96. data/lib/cabeza-de-termo/json-spec/modifiers/expression-modifier.rb +9 -0
  97. data/lib/cabeza-de-termo/json-spec/modifiers/modifier-composite.rb +27 -0
  98. data/lib/cabeza-de-termo/json-spec/signals/signal.rb +6 -0
  99. data/lib/cabeza-de-termo/json-spec/signals/skip-branch-signal.rb +8 -0
  100. data/lib/cabeza-de-termo/json-spec/utilities/bind.rb +20 -0
  101. data/lib/cabeza-de-termo/json-spec/utilities/range.rb +70 -0
  102. data/lib/cabeza-de-termo/json-spec/value-holders/accessors-chain.rb +27 -0
  103. data/lib/cabeza-de-termo/json-spec/value-holders/missing-value.rb +21 -0
  104. data/lib/cabeza-de-termo/json-spec/value-holders/value-holder.rb +135 -0
  105. data/lib/cabeza-de-termo/json-spec/version.rb +5 -0
  106. data/lib/cabeza-de-termo/json-spec/walkers/expression-walker.rb +66 -0
  107. data/lib/cabeza-de-termo/json-spec/walkers/json-expectations-runner.rb +214 -0
  108. data/lib/cabeza-de-termo/json-spec/walkers/json-expression-explainer.rb +183 -0
  109. data/lib/cabeza-de-termo/json-spec/walkers/reporter/expectation-report.rb +63 -0
  110. data/lib/cabeza-de-termo/json-spec/walkers/reporter/json-expectations-reporter.rb +111 -0
  111. data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator-error.rb +29 -0
  112. data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator.rb +133 -0
  113. data/lib/cabeza-de-termo/json-spec/walkers/value-holders-stack-behaviour.rb +57 -0
  114. metadata +242 -0
@@ -0,0 +1,16 @@
1
+ require_relative "json-expression"
2
+
3
+ module CabezaDeTermo
4
+ module JsonSpec
5
+ #
6
+ # A JsonExpression representing a field name in a json parse tree.
7
+ #
8
+ class JsonFieldName < JsonExpression
9
+ # Walking expressions
10
+
11
+ def accept_walker(expression_walker)
12
+ expression_walker.walk_json_field_name(self)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,76 @@
1
+ require_relative "json-expression"
2
+
3
+ module CabezaDeTermo
4
+ module JsonSpec
5
+ #
6
+ # A JsonExpression representing an objects field in a json parse tree.
7
+ #
8
+ class JsonField < JsonExpression
9
+ #
10
+ # @param JsonExpression parent_expression The parent expression of self field
11
+ #
12
+ # @param string name The name of the field
13
+ #
14
+ def initialize(parent_expression, name)
15
+ @name = name
16
+ @value_expression = new_anything_expression
17
+
18
+ super(parent_expression)
19
+ end
20
+
21
+ def default_expectations
22
+ default_expectations_for(:fields)
23
+ end
24
+
25
+ # Expectations
26
+
27
+ def to_be(type, &block)
28
+ to_be_a(type, &block)
29
+ end
30
+
31
+ def to_be_an(type, &block)
32
+ to_be_a(type, &block)
33
+ end
34
+
35
+ def to_be_a(type, &block)
36
+ expression = set_value_expression( new_expression_for(type) )
37
+ Bind.evaluation of: block, to: expression unless block.nil?
38
+ expression
39
+ end
40
+
41
+ def add_expectation(expectation)
42
+ value_expression.add_expectation(expectation)
43
+ self
44
+ end
45
+
46
+ def run_modifier(modifier)
47
+ value_expression.run_modifier(modifier)
48
+ end
49
+
50
+ # Accessing
51
+
52
+ def name()
53
+ @name
54
+ end
55
+
56
+ def value_expression()
57
+ @value_expression
58
+ end
59
+
60
+ def set_value_expression(expression)
61
+ expression.set_parent_expression(self)
62
+ @value_expression = expression
63
+
64
+ add_default_expectations
65
+
66
+ expression
67
+ end
68
+
69
+ # Walking expressions
70
+
71
+ def accept_walker(expression_walker)
72
+ expression_walker.walk_json_field(self)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "json-expression"
2
+
3
+ module CabezaDeTermo
4
+ module JsonSpec
5
+ #
6
+ # A JsonExpression representing a list in a json parse tree.
7
+ #
8
+ class JsonList < JsonExpression
9
+ def initialize(parent_expression)
10
+ @each_expression = new_json_each_expression
11
+
12
+ super(parent_expression)
13
+ end
14
+
15
+ def default_expectations()
16
+ default_expectations_for(:lists)
17
+ end
18
+
19
+ # Accessing
20
+
21
+ def each_expression()
22
+ @each_expression
23
+ end
24
+
25
+ # Defining Expectations
26
+
27
+ def each(&block)
28
+ Bind.evaluation of: block, to: each_expression unless block.nil?
29
+
30
+ each_expression
31
+ end
32
+
33
+ # Walking expressions
34
+
35
+ def accept_walker(expression_walker)
36
+ expression_walker.walk_json_list(self)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,82 @@
1
+ require_relative "json-expression"
2
+
3
+ module CabezaDeTermo
4
+ module JsonSpec
5
+ #
6
+ # A JsonExpression representing an object in a json parse tree.
7
+ #
8
+ class JsonObject < JsonExpression
9
+ def initialize(parent_expression)
10
+ super(parent_expression)
11
+
12
+ @fields = []
13
+ @each_field_expression = nil
14
+ end
15
+
16
+ def default_expectations
17
+ default_expectations_for(:objects)
18
+ end
19
+
20
+ # Accessing
21
+
22
+ #
23
+ # Answer the fields of self json object.
24
+ #
25
+ # @return JsonField[]
26
+ #
27
+ def fields()
28
+ @fields
29
+ end
30
+
31
+ #
32
+ # Answer the each_field expression of self object.
33
+ #
34
+ # @return JsonEachField
35
+ #
36
+ def each_field_expression()
37
+ @each_field_expression
38
+ end
39
+
40
+ # Asking
41
+
42
+ #
43
+ # Answer whether self object has a each_field expression defined or no.
44
+ #
45
+ # @return JsonEachField
46
+ #
47
+ def has_each_field?()
48
+ !each_field_expression.nil?
49
+ end
50
+
51
+ # Creating fields
52
+
53
+ def expect(field_name)
54
+ field_expression = new_named_field_expression(field_name)
55
+
56
+ add_field_expression(field_expression)
57
+
58
+ field_expression
59
+ end
60
+
61
+ def each_field(&block)
62
+ @each_field_expression = new_each_field
63
+
64
+ Bind.evaluation of: block, to: @each_field_expression unless block.nil?
65
+
66
+ @each_field_expression
67
+ end
68
+
69
+ def add_field_expression(field_expression)
70
+ fields << field_expression
71
+
72
+ self
73
+ end
74
+
75
+ # Walking expressions
76
+
77
+ def accept_walker(expression_walker)
78
+ expression_walker.walk_json_object(self)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,20 @@
1
+ require_relative "json-expression"
2
+
3
+ module CabezaDeTermo
4
+ module JsonSpec
5
+ #
6
+ # A JsonExpression representing a scalar value in a json parse tree.
7
+ #
8
+ class JsonScalar < JsonExpression
9
+ def default_expectations()
10
+ default_expectations_for(:scalars)
11
+ end
12
+
13
+ # Walking expressions
14
+
15
+ def accept_walker(expression_walker)
16
+ expression_walker.walk_json_scalar(self)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,174 @@
1
+ require 'json'
2
+ require "cabeza-de-termo/json-spec/utilities/bind"
3
+ require "cabeza-de-termo/json-spec/expectations-library/expectations-library"
4
+ require "cabeza-de-termo/json-spec/walkers/validator/json-validator"
5
+
6
+ require_relative "json-any-of"
7
+ require_relative "json-each-field"
8
+ require_relative "json-each"
9
+ require_relative "json-field-name"
10
+ require_relative "json-field"
11
+ require_relative "json-list"
12
+ require_relative "json-object"
13
+ require_relative "json-scalar"
14
+ require_relative "json-anything"
15
+
16
+ module CabezaDeTermo
17
+ module JsonSpec
18
+ #
19
+ # This is the main object to define the expectations on a Json object.
20
+ # A JsonSpec is a tree of Json expressions.
21
+ #
22
+ class JsonSpec
23
+ def initialize(&block)
24
+ @root_expression = nil
25
+ @expectation_messages_mapping = new_expectations_messages_mapping
26
+ @default_expectations = new_default_expectations_mapping
27
+
28
+ Bind.evaluation of: block, to: self unless block.nil?
29
+ end
30
+
31
+ # Accessing
32
+
33
+ def json_spec()
34
+ self
35
+ end
36
+
37
+ def default_expectations()
38
+ @default_expectations
39
+ end
40
+
41
+ def global_expectations_library()
42
+ ExpectationsLibrary.current
43
+ end
44
+
45
+ def root_expression()
46
+ @root_expression
47
+ end
48
+
49
+ # Default expectations
50
+
51
+ def define(&block)
52
+ Bind.evaluation of: block, to: ExpectationLibraryDefinitionBuilder.new(self)
53
+ end
54
+
55
+ # Expectations
56
+
57
+ def expect_an(type, &block)
58
+ expect_a(type, &block)
59
+ end
60
+
61
+ def expect(type, &block)
62
+ expect_a(type, &block)
63
+ end
64
+
65
+ def expect_a(type, &block)
66
+ @root_expression = new_expression_for(type)
67
+
68
+ Bind.evaluation of: block, to: @root_expression unless block.nil?
69
+
70
+ @root_expression
71
+ end
72
+
73
+ def new_expression_for(type)
74
+ return new_object_expression if type == :object
75
+ return new_list_expression if type == :list
76
+ return new_any_of_expression if type == :any_of
77
+
78
+ raise "Invalid expected type: #{type.inspect}"
79
+ end
80
+
81
+ def new_object_expression()
82
+ JsonObject.new(self)
83
+ end
84
+
85
+ def new_list_expression()
86
+ JsonList.new(self)
87
+ end
88
+
89
+ def new_any_of_expression()
90
+ JsonAnyOf.new(self)
91
+ end
92
+
93
+ # Walking expressions
94
+
95
+ def accept_walker(expression_walker)
96
+ expression_walker.walk_json_spec(self)
97
+ end
98
+
99
+ # Helpers
100
+
101
+ def new_expectations_messages_mapping()
102
+ ExpectationMessagesMapping.new
103
+ end
104
+
105
+ def new_default_expectations_mapping()
106
+ DefaultExpectationsMapping.new
107
+ end
108
+
109
+ def new_expression_explainer()
110
+ JsonExpressionExplainer.new
111
+ end
112
+
113
+ def new_validator()
114
+ JsonValidator.new
115
+ end
116
+
117
+ # Expectation messages
118
+
119
+ def message_formatter_for(expectation_method)
120
+ if @expectation_messages_mapping.has_message_formatter_for?(expectation_method)
121
+ return @expectation_messages_mapping.message_formatter_for(expectation_method)
122
+ end
123
+
124
+ global_expectations_library.message_formatter_for(expectation_method)
125
+ end
126
+
127
+ def define_message_formatter_for(expectation_method, message_block)
128
+ @expectation_messages_mapping.define_message_formatter_for(expectation_method, message_block)
129
+ self
130
+ end
131
+
132
+ # Default Expectations
133
+
134
+ def default_expectations_for(json_expression_type)
135
+ messages = []
136
+ messages.concat global_default_expectations_for(json_expression_type)
137
+ messages.concat spec_default_expectations_for(json_expression_type)
138
+
139
+ messages
140
+ end
141
+
142
+ def spec_default_expectations_for(json_expression_type)
143
+ default_expectations.expectations_for(json_expression_type)
144
+ end
145
+
146
+ def global_default_expectations_for(json_expression_type)
147
+ global_expectations_library.default_expectations.expectations_for(json_expression_type)
148
+ end
149
+
150
+ # Validating
151
+
152
+ def parse_json_string(json_string)
153
+ JSON.parse(json_string)
154
+ end
155
+
156
+ def validate_string(json_string)
157
+ validate parse_json_string(json_string)
158
+ end
159
+
160
+ def validate(json)
161
+ validator = new_validator
162
+ validator.validate(self, json)
163
+
164
+ validator
165
+ end
166
+
167
+ # Explaining
168
+
169
+ def explain()
170
+ new_expression_explainer.explain(self)
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,9 @@
1
+ module CabezaDeTermo
2
+ module JsonSpec
3
+ class AbstractInstantiator
4
+ def new(*args)
5
+ raise 'Subclass responsibility'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "composite-instantiator"
2
+ require "cabeza-de-termo/json-spec/expectations/all-expectations-composite"
3
+
4
+ module CabezaDeTermo
5
+ module JsonSpec
6
+ class AllExpectationsCompositeInstantiator < CompositeInstantiator
7
+ def new_composite_expectation()
8
+ AllExpectationsComposite.new
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "composite-instantiator"
2
+ require "cabeza-de-termo/json-spec/expectations/any-expectation-composite"
3
+
4
+ module CabezaDeTermo
5
+ module JsonSpec
6
+ class AnyExpectationCompositeInstantiator < CompositeInstantiator
7
+ def new_composite_expectation()
8
+ AnyExpectationComposite.new
9
+ end
10
+ end
11
+ end
12
+ end