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.
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