easy_json_matcher 0.0.2.pre.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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