pacto 0.3.0.pre → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rubocop-todo.yml +0 -27
  4. data/.rubocop.yml +9 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +4 -5
  8. data/CONTRIBUTING.md +112 -0
  9. data/Gemfile +5 -0
  10. data/Guardfile +18 -13
  11. data/README.md +157 -101
  12. data/Rakefile +3 -3
  13. data/features/configuration/strict_matchers.feature +97 -0
  14. data/features/evolve/README.md +11 -0
  15. data/features/evolve/existing_services.feature +82 -0
  16. data/features/generate/README.md +5 -0
  17. data/features/generate/generation.feature +28 -0
  18. data/features/steps/pacto_steps.rb +75 -0
  19. data/features/stub/README.md +2 -0
  20. data/features/stub/templates.feature +46 -0
  21. data/features/support/env.rb +11 -5
  22. data/features/validate/README.md +1 -0
  23. data/features/validate/body_only.feature +85 -0
  24. data/features/{journeys/validation.feature → validate/meta_validation.feature} +41 -24
  25. data/features/validate/validation.feature +36 -0
  26. data/lib/pacto.rb +61 -33
  27. data/lib/pacto/contract.rb +18 -15
  28. data/lib/pacto/contract_factory.rb +14 -11
  29. data/lib/pacto/contract_files.rb +17 -0
  30. data/lib/pacto/contract_list.rb +17 -0
  31. data/lib/pacto/contract_validator.rb +29 -0
  32. data/lib/pacto/core/configuration.rb +19 -17
  33. data/lib/pacto/core/contract_registry.rb +43 -0
  34. data/lib/pacto/core/{callback.rb → hook.rb} +3 -3
  35. data/lib/pacto/core/modes.rb +33 -0
  36. data/lib/pacto/core/validation_registry.rb +45 -0
  37. data/lib/pacto/erb_processor.rb +0 -1
  38. data/lib/pacto/extensions.rb +18 -4
  39. data/lib/pacto/generator.rb +34 -49
  40. data/lib/pacto/generator/filters.rb +41 -0
  41. data/lib/pacto/hooks/erb_hook.rb +4 -3
  42. data/lib/pacto/logger.rb +4 -2
  43. data/lib/pacto/meta_schema.rb +4 -2
  44. data/lib/pacto/rake_task.rb +28 -25
  45. data/lib/pacto/request_clause.rb +43 -0
  46. data/lib/pacto/request_pattern.rb +8 -0
  47. data/lib/pacto/response_clause.rb +15 -0
  48. data/lib/pacto/rspec.rb +102 -0
  49. data/lib/pacto/stubs/uri_pattern.rb +23 -0
  50. data/lib/pacto/stubs/webmock_adapter.rb +69 -0
  51. data/lib/pacto/stubs/webmock_helper.rb +71 -0
  52. data/lib/pacto/ui.rb +7 -0
  53. data/lib/pacto/uri.rb +9 -0
  54. data/lib/pacto/validation.rb +57 -0
  55. data/lib/pacto/validators/body_validator.rb +41 -0
  56. data/lib/pacto/validators/request_body_validator.rb +23 -0
  57. data/lib/pacto/validators/response_body_validator.rb +23 -0
  58. data/lib/pacto/validators/response_header_validator.rb +49 -0
  59. data/lib/pacto/validators/response_status_validator.rb +24 -0
  60. data/lib/pacto/version.rb +1 -1
  61. data/pacto.gemspec +33 -29
  62. data/resources/contract_schema.json +8 -176
  63. data/resources/draft-03.json +174 -0
  64. data/spec/integration/data/strict_contract.json +2 -2
  65. data/spec/integration/e2e_spec.rb +22 -31
  66. data/spec/integration/rspec_spec.rb +94 -0
  67. data/spec/integration/templating_spec.rb +9 -12
  68. data/{lib → spec}/pacto/server.rb +0 -0
  69. data/{lib → spec}/pacto/server/dummy.rb +11 -8
  70. data/{lib → spec}/pacto/server/playback_servlet.rb +1 -1
  71. data/spec/spec_helper.rb +2 -0
  72. data/spec/unit/hooks/erb_hook_spec.rb +15 -15
  73. data/spec/unit/pacto/configuration_spec.rb +2 -10
  74. data/spec/unit/pacto/contract_factory_spec.rb +16 -13
  75. data/spec/unit/pacto/contract_files_spec.rb +42 -0
  76. data/spec/unit/pacto/contract_list_spec.rb +35 -0
  77. data/spec/unit/pacto/contract_spec.rb +43 -44
  78. data/spec/unit/pacto/contract_validator_spec.rb +85 -0
  79. data/spec/unit/pacto/core/configuration_spec.rb +4 -11
  80. data/spec/unit/pacto/core/contract_registry_spec.rb +119 -0
  81. data/spec/unit/pacto/core/modes_spec.rb +18 -0
  82. data/spec/unit/pacto/core/validation_registry_spec.rb +76 -0
  83. data/spec/unit/pacto/core/validation_spec.rb +60 -0
  84. data/spec/unit/pacto/extensions_spec.rb +14 -23
  85. data/spec/unit/pacto/generator/filters_spec.rb +99 -0
  86. data/spec/unit/pacto/generator_spec.rb +34 -73
  87. data/spec/unit/pacto/meta_schema_spec.rb +46 -6
  88. data/spec/unit/pacto/pacto_spec.rb +17 -15
  89. data/spec/unit/pacto/{request_spec.rb → request_clause_spec.rb} +32 -44
  90. data/spec/unit/pacto/request_pattern_spec.rb +22 -0
  91. data/spec/unit/pacto/response_clause_spec.rb +54 -0
  92. data/spec/unit/pacto/stubs/uri_pattern_spec.rb +28 -0
  93. data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +205 -0
  94. data/spec/unit/pacto/stubs/webmock_helper_spec.rb +20 -0
  95. data/spec/unit/pacto/uri_spec.rb +20 -0
  96. data/spec/unit/pacto/validators/body_validator_spec.rb +105 -0
  97. data/spec/unit/pacto/validators/response_header_validator_spec.rb +94 -0
  98. data/spec/unit/pacto/validators/response_status_validator_spec.rb +20 -0
  99. metadata +230 -146
  100. data/features/generation/generation.feature +0 -25
  101. data/lib/pacto/core/contract_repository.rb +0 -44
  102. data/lib/pacto/hash_merge_processor.rb +0 -14
  103. data/lib/pacto/request.rb +0 -57
  104. data/lib/pacto/response.rb +0 -63
  105. data/lib/pacto/response_adapter.rb +0 -24
  106. data/lib/pacto/stubs/built_in.rb +0 -57
  107. data/spec/unit/pacto/core/contract_repository_spec.rb +0 -133
  108. data/spec/unit/pacto/hash_merge_processor_spec.rb +0 -20
  109. data/spec/unit/pacto/response_adapter_spec.rb +0 -25
  110. data/spec/unit/pacto/response_spec.rb +0 -201
  111. data/spec/unit/pacto/stubs/built_in_spec.rb +0 -168
