easy_json_matcher 0.0.2.pre.1 → 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.
@@ -1,8 +1,9 @@
1
1
  require 'test_helper'
2
2
  require 'json'
3
3
 
4
-
5
- class JsonapiMatcherTest < ActiveSupport::TestCase
4
+ # This test suite covers the basic concept of validating that a value is a
5
+ # certain type
6
+ class EasyJSONMatcherTest < ActiveSupport::TestCase
6
7
 
7
8
  test "As a user I want to create new Schemas to match JSON objects" do
8
9
  # This test represents the minimum level of implementation required to create a
@@ -11,7 +12,7 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
11
12
  schema.contains_node(key: :data) do |node|
12
13
  node.has_attribute(key: :title, opts: {type: :string})
13
14
  end
14
- }.register(schema_name: :test)
15
+ }.register(as: :test)
15
16
 
16
17
  valid_json = {
17
18
  data: {
@@ -21,12 +22,46 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
21
22
  assert(test_schema.valid? valid_json)
22
23
  end
23
24
 
25
+ # The first thing the gem ought to do is to check that the JSON candidate is actually JSON
26
+ test "As a user, if the validation candidate cannot be parsed as JSON, the schema should not be valid" do
27
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|s|
28
+ s.has_number(key: :population_of_china_1970)
29
+ }.generate_schema
30
+
31
+ invalid_json = "'population_of_china_1970' 810000000"
32
+
33
+ assert_not(test_schema.valid? invalid_json)
34
+ end
35
+
36
+
37
+ test "As a user I want to be able to validate strings" do
38
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|schema|
39
+ schema.has_string(key: :string, opts: { required: :true})
40
+ }.generate_schema
41
+
42
+ valid_json = {
43
+ string: "Mrs Mogs Hamilton"
44
+ }.to_json
45
+
46
+ assert(test_schema.valid?(valid_json), 'String was not validated')
47
+
48
+ # There isn't really a clear case for the string validator picking up if a
49
+ # value is not intended to be a string since all json values are effectively
50
+ # strings, and how is the library to know if the client meant 16 to be passed
51
+ # as a number or as a string?
52
+ # invalid_json = {
53
+ # string: 16
54
+ # }.to_json
55
+ #
56
+ # assert_not(test_schema.valid?(invalid_json), 'Number was validated as a string')
57
+ end
58
+
24
59
 
25
60
  test "As a user I want to be able to validate numbers" do
26
61
 
27
62
  test_schema = EasyJSONMatcher::SchemaGenerator.new {|schema|
28
- schema.has_attribute(key: :number, opts: {type: :number, required: :true})
29
- }.generate_node
63
+ schema.has_number(key: :number, opts: {required: :true})
64
+ }.generate_schema
30
65
 
31
66
  valid_json = {
32
67
  number: 5.55,
@@ -48,9 +83,9 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
48
83
  test "As a user I want to be able to validate booleans" do
49
84
 
50
85
  test_schema = EasyJSONMatcher::SchemaGenerator.new {|schema|
51
- schema.has_attribute(key: :true, opts: {type: :boolean})
52
- schema.has_attribute(key: :false, opts: {type: :boolean})
53
- }.generate_node
86
+ schema.has_boolean(key: :true)
87
+ schema.has_boolean(key: :false)
88
+ }.generate_schema
54
89
 
55
90
  valid_json = {
56
91
  true: true,
@@ -71,7 +106,7 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
71
106
  test "As a user I want to be able to validate Array values" do
72
107
  test_schema = EasyJSONMatcher::SchemaGenerator.new {|schema|
73
108
  schema.has_attribute(key: :array, opts: {type: :array})
74
- }.generate_node
109
+ }.generate_schema
75
110
 
76
111
  valid_json = {
77
112
  array: []
@@ -88,8 +123,8 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
88
123
 
89
124
  test "As a user I want to be able to validate date values" do
90
125
  test_schema = EasyJSONMatcher::SchemaGenerator.new { |schema|
91
- schema.has_attribute(key: :date, opts: {type: :date})
92
- }.generate_node
126
+ schema.has_date(key: :date)
127
+ }.generate_schema
93
128
 
