json-spec 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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.gitmodules +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +960 -0
- data/Rakefile +10 -0
- data/api_documentation.md +611 -0
- data/cachivache/.gitignore +1 -0
- data/cachivache/Gemfile +4 -0
- data/cachivache/README.md +247 -0
- data/cachivache/Rakefile +19 -0
- data/cachivache/Vagrantfile +70 -0
- data/cachivache/cachivache.rb +59 -0
- data/cachivache/lib/let-behaviour.rb +27 -0
- data/cachivache/lib/rake-helper.rb +131 -0
- data/cachivache/lib/sh-file-context.rb +39 -0
- data/cachivache/lib/sh-if-context.rb +31 -0
- data/cachivache/stuff/.gitkeep +0 -0
- data/cachivache/stuff/ruby-json-spec.rb +22 -0
- data/examples/example-1-simple.rb +66 -0
- data/examples/example-2-default-expectations.rb +63 -0
- data/examples/example-3-each-field.rb +104 -0
- data/examples/example-4-to-be-as-defined-in.rb +117 -0
- data/examples/example-5-custom-expectations.rb +153 -0
- data/examples/example-6-custom-messages.rb +36 -0
- data/examples/example-7-full-example.rb +231 -0
- data/examples/fixtures.rb +77 -0
- data/examples/validation-printer.rb +47 -0
- data/json-spec.gemspec +29 -0
- data/lib/cabeza-de-termo/json-spec/errors/error.rb +6 -0
- data/lib/cabeza-de-termo/json-spec/errors/expectation-not-found-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/errors/modifier-not-found-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/errors/unkown-json-type-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/errors/validation-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectation-builder.rb +29 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectations-mapping.rb +54 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/block-expectation-definition.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/class-expectation-definition.rb +15 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectation-definition.rb +19 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectations-definition-builder.rb +136 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-all-of-expectation-definition.rb +23 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-any-of-expectation-definition.rb +23 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-expectation-definition.rb +17 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/negating-expectation-definition.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-library-definition-builder.rb +35 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/class-modifier-definition.rb +15 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/composing-modifiers-definition.rb +28 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifier-definition.rb +13 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifiers-definition-builder.rb +73 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/expectations-library.rb +150 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/default-library-initializer.rb +265 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/library-initializer.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/messages/expectation-messages-mapping.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/expectations/abstract-expectation.rb +39 -0
- data/lib/cabeza-de-termo/json-spec/expectations/all-expectations-composite.rb +33 -0
- data/lib/cabeza-de-termo/json-spec/expectations/any-expectation-composite.rb +33 -0
- data/lib/cabeza-de-termo/json-spec/expectations/block-expectation.rb +28 -0
- data/lib/cabeza-de-termo/json-spec/expectations/expectation.rb +51 -0
- data/lib/cabeza-de-termo/json-spec/expectations/is-email-expectation.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expectations/is-scalar-expectation.rb +17 -0
- data/lib/cabeza-de-termo/json-spec/expectations/is-url-expectation.rb +21 -0
- data/lib/cabeza-de-termo/json-spec/expectations/negated-expectation.rb +31 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/abstract-expectations-runner.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-absent-expectations-runner.rb +50 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-null-expectations-runner.rb +48 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/expectations-runner.rb +43 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-any-of.rb +62 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-anything.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-each-field.rb +58 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-each.rb +58 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-expression.rb +314 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-field-name.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-field.rb +76 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-list.rb +40 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-object.rb +82 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-scalar.rb +20 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-spec.rb +174 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/abstract-instantiator.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/all-expectations-composite-instantiator.rb +12 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/any-expectation-composite-instantiator.rb +12 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/block-expectation-instantiator.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/composite-instantiator.rb +45 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/modifier-composite-instantiator.rb +12 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/negated-expectation-instantiator.rb +20 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/patial-application-instantiator.rb +26 -0
- data/lib/cabeza-de-termo/json-spec/json-spec.rb +2 -0
- data/lib/cabeza-de-termo/json-spec/message-formatters/block-message-formatter.rb +15 -0
- data/lib/cabeza-de-termo/json-spec/message-formatters/erb-message-formatter.rb +60 -0
- data/lib/cabeza-de-termo/json-spec/message-formatters/message-formatter.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/metaprogramming/message-send.rb +37 -0
- data/lib/cabeza-de-termo/json-spec/metaprogramming/message.rb +37 -0
- data/lib/cabeza-de-termo/json-spec/metaprogramming/object-method.rb +14 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/can-be-absent-modifier.rb +13 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/can-be-null-modifier.rb +13 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/expression-modifier.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/modifier-composite.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/signals/signal.rb +6 -0
- data/lib/cabeza-de-termo/json-spec/signals/skip-branch-signal.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/utilities/bind.rb +20 -0
- data/lib/cabeza-de-termo/json-spec/utilities/range.rb +70 -0
- data/lib/cabeza-de-termo/json-spec/value-holders/accessors-chain.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/value-holders/missing-value.rb +21 -0
- data/lib/cabeza-de-termo/json-spec/value-holders/value-holder.rb +135 -0
- data/lib/cabeza-de-termo/json-spec/version.rb +5 -0
- data/lib/cabeza-de-termo/json-spec/walkers/expression-walker.rb +66 -0
- data/lib/cabeza-de-termo/json-spec/walkers/json-expectations-runner.rb +214 -0
- data/lib/cabeza-de-termo/json-spec/walkers/json-expression-explainer.rb +183 -0
- data/lib/cabeza-de-termo/json-spec/walkers/reporter/expectation-report.rb +63 -0
- data/lib/cabeza-de-termo/json-spec/walkers/reporter/json-expectations-reporter.rb +111 -0
- data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator-error.rb +29 -0
- data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator.rb +133 -0
- data/lib/cabeza-de-termo/json-spec/walkers/value-holders-stack-behaviour.rb +57 -0
- metadata +242 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
require_relative "expression-walker"
|
|
2
|
+
|
|
3
|
+
module CabezaDeTermo
|
|
4
|
+
module JsonSpec
|
|
5
|
+
class JsonExpressionExplainer < ExpressionWalker
|
|
6
|
+
def initialize()
|
|
7
|
+
reset
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def reset
|
|
11
|
+
@text = ''
|
|
12
|
+
@tabs = 0
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def text
|
|
16
|
+
@text
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def explain(json_walkable)
|
|
20
|
+
reset
|
|
21
|
+
walk_on(json_walkable)
|
|
22
|
+
text
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def walk_on(json_walkable)
|
|
26
|
+
json_walkable.accept_walker(self)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def walk_json_spec(json_spec)
|
|
30
|
+
walk_on(json_spec.root_expression)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def walk_json_object(json_object)
|
|
34
|
+
append_with_tabs('{')
|
|
35
|
+
|
|
36
|
+
during_tab do
|
|
37
|
+
walk_each_defined_field_of(json_object)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if json_object.has_each_field?
|
|
41
|
+
during_tab do
|
|
42
|
+
cr
|
|
43
|
+
walk_on(json_object.each_field_expression)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
append_in_new_line('}')
|
|
48
|
+
|
|
49
|
+
walk_on_expectations_of(json_object)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def walk_each_defined_field_of(json_object)
|
|
53
|
+
json_object.fields.each do |field|
|
|
54
|
+
cr
|
|
55
|
+
walk_on(field)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def walk_json_each_field(json_each_field)
|
|
60
|
+
append_with_tabs('each field')
|
|
61
|
+
|
|
62
|
+
during_tab do
|
|
63
|
+
append_in_new_line('name')
|
|
64
|
+
walk_on( json_each_field.name_expression )
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
during_tab do
|
|
68
|
+
append_in_new_line('value')
|
|
69
|
+
cr
|
|
70
|
+
|
|
71
|
+
during_tab do
|
|
72
|
+
walk_on(json_each_field.value_expression)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def walk_json_field_name(json_field_name)
|
|
78
|
+
walk_on_expectations_of(json_field_name)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def walk_json_list(json_list_expression)
|
|
82
|
+
append_with_tabs('[')
|
|
83
|
+
|
|
84
|
+
walk_on(json_list_expression.each_expression)
|
|
85
|
+
|
|
86
|
+
append_in_new_line(']')
|
|
87
|
+
|
|
88
|
+
walk_on_expectations_of(json_list_expression)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def walk_json_each(json_each_expression)
|
|
92
|
+
return unless json_each_expression.has_each_item_expression?
|
|
93
|
+
|
|
94
|
+
cr
|
|
95
|
+
during_tab do
|
|
96
|
+
walk_on(json_each_expression.each_item_expression)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def walk_json_field(json_field_expression)
|
|
101
|
+
append_with_tabs('"' + json_field_expression.name + '":')
|
|
102
|
+
|
|
103
|
+
during_tab do
|
|
104
|
+
cr
|
|
105
|
+
walk_on(json_field_expression.value_expression)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def walk_json_anything(json_anything)
|
|
110
|
+
append_with_tabs('anything')
|
|
111
|
+
walk_on_expectations_of(json_anything)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def walk_json_scalar(json_scalar)
|
|
115
|
+
append_with_tabs('scalar')
|
|
116
|
+
walk_on_expectations_of(json_scalar)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def walk_json_any_of(any_of)
|
|
120
|
+
append_with_tabs('any of')
|
|
121
|
+
|
|
122
|
+
isFirst = true
|
|
123
|
+
|
|
124
|
+
any_of.possible_expressions.each do |expression|
|
|
125
|
+
append_in_new_line('or') unless isFirst
|
|
126
|
+
|
|
127
|
+
during_tab do
|
|
128
|
+
cr
|
|
129
|
+
walk_on(expression)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
isFirst = false
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def walk_on_expectations_of(expression)
|
|
137
|
+
walk_on(expression.expectations_runner)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def walk_expectation_runner(expectation_runner)
|
|
141
|
+
expectation_runner.explain_with(self)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def walk_expectation(expectation)
|
|
145
|
+
append(' .' + expectation.explain)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Text
|
|
149
|
+
|
|
150
|
+
def append_with_tabs(text)
|
|
151
|
+
append_tabs
|
|
152
|
+
append(text)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def append_in_new_line(text)
|
|
156
|
+
cr
|
|
157
|
+
append_with_tabs(text)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def append_tabs()
|
|
161
|
+
@tabs.times { |i| tab }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def append(text)
|
|
165
|
+
@text += text
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def cr()
|
|
169
|
+
append("\n")
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def tab()
|
|
173
|
+
append("\t")
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def during_tab(&block)
|
|
177
|
+
@tabs += 1
|
|
178
|
+
block.call
|
|
179
|
+
@tabs -= 1
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module CabezaDeTermo
|
|
2
|
+
module JsonSpec
|
|
3
|
+
class ExpectationReport
|
|
4
|
+
def initialize()
|
|
5
|
+
super()
|
|
6
|
+
|
|
7
|
+
@expectation_method = nil
|
|
8
|
+
@failed_message = nil
|
|
9
|
+
@status = nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def set_expectation_method(expectation_method)
|
|
13
|
+
@expectation_method = expectation_method
|
|
14
|
+
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def expectation_method()
|
|
19
|
+
@expectation_method
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def set_failed_message(failed_message)
|
|
23
|
+
@failed_message = failed_message
|
|
24
|
+
|
|
25
|
+
self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def failed_message()
|
|
29
|
+
@failed_message
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def set_status(status)
|
|
33
|
+
@status = status
|
|
34
|
+
|
|
35
|
+
self
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def status()
|
|
39
|
+
@status
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def set_was_satisfied(was_satisfied)
|
|
43
|
+
set_status(was_satisfied ? :was_satisfied : :failed)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def failed?()
|
|
47
|
+
status == :failed
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def was_satisfied?()
|
|
51
|
+
status == :was_satisfied
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_array()
|
|
55
|
+
[
|
|
56
|
+
expectation_method,
|
|
57
|
+
status,
|
|
58
|
+
failed_message
|
|
59
|
+
]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require_relative "../json-expectations-runner"
|
|
2
|
+
require_relative "expectation-report"
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module CabezaDeTermo
|
|
6
|
+
module JsonSpec
|
|
7
|
+
class JsonExpectationsReporter < JsonExpectationsRunner
|
|
8
|
+
def initialize()
|
|
9
|
+
super()
|
|
10
|
+
|
|
11
|
+
@expectation_reports = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run_on_json_string(json_expression, json_string)
|
|
15
|
+
run_on(json_expression, JSON.parse(json_string))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run_on(json_expression, json)
|
|
19
|
+
walk_with_json(json_expression, json)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Accessing
|
|
23
|
+
|
|
24
|
+
def expectation_reports()
|
|
25
|
+
@expectation_reports
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def expectation_reports_as_array()
|
|
29
|
+
arrays = []
|
|
30
|
+
expectation_reports.each do |expectation_report|
|
|
31
|
+
arrays << expectation_report.to_array
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
arrays
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Asking
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Answer true if all the walked Expectations were satisfied.
|
|
41
|
+
#
|
|
42
|
+
def no_errors?()
|
|
43
|
+
expectation_reports.all? { |expectation_report| expectation_report.was_satisfied? }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Instance creation
|
|
47
|
+
|
|
48
|
+
def new_expectation_report()
|
|
49
|
+
ExpectationReport.new
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Logging Expectations reports
|
|
53
|
+
|
|
54
|
+
def log_expectation(expectation, value_holder, was_satisfied)
|
|
55
|
+
expectation_report = new_expectation_report
|
|
56
|
+
.set_expectation_method(expectation.expectation_method)
|
|
57
|
+
.set_was_satisfied(was_satisfied)
|
|
58
|
+
.set_failed_message( expectation.failed_message_on(value_holder) )
|
|
59
|
+
|
|
60
|
+
add_expectation_report(expectation_report)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def log_unwalked_field(field)
|
|
64
|
+
access_chain = @value_holder.accessors_chain.append_accessor(field).to_s
|
|
65
|
+
|
|
66
|
+
expectation_report = new_expectation_report
|
|
67
|
+
.set_expectation_method(:unexpected_field)
|
|
68
|
+
.set_status(:unexpected_field)
|
|
69
|
+
.set_failed_message("Unexpected field '#{access_chain}'.")
|
|
70
|
+
|
|
71
|
+
add_expectation_report(expectation_report)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def add_expectation_report(expectation_report)
|
|
75
|
+
@expectation_reports << expectation_report
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def add_all_expectation_reports(expectation_reports)
|
|
79
|
+
expectation_reports.each do |report|
|
|
80
|
+
add_expectation_report(report)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Hooks
|
|
85
|
+
|
|
86
|
+
def on_unwalked_field(field_name, value_holder)
|
|
87
|
+
log_unwalked_field(field_name)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def on_json_any_of_was_satisfied_with_runner(expectations_runner)
|
|
91
|
+
add_all_expectation_reports(expectations_runner.expectation_reports)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def on_json_any_of_failed_with_all_runners(expectations_runners)
|
|
95
|
+
expectations_runners.each do |each_runner|
|
|
96
|
+
add_all_expectation_reports(each_runner.expectation_reports)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def on_walked_expectation(expectation, value_holder, was_satisfied)
|
|
101
|
+
log_expectation(expectation, value_holder, was_satisfied)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Instance creation
|
|
105
|
+
|
|
106
|
+
def new_json_expectations_runner()
|
|
107
|
+
self.class.new
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module CabezaDeTermo
|
|
2
|
+
module JsonSpec
|
|
3
|
+
class JsonValidatorError
|
|
4
|
+
def initialize(accessors_chain, message)
|
|
5
|
+
@accessors_chain = accessors_chain
|
|
6
|
+
@message = message
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Accessing
|
|
10
|
+
|
|
11
|
+
def message()
|
|
12
|
+
@message
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def accessors_chain()
|
|
16
|
+
@accessors_chain
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Converting
|
|
20
|
+
|
|
21
|
+
def to_hash()
|
|
22
|
+
{
|
|
23
|
+
access_chain: accessors_chain().to_s,
|
|
24
|
+
message: message
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require_relative "json-validator-error"
|
|
2
|
+
require_relative "../json-expectations-runner"
|
|
3
|
+
|
|
4
|
+
module CabezaDeTermo
|
|
5
|
+
module JsonSpec
|
|
6
|
+
class JsonValidator < JsonExpectationsRunner
|
|
7
|
+
def initialize()
|
|
8
|
+
super()
|
|
9
|
+
|
|
10
|
+
@errors = []
|
|
11
|
+
@unexpected_field_errors = []
|
|
12
|
+
@treat_unexpected_fields_as_errors = false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def validate(json_expression, json)
|
|
16
|
+
walk_with_json(json_expression, json)
|
|
17
|
+
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Configuring
|
|
22
|
+
|
|
23
|
+
def treat_unexpected_fields_as_errors(boolean = true)
|
|
24
|
+
@treat_unexpected_fields_as_errors = boolean
|
|
25
|
+
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Asking
|
|
30
|
+
|
|
31
|
+
def no_errors?()
|
|
32
|
+
errors.empty?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def no_unexpected_fields?()
|
|
36
|
+
unexpected_fields.empty?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def has_unexpected_fields?()
|
|
40
|
+
!no_unexpected_fields?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def treat_unexpected_fields_as_errors?()
|
|
44
|
+
@treat_unexpected_fields_as_errors
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Counting
|
|
48
|
+
|
|
49
|
+
def errors_count()
|
|
50
|
+
errors.size
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def unexpected_fields_count()
|
|
54
|
+
unexpected_fields.size
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Accessing
|
|
58
|
+
|
|
59
|
+
def errors()
|
|
60
|
+
@errors
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def unexpected_fields()
|
|
64
|
+
@unexpected_field_errors
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Hooks
|
|
68
|
+
|
|
69
|
+
def on_unwalked_field(field_name, value_holder)
|
|
70
|
+
error = new_validation_error(
|
|
71
|
+
value_holder,
|
|
72
|
+
"An unexpected '#{field_name}' field was found."
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
add_unexpected_field(error)
|
|
76
|
+
|
|
77
|
+
add_error(error) if treat_unexpected_fields_as_errors?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def on_json_any_of_was_satisfied_with_runner(expectations_runner)
|
|
81
|
+
add_all_unexpected_fields(expectations_runner.unexpected_fields)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def on_json_any_of_failed_with_all_runners(expectations_runners)
|
|
85
|
+
expectations_runners.each do |each_expectations_runner|
|
|
86
|
+
add_all_errors(each_expectations_runner.errors)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
expectations_runners.each do |each_expectations_runner|
|
|
90
|
+
add_all_unexpected_fields(each_expectations_runner.unexpected_fields)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def on_walked_expectation(expectation, value_holder, was_satisfied)
|
|
95
|
+
return if was_satisfied
|
|
96
|
+
|
|
97
|
+
add_error( new_validation_error(value_holder, expectation.failed_message_on(value_holder)) )
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Instance creation
|
|
101
|
+
|
|
102
|
+
def new_json_expectations_runner()
|
|
103
|
+
self.class.new
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def new_validation_error(value_holder, message)
|
|
107
|
+
JsonValidatorError.new(value_holder.accessors_chain, message)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Logging
|
|
111
|
+
|
|
112
|
+
def add_error(error)
|
|
113
|
+
@errors << error
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def add_all_errors(errors)
|
|
117
|
+
errors.each do |error|
|
|
118
|
+
add_error(error)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def add_unexpected_field(error)
|
|
123
|
+
@unexpected_field_errors << error
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def add_all_unexpected_fields(errors)
|
|
127
|
+
errors.each do |error|
|
|
128
|
+
add_unexpected_field(error)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|