easy_json_matcher 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/easy_json_matcher/array_content_validator.rb +22 -0
- data/lib/easy_json_matcher/array_generator.rb +41 -0
- data/lib/easy_json_matcher/array_validator.rb +11 -76
- data/lib/easy_json_matcher/attribute_generator.rb +37 -0
- data/lib/easy_json_matcher/attribute_type_methods.rb +29 -0
- data/lib/easy_json_matcher/coercion_error.rb +10 -0
- data/lib/easy_json_matcher/content_wrapper.rb +2 -4
- data/lib/easy_json_matcher/{validation_error.rb → easy_json_matcher_error.rb} +2 -1
- data/lib/easy_json_matcher/json_coercer.rb +34 -0
- data/lib/easy_json_matcher/node.rb +10 -114
- data/lib/easy_json_matcher/node_generator.rb +58 -0
- data/lib/easy_json_matcher/schema_generator.rb +47 -71
- data/lib/easy_json_matcher/schema_library.rb +8 -11
- data/lib/easy_json_matcher/unknown_validation_step_error.rb +10 -0
- data/lib/easy_json_matcher/validation_chain_factory.rb +48 -0
- data/lib/easy_json_matcher/validation_rules.rb +59 -0
- data/lib/easy_json_matcher/validation_step.rb +36 -0
- data/lib/easy_json_matcher/validator.rb +12 -87
- data/lib/easy_json_matcher/validator_set.rb +31 -0
- data/lib/easy_json_matcher/version.rb +1 -1
- data/lib/easy_json_matcher.rb +6 -2
- data/lib/easy_json_matcher.rb~ +5 -0
- data/test/array_content_validator_test.rb +17 -0
- data/test/custom_validations_test.rb +17 -17
- data/test/global_validation_options_test.rb +39 -44
- data/test/json_coercer_test.rb +25 -0
- data/test/managing_schemas_test.rb +53 -52
- data/test/node_test.rb +28 -0
- data/test/primitives_boolean_test.rb +27 -0
- data/test/primitives_date_test.rb +28 -0
- data/test/primitives_number_test.rb +27 -0
- data/test/primitives_object_test.rb +27 -0
- data/test/primitives_string_test.rb +27 -0
- data/test/primtives_value_test.rb +23 -0
- data/test/required_validation_test.rb +7 -7
- data/test/schema_generator_test.rb +23 -0
- data/test/strict_mode_test.rb +25 -54
- data/test/test_helper.rb +8 -6
- data/test/validating_arrays_test.rb +40 -132
- data/test/validation_chain_factory_test.rb +45 -0
- data/test/validation_chain_test_helper.rb +13 -0
- data/test/validation_step_array_test.rb +27 -0
- data/test/validation_step_boolean_test.rb +19 -0
- data/test/validation_step_date_test.rb +20 -0
- data/test/validation_step_not_required_test.rb +35 -0
- data/test/validation_step_number_test.rb +23 -0
- data/test/validation_step_object_test.rb +20 -0
- data/test/validation_step_required_test.rb +19 -0
- data/test/validation_step_string_test.rb +20 -0
- data/test/validation_step_test.rb +55 -0
- data/test/validation_step_value_test.rb +15 -0
- data/test/validator_set_test.rb +49 -0
- data/test/validator_test.rb +44 -0
- metadata +64 -26
- data/lib/easy_json_matcher/boolean_validator.rb +0 -14
- data/lib/easy_json_matcher/date_validator.rb +0 -44
- data/lib/easy_json_matcher/node.rb~ +0 -121
- data/lib/easy_json_matcher/number_validator.rb +0 -22
- data/lib/easy_json_matcher/object_validator.rb +0 -12
- data/lib/easy_json_matcher/schema_generator.rb~ +0 -104
- data/lib/easy_json_matcher/string_validator.rb +0 -16
- data/lib/easy_json_matcher/validator.rb~ +0 -99
- data/lib/easy_json_matcher/validator_factory.rb +0 -76
- data/lib/easy_json_matcher/value_validator.rb +0 -10
- data/lib/easy_json_matcher/version.rb~ +0 -3
- data/test/custom_validations_test.rb~ +0 -25
- data/test/easy_json_matcher_test.rb +0 -262
- data/test/easy_json_matcher_test.rb~ +0 -262
- data/test/error_messages_test.rb +0 -148
- data/test/reset_test.rb +0 -32
- data/test/reset_test.rb~ +0 -32
@@ -2,34 +2,31 @@ module EasyJSONMatcher
|
|
2
2
|
class SchemaLibrary
|
3
3
|
|
4
4
|
SCHEMAS = {}
|
5
|
+
|
5
6
|
private_constant :SCHEMAS
|
7
|
+
|
6
8
|
class << self
|
9
|
+
|
7
10
|
def available_schemas
|
8
|
-
|
11
|
+
SCHEMAS.keys
|
9
12
|
end
|
10
13
|
|
11
14
|
def schema_for(name)
|
12
|
-
|
15
|
+
SCHEMAS[name]
|
13
16
|
end
|
14
17
|
|
15
18
|
def add_schema(name:, schema:)
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def schemas
|
20
|
-
SCHEMAS
|
19
|
+
SCHEMAS[name] = schema
|
21
20
|
end
|
22
21
|
|
23
22
|
def get_schema(name:, opts: {})
|
24
|
-
|
25
|
-
_set_schema_key(schema, opts.delete(:key))
|
23
|
+
schema = _find_and_clone_schema(name) or raise MissingSchemaException.new("No schema with #{name} has been registered")
|
26
24
|
schema
|
27
25
|
end
|
28
26
|
|
29
27
|
def _find_and_clone_schema(name)
|
30
28
|
s = SCHEMAS[name]
|
31
|
-
return s.dup if s
|
32
|
-
nil
|
29
|
+
return s.dup if s or nil
|
33
30
|
end
|
34
31
|
|
35
32
|
def _set_schema_key(schema, key)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "easy_json_matcher/validation_step"
|
2
|
+
require "easy_json_matcher/unknown_validation_step_error"
|
3
|
+
require "easy_json_matcher/exceptions"
|
4
|
+
|
5
|
+
module EasyJSONMatcher
|
6
|
+
class ValidationChainFactory
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def get_chain(steps:, of: ValidationStep)
|
11
|
+
head = create_head_for(steps: steps, step_type: of)
|
12
|
+
assemble_chain(head: head, steps: steps, step_type: of)
|
13
|
+
head
|
14
|
+
end
|
15
|
+
|
16
|
+
def assemble_chain(head:, steps:, step_type:)
|
17
|
+
steps.inject(head) do |last_link, step|
|
18
|
+
last_link >> get_step_for(validating: step, using: step_type)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_head_for(steps:, step_type:)
|
23
|
+
is_required = steps.include?(:required)
|
24
|
+
get_step_for validating: is_required ? :required : :not_required, using: step_type
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_step_for(validating:, using: ValidationStep)
|
28
|
+
if validating.respond_to? :call
|
29
|
+
using.new verify_with: validating
|
30
|
+
elsif verifier = standard_validator(with: validating)
|
31
|
+
using.new verify_with: verifier
|
32
|
+
else
|
33
|
+
begin
|
34
|
+
return SchemaLibrary.get_schema(name: validating)
|
35
|
+
rescue MissingSchemaException => ex
|
36
|
+
#TODO this needs a little finesse: How will the user know if it was a missing schema?
|
37
|
+
raise UnknownValidationStepError.new(type: validating)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def standard_validator(with:)
|
43
|
+
require "easy_json_matcher/validation_rules"
|
44
|
+
VALIDATION_RULES[with]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module EasyJSONMatcher
|
2
|
+
|
3
|
+
VALIDATION_RULES = {
|
4
|
+
object: -> (value, errors) {
|
5
|
+
unless value.is_a? Hash
|
6
|
+
errors << "#{value} is not an Object"
|
7
|
+
return false
|
8
|
+
end
|
9
|
+
},
|
10
|
+
string: -> (value, errors) {
|
11
|
+
unless value.is_a? String
|
12
|
+
errors << "#{value} is not a String"
|
13
|
+
return false
|
14
|
+
end
|
15
|
+
},
|
16
|
+
number: -> (value, errors){
|
17
|
+
error_message = "#{value} is not a Number"
|
18
|
+
begin
|
19
|
+
Kernel::Float(value)
|
20
|
+
rescue ArgumentError, TypeError
|
21
|
+
errors << error_message
|
22
|
+
false
|
23
|
+
end
|
24
|
+
},
|
25
|
+
date: ->(value, errors){
|
26
|
+
require "date"
|
27
|
+
error_message = "#{value} is not a valid SQL date"
|
28
|
+
begin
|
29
|
+
Date.strptime(value,"%Y-%m-%d")
|
30
|
+
rescue ArgumentError, TypeError
|
31
|
+
errors << error_message
|
32
|
+
end
|
33
|
+
},
|
34
|
+
boolean: ->(value, errors){
|
35
|
+
clazz = value.class
|
36
|
+
unless (clazz == TrueClass) || (clazz == FalseClass)
|
37
|
+
errors << "#{value} is not a Boolean"
|
38
|
+
false
|
39
|
+
end
|
40
|
+
},
|
41
|
+
array: ->(value, errors){
|
42
|
+
unless value.is_a? Array
|
43
|
+
errors << "Value was not an array"
|
44
|
+
false
|
45
|
+
end
|
46
|
+
},
|
47
|
+
value: ->(value, errors){
|
48
|
+
# This is a bit of a toughie since value can be any value, including nil
|
49
|
+
},
|
50
|
+
not_required: ->(value, errors){
|
51
|
+
false if value.nil?
|
52
|
+
},
|
53
|
+
required: ->(value, errors){
|
54
|
+
errors << "no value found" and return false if value.nil?
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# The ValidationStep class represents a step in the process of validating a value. Each ValidationStep
|
2
|
+
# instance can be chained to another ValidationStep instance in order to produce a defined process for
|
3
|
+
# running validations within a given Validator. A use case for such a procedure is where a value is
|
4
|
+
# required and of a certain type. In this case the validation for required must precede the check for
|
5
|
+
# the type, and validation must cease if the value is nil.
|
6
|
+
module EasyJSONMatcher
|
7
|
+
class ValidationStep
|
8
|
+
|
9
|
+
attr_reader :next_step, :verifier
|
10
|
+
|
11
|
+
def initialize(verify_with:)
|
12
|
+
@verifier = verify_with
|
13
|
+
end
|
14
|
+
|
15
|
+
def check(value:)
|
16
|
+
errors = []
|
17
|
+
if verifier.call(value, errors) == false || is_tail?
|
18
|
+
errors
|
19
|
+
else
|
20
|
+
errors + next_step.check(value: value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def >>(step)
|
25
|
+
@next_step = step
|
26
|
+
end
|
27
|
+
|
28
|
+
def concat(chain)
|
29
|
+
is_tail? ? self.>>(chain) : next_step.concat(chain)
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_tail?
|
33
|
+
next_step.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,102 +1,27 @@
|
|
1
|
+
require 'easy_json_matcher/json_coercer'
|
2
|
+
|
1
3
|
module EasyJSONMatcher
|
2
4
|
class Validator
|
3
5
|
|
4
|
-
attr_reader :
|
6
|
+
attr_reader :validation_chain, :coercer
|
5
7
|
attr_accessor :key
|
6
8
|
|
7
|
-
def initialize(
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@custom_validator = options[:custom_validator]
|
11
|
-
@errors = []
|
12
|
-
_post_initialise(options)
|
9
|
+
def initialize(validate_with:, coerce_with: JsonCoercer.new)
|
10
|
+
@validation_chain = validate_with
|
11
|
+
@coercer = coerce_with
|
13
12
|
end
|
14
13
|
|
15
14
|
# Hook. Allows further setup to be carried out by subclasses
|
16
15
|
def _post_initialise(options); end
|
17
16
|
|
18
|
-
def valid?(candidate)
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
_set_content(candidate) #Hook
|
23
|
-
if content.nil?
|
24
|
-
_check_required?
|
25
|
-
else
|
26
|
-
_validate #Hook
|
27
|
-
end
|
28
|
-
_run_custom_validator if custom_validator
|
29
|
-
_no_errors?
|
30
|
-
end
|
31
|
-
|
32
|
-
# Hook. Overriden in Node
|
33
|
-
def reset!
|
34
|
-
errors.clear
|
35
|
-
end
|
36
|
-
|
37
|
-
# Hook
|
38
|
-
# Protected method that Validators use to implement their validation logic.
|
39
|
-
# Called by #valid?
|
40
|
-
def _validate
|
41
|
-
raise NotImplementedError.new "Validators must override _validate"
|
42
|
-
end
|
43
|
-
|
44
|
-
# Hook
|
45
|
-
# Protected method that Validators use to set their content from the candidate.
|
46
|
-
def _set_content(candidate)
|
47
|
-
@content = key ? candidate[key] : candidate
|
48
|
-
end
|
49
|
-
|
50
|
-
# Hook.
|
51
|
-
# This method returns the errors that this validator has found in the candidate.
|
52
|
-
def get_errors
|
53
|
-
error_message = {}
|
54
|
-
# Should the method just add errors even if there has been no error? Would
|
55
|
-
# avoid undefined method [] for nil:NilClass if you look for a key where
|
56
|
-
# there is no error but it would also make the output harder to read...
|
57
|
-
error_message[key.to_sym] = errors
|
58
|
-
error_message
|
59
|
-
end
|
60
|
-
|
61
|
-
# This method makees sure that the candidate behaves like a Hash, and not a
|
62
|
-
# value or an array.
|
63
|
-
def _check_content_type(candidate)
|
64
|
-
# TODO perhaps this should raise an error instead of returning false?
|
65
|
-
# if the value that has arrived at this point doesn't behave like a Hash then it
|
66
|
-
# is in the wrong place.
|
67
|
-
begin
|
68
|
-
candidate[key]
|
69
|
-
rescue TypeError
|
70
|
-
return false
|
71
|
-
end
|
72
|
-
true
|
73
|
-
end
|
74
|
-
|
75
|
-
def _check_required?
|
76
|
-
if required
|
77
|
-
errors << "Value was not present"
|
78
|
-
return true
|
79
|
-
else
|
80
|
-
return false
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def _create_validator(type:, opts: {})
|
85
|
-
ValidatorFactory.get_instance(type: type, opts: opts)
|
86
|
-
end
|
87
|
-
|
88
|
-
def _custom_validator?
|
89
|
-
custom_validator
|
90
|
-
end
|
91
|
-
|
92
|
-
def _run_custom_validator
|
93
|
-
if error_message = custom_validator.call(content)
|
94
|
-
errors << error_message
|
95
|
-
end
|
17
|
+
def valid?(candidate:)
|
18
|
+
errors = validate(candidate: candidate)
|
19
|
+
errors.empty?
|
96
20
|
end
|
97
21
|
|
98
|
-
def
|
99
|
-
|
22
|
+
def validate(candidate:)
|
23
|
+
candidate = coercer.coerce(json: candidate)
|
24
|
+
validation_chain.check(value: candidate)
|
100
25
|
end
|
101
26
|
end
|
102
27
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'easy_json_matcher'
|
2
|
+
|
3
|
+
module EasyJSONMatcher
|
4
|
+
class ValidatorSet
|
5
|
+
|
6
|
+
attr_accessor :validators, :strict
|
7
|
+
|
8
|
+
def initialize(validators:, strict: false)
|
9
|
+
@validators = validators
|
10
|
+
@strict = strict
|
11
|
+
end
|
12
|
+
|
13
|
+
def check(value:, errors:[])
|
14
|
+
error_hash = validators.each_with_object({}) do |k_v, errors_found|
|
15
|
+
key = k_v[0]
|
16
|
+
val = value[key]
|
17
|
+
validator = k_v[1]
|
18
|
+
results = validator.check(value: val)
|
19
|
+
errors_found[key] = results unless results.empty?
|
20
|
+
end
|
21
|
+
validate_strict_keyset(keys: validators.keys, candidates: value.keys, errors: error_hash) if strict
|
22
|
+
errors << error_hash unless error_hash.empty?
|
23
|
+
errors
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate_strict_keyset(keys:, errors:, candidates:)
|
27
|
+
rogue_keys = candidates - keys
|
28
|
+
errors[:unexpected_keys] = "Unexpected keys: #{rogue_keys}" unless rogue_keys.empty?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/easy_json_matcher.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "easy_json_matcher/node"
|
2
|
+
require "easy_json_matcher/schema_generator"
|
3
|
+
require "easy_json_matcher/validator_set"
|
4
|
+
|
3
5
|
module EasyJSONMatcher
|
4
6
|
|
7
|
+
TYPES = [:number, :object, :value, :string, :boolean, :date, :array]
|
8
|
+
|
5
9
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "easy_json_matcher/array_content_validator"
|
3
|
+
|
4
|
+
module EasyJSONMatcher
|
5
|
+
describe ArrayContentValidator do
|
6
|
+
|
7
|
+
it "should check all the elements in an array" do
|
8
|
+
mock_values = (1..5).map do |n|
|
9
|
+
mock_val = Minitest::Mock.new
|
10
|
+
mock_val.expect(:hello, "hi")
|
11
|
+
end
|
12
|
+
subject = ArrayContentValidator.new( verify_with: ValidationStep.new(verify_with: ->(value, errors) { value.hello }))
|
13
|
+
subject.check value: mock_values
|
14
|
+
mock_values.each(&:verify)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
3
|
+
module EasyJSONMatcher
|
4
4
|
|
5
|
-
|
6
|
-
test_schema = EasyJSONMatcher::SchemaGenerator.new do |s|
|
7
|
-
string_validator = ->(candidate) { "String did not say 'hi'" unless candidate == 'hi' }
|
8
|
-
s.has_string key: :a_string, opts: { custom_validator: string_validator }
|
9
|
-
end.generate_schema
|
5
|
+
describe "Custom Validations" do
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
subject {
|
8
|
+
SchemaGenerator.new { |sc|
|
9
|
+
sc.has_attribute key: :val,
|
10
|
+
opts: [
|
11
|
+
:required,
|
12
|
+
->(value, errors) { errors << "value was false" unless value === true }
|
13
|
+
]
|
14
|
+
}.generate_schema
|
15
|
+
}
|
14
16
|
|
15
|
-
|
17
|
+
it "should pass where val => true" do
|
18
|
+
subject.validate( candidate: { val: true }.to_json ).must_be :empty?
|
19
|
+
end
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
test_schema.reset!
|
22
|
-
|
23
|
-
assert(test_schema.valid?(should_validate), test_schema.get_errors)
|
21
|
+
it "should show an error where val => false" do
|
22
|
+
subject.validate( candidate: { val: false }.to_json ).wont_be :empty?
|
23
|
+
end
|
24
24
|
end
|
25
25
|
end
|
@@ -1,48 +1,43 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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?)
|
3
|
+
module EasyJSONMatcher
|
4
|
+
|
5
|
+
describe "Global Validation Options" do
|
6
|
+
|
7
|
+
|
8
|
+
subject {
|
9
|
+
SchemaGenerator.new(global_opts: [ :required ]) { |schema|
|
10
|
+
schema.has_boolean key: :implicitly_required
|
11
|
+
schema.contains_node key: :also_implicitly_required do |n|
|
12
|
+
n.has_boolean key: :nested_implicitly_required
|
13
|
+
n.has_boolean key: :not_required, opts: [:not_required]
|
14
|
+
end
|
15
|
+
}.generate_schema
|
16
|
+
}
|
17
|
+
|
18
|
+
let(:invalid_candidate){
|
19
|
+
{
|
20
|
+
also_implicitly_required: {
|
21
|
+
nested_implicitly_required: true
|
22
|
+
}
|
23
|
+
}.to_json
|
24
|
+
}
|
25
|
+
|
26
|
+
let(:valid_candidate){
|
27
|
+
{
|
28
|
+
implicitly_required: true,
|
29
|
+
also_implicitly_required: {
|
30
|
+
nested_implicitly_required: true
|
31
|
+
}
|
32
|
+
}.to_json
|
33
|
+
}
|
34
|
+
|
35
|
+
it "should only apply required to all implicitly required keys" do
|
36
|
+
subject.valid?(candidate: valid_candidate).must_be :===, true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should apply required to all implicitly required keys" do
|
40
|
+
subject.valid?(candidate: invalid_candidate).must_be :===, false
|
41
|
+
end
|
47
42
|
end
|
48
43
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "easy_json_matcher/json_coercer"
|
3
|
+
require "easy_json_matcher/coercion_error"
|
4
|
+
|
5
|
+
module EasyJSONMatcher
|
6
|
+
describe JsonCoercer do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@subject = JsonCoercer.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#coerce" do
|
13
|
+
|
14
|
+
it "should coerce a valid JSON string to a Hash" do
|
15
|
+
valid_json = { a: 1, b: 2, c: 3}.to_json
|
16
|
+
@subject.coerce(json: valid_json).must_be_instance_of Hash
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise a JSONFormatError if json: is an invalid JSON string" do
|
20
|
+
invalid_json = "123"
|
21
|
+
-> { @subject.coerce(json: invalid_json) }.must_raise CoercionError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,68 +1,69 @@
|
|
1
|
-
require
|
1
|
+
require "test_helper"
|
2
|
+
require "easy_json_matcher/exceptions"
|
2
3
|
|
3
|
-
|
4
|
+
module EasyJSONMatcher
|
5
|
+
class ManagingSchemasTest < ActiveSupport::TestCase
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
test "As a user I want to be able to register a Schema so I can reuse it later" do
|
13
|
-
assert(EasyJSONMatcher::SchemaLibrary.available_schemas.include?(:test), ":test not found in available_nodes")
|
14
|
-
end
|
7
|
+
setup do
|
8
|
+
@name = :test
|
9
|
+
SchemaGenerator.new { |schema|
|
10
|
+
schema.has_attribute(key: :name, opts: [ :string, :required ])
|
11
|
+
}.register(as: @name)
|
12
|
+
end
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}.to_json
|
14
|
+
test "As a user I want to be able to register a Schema so I can reuse it later" do
|
15
|
+
assert(SchemaLibrary.available_schemas.include?(:test), ":test not found in available_nodes")
|
16
|
+
end
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
test "As as user I want to reuse a saved schema" do
|
19
|
+
candidate = {
|
20
|
+
name: "Green Mandarin"
|
21
|
+
}.to_json
|
22
|
+
schema = Validator.new validate_with: SchemaLibrary.get_schema(name: @name)
|
23
|
+
assert(schema.valid?(candidate: candidate), "test_schema did not validate correctly")
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
test "SchemaLibrary should thrown a MissingSchemaException if an unregistered schema is requested" do
|
27
|
+
assert_raises(MissingSchemaException) do
|
28
|
+
SchemaLibrary.get_schema(name: "#{@name.to_s}-wibble")
|
29
|
+
end
|
28
30
|
end
|
29
|
-
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
test "As a user I want to reuse a schema within another schema" do
|
33
|
+
test_schema = SchemaGenerator.new { |s|
|
34
|
+
s.has_boolean key: :is_present, opts: [ :required ]
|
35
|
+
s.has_schema key: @name, name: @name
|
36
|
+
}.generate_schema
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
invalid_json = {
|
39
|
+
is_present: true,
|
40
|
+
}
|
40
41
|
|
41
|
-
|
42
|
+
# assert_not(test_schema.valid?(invalid_json), "#{invalid_json} should not have been valid as it does not include the saved schema")
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
valid_json = invalid_json.dup
|
45
|
+
valid_json.store(@name, {name: "Achilles Tang"})
|
46
|
+
valid_json = valid_json.to_json
|
47
|
+
assert(test_schema.valid?(candidate: valid_json), "Stored schema did not validate correctly")
|
48
|
+
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
test "It can validate JSON Schema payloads" do
|
51
|
+
SchemaGenerator.new { |country|
|
52
|
+
country.has_attribute key: :id, opts: [:number, :required]
|
53
|
+
country.contains_node(key: :attributes) do |atts|
|
54
|
+
atts.has_attribute key: :alpha_2, opts: [ :string, :required ]
|
55
|
+
atts.has_attribute key: :alpha_3, opts: [ :string, :required ]
|
56
|
+
atts.has_attribute key: :name, opts: [ :string, :required ]
|
57
|
+
end
|
58
|
+
}.register(as: :country)
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
country_payload = SchemaGenerator.new {|country_payload|
|
61
|
+
country_payload.has_schema(key: :data, name: :country)
|
62
|
+
}.register(as: :country_payload)
|
62
63
|
|
63
|
-
|
64
|
+
valid_json = "{\"data\":{\"id\":\"4376\",\"type\":\"countries\",\"attributes\":{\"alpha_2\":\"GB\",\"alpha_3\":\"GBR\",\"name\":\"United Kingdom of Great Britain and Northern Ireland\"}}}"
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
assert country_payload.valid?(candidate: valid_json)
|
67
|
+
end
|
67
68
|
end
|
68
69
|
end
|