94
129
  valid_json = {
95
130
  date: "2015-01-15"
@@ -111,8 +146,8 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
111
146
 
112
147
  test "As a user I want to validate object values" do
113
148
  test_schema = EasyJSONMatcher::SchemaGenerator.new { |schema|
114
- schema.has_attribute(key: :object, opts: {type: :object})
115
- }.generate_node
149
+ schema.has_object(key: :object)
150
+ }.generate_schema
116
151
 
117
152
  is_an_object = {}
118
153
 
@@ -133,24 +168,21 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
133
168
 
134
169
  # Refers to validation of a JSON value attribute. This one is slightly tricky
135
170
  # though since attempting to access a Ruby Hash with a missing key will return
136
- # nil. The ValueValidator (or indeed any Validator) will accept nil as a value.
137
- # However, if in future we want to implement the :required option then in the
138
- # case of ValueValidator we will be stuck because for all of the other Validator
139
- # classes nil indicates a missing value, but in the case of the ValueValidator
140
- # we just want to check that there is a key available. It makes sense, therefore,
141
- # to reverse the dependency such that the Node instance is passed to the Validator
142
- # with its key and it then tests for the presence of the attribute and what it
143
- # whether or not it is available
171
+ # nil. The ValueValidator (or indeed any Validator) will accept nil as a value
172
+ # when the value is not marked as required.
173
+ # ValueValidator we will be stuck because although the other Validator
174
+ # classes nil indicates a missing value, in the case of the ValueValidator null is
175
+ # a valid value and we just want to check that there is a key available.
144
176
  test "As a user I want to validate json value attributes" do
145
177
  test_schema = EasyJSONMatcher::SchemaGenerator.new {|schema|
146
- schema.has_attribute(key: :array, opts: {type: :value})
147
- schema.has_attribute(key: :boolean, opts: {type: :value})
148
- schema.has_attribute(key: :date, opts: {type: :value})
149
- schema.has_attribute(key: :number, opts: {type: :value})
150
- schema.has_attribute(key: :object, opts: {type: :value})
151
- schema.has_attribute(key: :string, opts: {type: :value})
152
- schema.has_attribute(key: :null, opts: {type: :value})
153
- }.generate_node
178
+ schema.has_value(key: :array)
179
+ schema.has_value(key: :boolean)
180
+ schema.has_value(key: :date)
181
+ schema.has_value(key: :number)
182
+ schema.has_value(key: :object)
183
+ schema.has_value(key: :string)
184
+ schema.has_value(key: :null)
185
+ }.generate_schema
154
186
 
155
187
 
156
188
  valid_json = {
@@ -179,7 +211,7 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
179
211
  n3.has_attribute(key: :level_3_attribute, opts: {type: :number})
180
212
  end
181
213
  end
182
- }.generate_node
214
+ }.generate_schema
183
215
 
184
216
  valid_json = {
185
217
  level_1_attribute: 1,
@@ -194,30 +226,37 @@ class JsonapiMatcherTest < ActiveSupport::TestCase
194
226
  assert(test_schema.valid?(valid_json), "Nested JSON was not correctly validated")
195
227
  end
196
228
 
197
- test "As a user I want to know why my json was not valid" do
198
-
199
- class Validator
200
- def valid?(json)
201
- raise EasyJSONMatcher::ValidationError.new ("Oops!!")
202
- end
203
- end
204
-
205
- test_schema = EasyJSONMatcher::SchemaGenerator.new { |schema|
206
- schema.has_attribute(key: :oops, opts: {type: :value})
207
- schema.contains_node(key: :nested_oops) do |node|
208
- node.has_attribute(key: :bigger_oops, opts: {type: :value})
229
+ test "As a user, if I specify a node and the content is not a node, it should be invalid without raising an error" do
230
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|schema|
231
+ schema.has_attribute(key: :fish_name, opts: {type: :string, required: :true})
232
+ schema.contains_node(key: :scientific_name) do |n|
233
+ n.has_attribute(key: :genus, opts: {type: :string, required: :true})
234
+ n.has_attribute(key: :species, opts: {type: :string, required: :true})
209
235
  end
210
- }.generate_node
236
+ }.generate_schema
211
237
 