@@ -0,0 +1,23 @@
1
+ module Pacto
2
+ module Validators
3
+ class RequestBodyValidator < BodyValidator
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def self.section_name
9
+ 'request'
10
+ end
11
+
12
+ def call(env)
13
+ if env[:validation_results].empty? # skip body validation if we already have other errors
14
+ expected_body = env[:contract].request.schema
15
+ actual_body = env[:actual_request]
16
+ errors = self.class.validate(expected_body, actual_body)
17
+ env[:validation_results].concat errors.compact
18
+ end
19
+ @app.call env
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Pacto
2
+ module Validators
3
+ class ResponseBodyValidator < BodyValidator
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def self.section_name
9
+ 'response'
10
+ end
11
+
12
+ def call(env)
13
+ if env[:validation_results].empty? # skip body validation if we already have other errors
14
+ expected_body = env[:contract].response.schema
15
+ actual_body = env[:actual_response]
16
+ errors = self.class.validate(expected_body, actual_body)
17
+ env[:validation_results].concat errors.compact
18
+ end
19
+ @app.call env
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ module Pacto
2
+ module Validators
3
+ class ResponseHeaderValidator
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ expected_headers = env[:contract].response.headers
10
+ actual_headers = env[:actual_response].headers
11
+ env[:validation_results].concat self.class.validate(expected_headers, actual_headers)
12
+ @app.call env
13
+ end
14
+
15
+ def self.validate(expected_headers, actual_headers)
16
+ actual_headers = Pacto::Extensions.normalize_header_keys actual_headers
17
+ headers_to_validate = Pacto::Extensions.normalize_header_keys expected_headers
18
+
19
+ headers_to_validate.map do |expected_header, expected_value|
20
+ if actual_headers.key? expected_header
21
+ actual_value = actual_headers[expected_header]
22
+ HeaderValidatorMap[expected_header].call(expected_value, actual_value)
23
+ else
24
+ "Missing expected response header: #{expected_header}"
25
+ end
26
+ end.compact
27
+ end
28
+
29
+ private
30
+
31
+ HeaderValidatorMap = Hash.new do |map, key|
32
+ proc do |expected_value, actual_value|
33
+ unless expected_value.eql? actual_value
34
+ "Invalid response header #{key}: expected #{expected_value.inspect} but received #{actual_value.inspect}"
35
+ end
36
+ end
37
+ end
38
+
39
+ HeaderValidatorMap['Location'] = proc do |expected_value, actual_value|
40
+ location_template = Addressable::Template.new(expected_value)
41
+ if location_template.match(Addressable::URI.parse(actual_value))
42
+ nil
43
+ else
44
+ "Invalid response header Location: expected URI #{actual_value} to match URI Template #{location_template.pattern}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ module Pacto
2
+ module Validators
3
+ class ResponseStatusValidator
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ expected_status = env[:contract].response.status
10
+ actual_status = env[:actual_response].status
11
+ env[:validation_results].concat self.class.validate(expected_status, actual_status)
12
+ @app.call env
13
+ end
14
+
15
+ def self.validate(expected_status, actual_status)
16
+ errors = []
17
+ if expected_status != actual_status
18
+ errors << "Invalid status: expected #{expected_status} but got #{actual_status}"
19
+ end
20
+ errors
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Pacto
2
- VERSION = '0.3.0.pre'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -4,38 +4,42 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'pacto/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = "pacto"
7
+ gem.name = 'pacto'
8
8
  gem.version = Pacto::VERSION