212
- # This JSON only reflects the structure of the above, it's validity is rendered
213
- # irrelevant by our monkey-patch of Validator
214
238
  valid_json = {
215
- oops: 'oops',
216
- nested_oops: {
217
- bigger_oops: 'bigger_oops'
239
+ fish_name: 'Clownfish',
240
+ scientific_name: {
241
+ genus: 'Amphiprion',
242
+ species: 'ocellaris'
218
243
  }
219
- }
220
- flunk "Implement me"
244
+ }.to_json
245
+
246
+ assert(test_schema.valid?(valid_json), "#{valid_json} should have been valid")
247
+
248
+ invalid_with_array = {
249
+ fish_name: 'Green Mandarin',
250
+ scientific_name: ['Synchiropus', 'splendidus']
251
+ }.to_json
252
+
253
+ assert_not(test_schema.valid?(invalid_with_array), "#{invalid_with_array} should not have been valid as it has an array instead of a node")
254
+
255
+ invalid_with_primitive = {
256
+ fish_name: 'Hawaiian Tang',
257
+ scientific_name: 'Zebrasoma flavescens'
258
+ }.to_json
221
259
 
260
+ assert_not(test_schema.valid?(invalid_with_primitive), "#{invalid_with_primitive} shoudl not have been valid as it has a primite instead of a node")
222
261
  end
223
262
  end
@@ -0,0 +1,148 @@
1
+ require 'test_helper'
2
+
3
+ class ErrorMessagesTest < ActiveSupport::TestCase
4
+
5
+ test "As a user I want to know why my json was not valid" do
6
+
7
+ test_schema = EasyJSONMatcher::SchemaGenerator.new { |schema|
8
+ schema.has_string key: :oops
9
+ schema.has_value key: :ok
10
+ schema.contains_node(key: :nested_oops) do |node|
11
+ node.has_value key: :ok
12
+ node.has_string key: :bigger_oops
13
+ end
14
+ }.generate_schema
15
+
16
+ has_errors = {
17
+ oops: 1,
18
+ ok: 'ok',
19
+ nested_oops: {
20
+ ok: 'ok',
21
+ bigger_oops: 2
22
+ }
23
+ }.to_json
24
+
25
+ # The resulting error object should show an error for oops, and an error in the
26
+ # :nested_oops object for :bigger_oops. It should not show any errors for either
27
+ # of the :oks.
28
+
29
+ # Generate error messages. Better test that the thing is definitely invalid too...
30
+ assert_not(test_schema.valid? has_errors)
31
+
32
+ assert_match(/.*is not a String/, test_schema.get_errors[:oops][0])
33
+ assert_match( /.*is not a String/, test_schema.get_errors[:nested_oops][:bigger_oops][0])
34
+ end
35
+
36
+ test "As a user, given that I have specified that an array should be mapped to a key and that the actual value
37
+ is not an array, I want to know that the value is not an array" do
38
+
39
+ test_schema = EasyJSONMatcher::SchemaGenerator.new do |s|
40
+ s.contains_array(key: :arr)
41
+ end.generate_schema
42
+
43
+ wrong_type = {
44
+ arr: "This not an array"
45
+ }.to_json
46
+
47
+ #As above just check that the validator is actually behaving itself
48
+ assert_not(test_schema.valid? wrong_type)
49
+
50
+ assert_match(/.*is not an Array/, test_schema.get_errors[:arr][0])
51
+ end
52
+
53
+ test "As a user, given that I have specified that an array should contain a specific
54
+ type of value and the array contains other types of value, I want to know which
55
+ value was the wrong type and why" do
56
+
57
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|s|
58
+ s.contains_array key: :array do |a|
59
+ a.should_only_contain type: :string
60
+ end
61
+ }.generate_schema
62
+
63
+ episodes_where_sheldon_says_bazinga_in_series_2 = {
64
+ array: [1,2,3]
65
+ }.to_json
66
+
67
+ assert_not(test_schema.valid? episodes_where_sheldon_says_bazinga_in_series_2)
68
+ assert_match(/.* is not a String/, test_schema.get_errors[:array][0][0])
69
+ end
70
+
71
+ test "As a user, given that I have specified that a boolean should map to a given
72
+ key and that the actual value is not a boolean, I want to now that the
73
+ value is not a boolean" do
74
+
75
+ test_schema = EasyJSONMatcher::SchemaGenerator.new { |s|
76
+ s.has_boolean(key: :bool)
77
+ }.generate_schema
78
+
79
+ no_bool = {
80
+ bool: "false"
81
+ }.to_json
82
+
83
+ assert_not(test_schema.valid? no_bool)
84
+
85
+ assert_match(/.* is not a Boolean/, test_schema.get_errors[:bool][0])
86
+ end
87
+
88
+ test "As a user, given that I have specified that a date should map to a given key
89
+ and that the actual value is not a date, I want to be informed that the value
90
+ is not a date" do
91
+
92
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|s|
93
+ s.has_date(key: :date)
94
+ }.generate_schema
95
+
96
+ no_date = {
97
+ date: "hello world"
98
+ }.to_json
99
+
100
+ assert_not(test_schema.valid? no_date)
101
+
102
+ assert_match(/.* is not a Date/, test_schema.get_errors[:date][0])
103
+ end
104
+
105
+ test "As a user, given that I have specified that a value should be a number,
106
+ I want to be informed that the value was not a number" do
107
+
108
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|s|
109
+ s.has_number(key: :number)
110
+ }.generate_schema
111
+
112
+ no_number = {
113
+ number: 'six'
114
+ }.to_json
115
+
116
+
117
+ assert_not(test_schema.valid? no_number)
118
+ assert_match(/.* is not a Number/, test_schema.get_errors[:number][0])
119
+ end
120
+
121
+ test "As a user, given that I have specified that a value should be an object,
122
+ I want an error message to inform me if a value is not an object" do
123
+
124
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|s|
125
+ s.has_object(key: :object)
126
+ }.generate_schema
127
+
128
+ no_object = {
129
+ object: false
130
+ }.to_json
131
+
132
+ assert_not(test_schema.valid? no_object)
133
+ assert_match(/.* is not an Object/, test_schema.get_errors[:object][0])
134
+ end
135
+
136
+ test "As a user, given that I have supplied an invalid JSON object, I want an
137
+ error message to inform me that the candidate could not be parsed" do
138
+
139
+ test_schema = EasyJSONMatcher::SchemaGenerator.new {|s|
140
+ s.has_object(key: :object)
141
+ }.generate_schema
142
+
143
+ not_json = 'this is not a JSON String'
144
+
145
+ test_schema.valid? not_json
146
+ assert_match(/.* is not a valid JSON String/, test_schema.get_errors[:root][0])
147
+ end
148
+ end
@@ -0,0 +1,48 @@
1
+ require 'test_helper'
2
+
3
+ class GlobalValidationOptionsTest < ActiveSupport::TestCase
4
+
5
+ test 'As a user I want to be able to set validation options globally when defining the schema' do
6
+
7
+ test_schema = EasyJSONMatcher::SchemaGenerator.new(global_opts: { required: true }) { |schema|
8
+ schema.has_boolean key: :implicitly_required
9
+ schema.contains_node key: :also_implicitly_required do |n|
10
+ n.has_boolean key: :nested_implicitly_required
11
+ end
12
+ }.generate_schema
13
+
14
+ invalid = {
15
+ also_implicitly_required: {
16
+ }
17
+ }.to_json
18
+
19
+ assert_not(test_schema.valid?invalid)
20
+ implicitly_required_error = test_schema.get_errors[:implicitly_required][0]
21
+ nested_implicitly_required_error = test_schema.get_errors[:also_implicitly_required][:nested_implicitly_required][0]
22
+ error_message = /Value was not present/
23
+ assert_match(error_message, implicitly_required_error)
24
+ assert_match(error_message, nested_implicitly_required_error)
25
+ end
26
+
27
+ test 'As a user I want to be able to override global validation options for specific node' do
28
+
29
+ test_schema = EasyJSONMatcher::SchemaGenerator.new(global_opts: { required: true }) { |schema|
30
+ schema.has_boolean key: :implicitly_required
31
+ schema.contains_node key: :also_implicitly_required do |n|
32
+ n.has_boolean key: :nested_implicitly_required, opts: {required: false}
33
+ end
34
+ }.generate_schema
35
+
36
+ invalid = {
37
+ also_implicitly_required: {
38
+ }
39
+ }.to_json
40
+
41
+ assert_not(test_schema.valid?invalid)
42
+ implicitly_required_error = test_schema.get_errors[:implicitly_required][0]
43
+ nested_implicitly_required_error = test_schema.get_errors[:also_implicitly_required][:nested_implicitly_required][0]
44
+ error_message = /Value was not present/
45
+ assert_match(error_message, implicitly_required_error)
46
+ assert(nested_implicitly_required_error.nil?)
47
+ end
48
+ end
@@ -6,7 +6,7 @@ class ManagingSchemasTest < ActiveSupport::TestCase
6
6
  @name = :test