9
- gem.authors = ["ThoughtWorks & Abril"]
10
- gem.email = ["abril_vejasp_dev@thoughtworks.com"]
11
- gem.description = %q{Pacto is a Ruby implementation of the [Consumer-Driven Contracts](http://martinfowler.com/articles/consumerDrivenContracts.html) pattern for evolving services}
12
- gem.summary = %q{Consumer-Driven Contracts implementation}
13
- gem.homepage = 'https://github.com/thoughtworks/pacto'
9
+ gem.authors = ['ThoughtWorks & Abril']
10
+ gem.email = ['pacto-gem@googlegroups.com']
11
+ gem.description = %q{Pacto is a judge that arbitrates contract disputes between a service provider and one or more consumers. In other words, it is a framework for Integration Contract Testing, and helps guide service evolution patterns like Consumer-Driven Contracts or Documentation-Driven Contracts.}
12
+ gem.summary = %q{Integration Contract Testing framework}
13
+ gem.homepage = 'http://thoughtworks.github.io/pacto/'
14
14
  gem.license = 'MIT'
15
15
 
16
- gem.files = `git ls-files`.split($/)
17
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
- gem.require_paths = ["lib"]
16
+ gem.files = `git ls-files`.split($/) # rubocop:disable SpecialGlobalVars
17
+ gem.executables = gem.files.grep(/^bin\//).map { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(/^(test|spec|features)\//)
19
+ gem.require_paths = ['lib']
20
20
 
21
- gem.add_dependency "webmock"
22
- gem.add_dependency "multi_json"
23
- gem.add_dependency "json-schema", "~> 2.0"
24
- gem.add_dependency "json-generator"
25
- gem.add_dependency "hash-deep-merge"
26
- gem.add_dependency "httparty"
27
- gem.add_dependency "addressable"
28
- gem.add_dependency "coveralls"
29
- gem.add_dependency "json-schema-generator"
21
+ gem.add_dependency 'webmock', '~> 1.17'
22
+ gem.add_dependency 'middleware', '~> 0.1'
23
+ gem.add_dependency 'multi_json', '~> 1.8'
24
+ gem.add_dependency 'json-schema', '~> 2.0'
25
+ gem.add_dependency 'json-generator', '>= 0.0.5'
26
+ gem.add_dependency 'hash-deep-merge', '~> 0.1'
27
+ gem.add_dependency 'faraday', '~> 0.9'
28
+ gem.add_dependency 'addressable', '~> 2.3'
29
+ gem.add_dependency 'json-schema-generator', '>= 0.0.7'
30
+ gem.add_dependency 'term-ansicolor', '~> 1.3'
30
31
 
31
- gem.add_development_dependency "rake"
32
- gem.add_development_dependency "rspec"
33
- gem.add_development_dependency "should_not"
34
- gem.add_development_dependency "aruba"
35
- gem.add_development_dependency "guard-rspec"
36
- gem.add_development_dependency "rubocop"
37
- gem.add_development_dependency "guard-rubocop"
38
- gem.add_development_dependency "guard-cucumber"
39
- gem.add_development_dependency "rb-fsevent" if RUBY_PLATFORM =~ /darwin/i
40
- gem.add_development_dependency "terminal-notifier-guard" if RUBY_PLATFORM =~ /darwin/i
32
+ gem.add_development_dependency 'coveralls'
33
+ gem.add_development_dependency 'rake'
34
+ gem.add_development_dependency 'rake-notes'
35
+ gem.add_development_dependency 'rspec', '~> 2.14'
36
+ gem.add_development_dependency 'should_not'
37
+ gem.add_development_dependency 'aruba'
38
+ gem.add_development_dependency 'relish'
39
+ gem.add_development_dependency 'guard-rspec'
40
+ gem.add_development_dependency 'rubocop', '~> 0.16.0'
41
+ gem.add_development_dependency 'guard-rubocop'
42
+ gem.add_development_dependency 'guard-cucumber'
43
+ gem.add_development_dependency 'rb-fsevent' if RUBY_PLATFORM =~ /darwin/i
44
+ gem.add_development_dependency 'terminal-notifier-guard' if RUBY_PLATFORM =~ /darwin/i
41
45
  end
@@ -2,6 +2,10 @@
2
2
  "title": "Example Schema",
3
3
  "type": "object",
4
4
  "properties": {
5
+ "name": {
6
+ "type": "string",
7
+ "required": false
8
+ },
5
9
  "request": {
6
10
  "type": "object",
7
11
  "required": true,
@@ -21,6 +25,9 @@
21
25
  "params": {
22
26
  "type": "object",
23
27
  "required": false
28
+ },
29
+ "body": {
30
+ "$ref": "http://json-schema.org/draft-03/schema#"
24
31
  }
25
32
  }
26
33
  },
@@ -36,181 +43,6 @@
36
43
  "$ref": "http://json-schema.org/draft-03/schema#"
37
44
  }
38
45
  }
39
- },
40
- "json-schema": {
41
- "_comment": "this should be refactored to not need the whole schema here",
42
- "$schema": "http://json-schema.org/draft-03/schema#",
43
- "id": "http://json-schema.org/draft-03/schema#",
44
- "type": "object",
45
-
46
- "properties": {
47
- "type": {
48
- "type": [ "string", "array" ],
49
- "items": {
50
- "type": [ "string", { "$ref": "#" } ]
51
- },
52
- "uniqueItems": true,
53
- "default": "any"
54
- },
55
-
56
- "properties": {
57
- "type": "object",
58
- "additionalProperties": { "$ref": "#" },
59
- "default": {}
60
- },
61
-
62
- "patternProperties": {
63
- "type": "object",
64
- "additionalProperties": { "$ref": "#" },
65
- "default": {}
66
- },
67
-
68
- "additionalProperties": {
69
- "type": [ { "$ref": "#" }, "boolean" ],
70
- "default": {}
71
- },
72
-
73
- "items": {
74
- "type": [ { "$ref": "#" }, "array" ],
75
- "items": { "$ref": "#" },
76
- "default": {}
77
- },
78
-
79
- "additionalItems": {
80
- "type": [ { "$ref": "#" }, "boolean" ],
81
- "default": {}
82
- },
83
-
84
- "required": {
85
- "type": "boolean",
86
- "default": false
87
- },
88
-
89
- "dependencies": {
90
- "type": "object",
91
- "additionalProperties": {
92
- "type": [ "string", "array", { "$ref": "#" } ],
93
- "items": {
94
- "type": "string"
95
- }
96
- },
97
- "default": {}
98
- },
99
-
100
- "minimum": {
101
- "type": "number"
102
- },
103
-
104
- "maximum": {
105
- "type": "number"
106
- },
107
-
108
- "exclusiveMinimum": {
109
- "type": "boolean",
110
- "default": false
111
- },
112
-
113
- "exclusiveMaximum": {
114
- "type": "boolean",
115
- "default": false
116
- },
117
-
118
- "minItems": {
119
- "type": "integer",
120
- "minimum": 0,
121
- "default": 0
122
- },
123
-
124
- "maxItems": {
125
- "type": "integer",
126
- "minimum": 0
127
- },
128
-
129
- "uniqueItems": {
130
- "type": "boolean",
131
- "default": false
132
- },
133
-
134
- "pattern": {
135
- "type": "string",
136
- "format": "regex"
137
- },
138
-
139
- "minLength": {
140
- "type": "integer",
141
- "minimum": 0,
142
- "default": 0
143
- },
144
-
145
- "maxLength": {
146
- "type": "integer"
147
- },
148
-
149
- "enum": {
150
- "type": "array",
151
- "minItems": 1,
152
- "uniqueItems": true
153
- },
154
-
155
- "default": {
156
- "type": "any"
157
- },
158
-
159
- "title": {
160
- "type": "string"
161
- },
162
-
163
- "description": {
164
- "type": "string"
165
- },
166
-
167
- "format": {
168
- "type": "string"
169
- },
170
-
171
- "divisibleBy": {
172
- "type": "number",
173
- "minimum": 0,
174
- "exclusiveMinimum": true,
175
- "default": 1
176
- },
177
-
178
- "disallow": {
179
- "type": [ "string", "array" ],
180
- "items": {
181
- "type": [ "string", { "$ref": "#" } ]
182
- },
183
- "uniqueItems": true
184
- },
185
-
186
- "extends": {
187
- "type": [ { "$ref": "#" }, "array" ],
188
- "items": { "$ref": "#" },
189
- "default": {}
190
- },
191
-
192
- "id": {
193
- "type": "string",
194
- "format": "uri"
195
- },
196
-
197
- "$ref": {
198
- "type": "string",
199
- "format": "uri"
200
- },
201
-
202
- "$schema": {
203
- "type": "string",
204
- "format": "uri"
205
- }
206
- },
207
-
208
- "dependencies": {
209
- "exclusiveMinimum": "minimum",
210
- "exclusiveMaximum": "maximum"
211
- },
212
-
213
- "default": {}
214
- }
46
+ }
215
47
  }
216
48
  }
@@ -0,0 +1,174 @@
1
+ {
2
+ "$schema" : "http://json-schema.org/draft-03/schema#",
3
+ "id" : "http://json-schema.org/draft-03/schema#",
4
+ "type" : "object",
5
+
6
+ "properties" : {
7
+ "type" : {
8
+ "type" : ["string", "array"],
9
+ "items" : {
10
+ "type" : ["string", {"$ref" : "#"}]
11
+ },
12
+ "uniqueItems" : true,
13
+ "default" : "any"
14
+ },
15
+
16
+ "properties" : {
17
+ "type" : "object",
18
+ "additionalProperties" : {"$ref" : "#"},
19
+ "default" : {}
20
+ },
21
+
22
+ "patternProperties" : {
23
+ "type" : "object",
24
+ "additionalProperties" : {"$ref" : "#"},
25
+ "default" : {}
26
+ },
27
+
28
+ "additionalProperties" : {
29
+ "type" : [{"$ref" : "#"}, "boolean"],
30
+ "default" : {}
31
+ },
32
+
33
+ "items" : {
34
+ "type" : [{"$ref" : "#"}, "array"],
35
+ "items" : {"$ref" : "#"},
36
+ "default" : {}
37
+ },
38
+
39
+ "additionalItems" : {
40
+ "type" : [{"$ref" : "#"}, "boolean"],
41
+ "default" : {}
42
+ },
43
+
44
+ "required" : {
45
+ "type" : "boolean",
46
+ "default" : false
47
+ },
48
+
49
+ "dependencies" : {
50
+ "type" : "object",
51
+ "additionalProperties" : {
52
+ "type" : ["string", "array", {"$ref" : "#"}],
53
+ "items" : {
54
+ "type" : "string"
55
+ }
56
+ },
57
+ "default" : {}
58
+ },
59
+
60
+ "minimum" : {
61
+ "type" : "number"
62
+ },
63
+
64
+ "maximum" : {
65
+ "type" : "number"
66
+ },
67
+
68
+ "exclusiveMinimum" : {
69
+ "type" : "boolean",
70
+ "default" : false
71
+ },
72
+
73
+ "exclusiveMaximum" : {
74
+ "type" : "boolean",
75
+ "default" : false
76
+ },
77
+
78
+ "minItems" : {
79
+ "type" : "integer",
80
+ "minimum" : 0,
81
+ "default" : 0
82
+ },
83
+
84
+ "maxItems" : {
85
+ "type" : "integer",
86
+ "minimum" : 0
87
+ },
88
+
89
+ "uniqueItems" : {
90
+ "type" : "boolean",
91
+ "default" : false
92
+ },
93
+
94
+ "pattern" : {
95
+ "type" : "string",
96
+ "format" : "regex"
97
+ },
98
+
99
+ "minLength" : {
100
+ "type" : "integer",
101
+ "minimum" : 0,
102
+ "default" : 0
103
+ },
104
+
105
+ "maxLength" : {
106
+ "type" : "integer"
107
+ },
108
+
109
+ "enum" : {
110
+ "type" : "array",
111
+ "minItems" : 1,
112
+ "uniqueItems" : true
113
+ },
114
+
115
+ "default" : {
116
+ "type" : "any"
117
+ },
118
+
119
+ "title" : {
120
+ "type" : "string"
121
+ },
122
+
123
+ "description" : {
124
+ "type" : "string"
125
+ },
126
+
127
+ "format" : {
128
+ "type" : "string"
129
+ },
130
+
131
+ "divisibleBy" : {
132
+ "type" : "number",
133
+ "minimum" : 0,
134
+ "exclusiveMinimum" : true,
135
+ "default" : 1
136
+ },
137
+
138
+ "disallow" : {
139
+ "type" : ["string", "array"],
140
+ "items" : {
141
+ "type" : ["string", {"$ref" : "#"}]
142
+ },
143
+ "uniqueItems" : true
144
+ },
145
+
146
+ "extends" : {
147
+ "type" : [{"$ref" : "#"}, "array"],
148
+ "items" : {"$ref" : "#"},
149
+ "default" : {}
150
+ },
151
+
152
+ "id" : {
153
+ "type" : "string",
154
+ "format" : "uri"
155
+ },
156
+
157
+ "$ref" : {
158
+ "type" : "string",
159
+ "format" : "uri"
160
+ },
161
+
162
+ "$schema" : {
163
+ "type" : "string",
164
+ "format" : "uri"
165
+ }
166
+ },
167
+
168
+ "dependencies" : {
169
+ "exclusiveMinimum" : "minimum",
170
+ "exclusiveMaximum" : "maximum"
171
+ },
172
+
173
+ "default" : {}
174
+ }