7
7
  EasyJSONMatcher::SchemaGenerator.new { |schema|
8
8
  schema.has_attribute(key: :name, opts: {type: :string, required: true})
9
- }.register(schema_name: @name)
9
+ }.register(as: @name)
10
10
  end
11
11
 
12
12
  test "As a user I want to be able to register a Schema so I can reuse it later" do
@@ -18,27 +18,27 @@ class ManagingSchemasTest < ActiveSupport::TestCase
18
18
  name: 'Green Mandarin'
19
19
  }.to_json
20
20
 
21
- schema = EasyJSONMatcher::SchemaLibrary.get_schema(@name)
21
+ schema = EasyJSONMatcher::SchemaLibrary.get_schema(name: @name)
22
22
  assert(schema.valid?(test_schema), "test_schema did not validate correctly")
23
23
  end
24
24
 
25
25
  test "SchemaLibrary should thrown a MissingSchemaException if an unregistered schema is requested" do
26
26
  assert_raises(EasyJSONMatcher::MissingSchemaException) do
27
- EasyJSONMatcher::SchemaLibrary.get_schema("#{@name.to_s}-wibble")
27
+ EasyJSONMatcher::SchemaLibrary.get_schema(name: "#{@name.to_s}-wibble")
28
28
  end
29
29
  end
30
30
 
31
31
  test "As a user I want to reuse a schema within another schema" do
32
32
  test_schema = EasyJSONMatcher::SchemaGenerator.new { |s|
33
- s.has_attribute(key: :is_present, opts: {type: :boolean, required: true})
34
- s.contains_schema(schema_name: @name)
35
- }.generate_node
33
+ s.has_boolean(key: :is_present, opts: {required: true})
34
+ s.has_schema(key: @name, opts: {name: @name, required: true})
35
+ }.generate_schema
36
36
 
37
37
  invalid_json = {
38
38
  is_present: true,
39
39
  }
40
40
 
41
- assert_not(test_schema.valid?(invalid_json), "#{invalid_json} should not have been valid as it does not include the saved schema")
41
+ # assert_not(test_schema.valid?(invalid_json), "#{invalid_json} should not have been valid as it does not include the saved schema")
42
42
 
43
43
  valid_json = invalid_json.dup
44
44
  valid_json.store(@name, {name: 'Achilles Tang'})
@@ -54,15 +54,15 @@ class ManagingSchemasTest < ActiveSupport::TestCase
54
54
  atts.has_attribute key: :alpha_3, opts: {type: :string, required: true}
55
55
  atts.has_attribute key: :name, opts: {type: :string, required: true}
56
56
  end
57
- }.register(schema_name: :country)
57
+ }.register(as: :country)
58
58
 
59
59
  EasyJSONMatcher::SchemaGenerator.new {|country_payload|
60
- country_payload.contains_schema(schema_name: :country, opts: {key: :data})
61
- }.register(schema_name: :country_payload)
60
+ country_payload.has_attribute(key: :data, opts: {name: :country, type: :schema})
61
+ }.register(as: :country_payload)
62
62
 
63
63
  valid_json = "{\"data\":{\"id\":\"4376\",\"type\":\"countries\",\"attributes\":{\"alpha_2\":\"GB\",\"alpha_3\":\"GBR\",\"name\":\"United Kingdom of Great Britain and Northern Ireland\"}}}"
64
64
 
65
- validator = EasyJSONMatcher::SchemaLibrary.get_schema(:country_payload)
65
+ validator = EasyJSONMatcher::SchemaLibrary.get_schema(name: :country_payload)
66
66
  assert(validator.valid? valid_json)
67
67
  end
68
68
  end