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.
- checksums.yaml +4 -4
- data/lib/easy_json_matcher/array_validator.rb +46 -15
- data/lib/easy_json_matcher/boolean_validator.rb +5 -0
- data/lib/easy_json_matcher/content_wrapper.rb +7 -9
- data/lib/easy_json_matcher/date_validator.rb +12 -3
- data/lib/easy_json_matcher/exceptions.rb +0 -1
- data/lib/easy_json_matcher/node.rb +75 -18
- data/lib/easy_json_matcher/number_validator.rb +6 -1
- data/lib/easy_json_matcher/object_validator.rb +5 -1
- data/lib/easy_json_matcher/schema_generator.rb +59 -30
- data/lib/easy_json_matcher/schema_library.rb +8 -3
- data/lib/easy_json_matcher/string_validator.rb +9 -3
- data/lib/easy_json_matcher/validator.rb +64 -6
- data/lib/easy_json_matcher/validator_factory.rb +2 -2
- data/lib/easy_json_matcher/value_validator.rb +2 -0
- data/lib/easy_json_matcher/version.rb +1 -1
- data/test/dummy/log/test.log +23957 -10665
- data/test/easy_json_matcher_test.rb +89 -50
- data/test/error_messages_test.rb +148 -0
- data/test/global_validation_options_test.rb +48 -0
- data/test/managing_schemas_test.rb +11 -11
- data/test/required_validation_test.rb +2 -2
- data/test/reset_test.rb +26 -0
- data/test/strict_mode_test.rb +63 -0
- data/test/validating_arrays_test.rb +106 -35
- metadata +43 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 550d51e3fa5dcd2a06ade6049b34666c957e3c06
|
4
|
+
data.tar.gz: 073104ceb62af67ae2dfbf2cb4ac800cd584b809
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a512cdd2cde619c1b9beaf88efb96167077c8d96c6fd19cf76d5c74c8e89c5e95f274b643901fe344cd96d1dc7d086721731962bad243942ea95c174b705735
|
7
|
+
data.tar.gz: 01960e66aa4bdf8ce3bb31df5ddc474622f10d19bca0b414bd1c7ab8d1b70c5ab16da3c75ea770dd0836cf1c7825dc8dfa20d18a98f16aae2896359772e36579
|
@@ -2,9 +2,45 @@ require 'easy_json_matcher/validator'
|
|
2
2
|
module EasyJSONMatcher
|
3
3
|
class ArrayValidator < Validator
|
4
4
|
attr_reader :validators, :validator_results
|
5
|
+
######################### Methods for requiring values by type #################
|
6
|
+
|
7
|
+
def should_only_contain_strings(opts: {})
|
8
|
+
should_only_contain type: :string, opts: opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def should_only_contain_objects(opts: {})
|
12
|
+
should_only_contain type: :object, opts: opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def should_only_contain_values(opts: {})
|
16
|
+
should_only_contain type: :value, opts: opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def should_only_contain_numbers(opts: {})
|
20
|
+
should_only_contain type: :number, opts: opts
|
21
|
+
end
|
22
|
+
|
23
|
+
def should_only_contain_booleans(opts: {})
|
24
|
+
should_only_contain type: :boolean, opts: opts
|
25
|
+
end
|
26
|
+
|
27
|
+
def should_only_contain_dates(opts: {})
|
28
|
+
should_only_contain type: :date, opts: opts
|
29
|
+
end
|
30
|
+
|
31
|
+
def should_only_contain_schema(name:, opts: {})
|
32
|
+
should_only_contain type: :schema, opts: opts.merge({name: name})
|
33
|
+
end
|
34
|
+
|
35
|
+
def should_only_contain(type:,opts: {})
|
36
|
+
_clear_validators
|
37
|
+
_add_validator(_create_validator(type: type, opts: opts))
|
38
|
+
end
|
39
|
+
|
40
|
+
######################## Private methods #######################################
|
5
41
|
|
6
42
|
def _validate
|
7
|
-
|
43
|
+
errors << "#{content} is not an Array" unless _content_is_array?
|
8
44
|
_validate_content
|
9
45
|
end
|
10
46
|
|
@@ -14,14 +50,8 @@ module EasyJSONMatcher
|
|
14
50
|
|
15
51
|
def _validate_content
|
16
52
|
validators.each do |val|
|
17
|
-
|
53
|
+
_accumulate_errors val
|
18
54
|
end
|
19
|
-
_validation_result
|
20
|
-
end
|
21
|
-
|
22
|
-
def should_only_contain(type:,opts: {})
|
23
|
-
_clear_validators
|
24
|
-
_add_validator(_create_validator(type: type, opts: opts))
|
25
55
|
end
|
26
56
|
|
27
57
|
def _clear_validators
|
@@ -36,18 +66,19 @@ module EasyJSONMatcher
|
|
36
66
|
@validators ||= []
|
37
67
|
end
|
38
68
|
|
39
|
-
def
|
40
|
-
content.each do |
|
41
|
-
|
69
|
+
def _accumulate_errors(validator)
|
70
|
+
content.each do |candidate|
|
71
|
+
_run_validator(validator, candidate)
|
42
72
|
end
|
73
|
+
errors << validator.errors unless validator._no_errors?
|
43
74
|
end
|
44
75
|
|
45
|
-
def
|
46
|
-
|
76
|
+
def _run_validator(validator, candidate)
|
77
|
+
validator.valid? candidate
|
47
78
|
end
|
48
79
|
|
49
|
-
def
|
50
|
-
|
80
|
+
def _validation_result
|
81
|
+
!validator_results.include? false
|
51
82
|
end
|
52
83
|
end
|
53
84
|
end
|
@@ -1,7 +1,12 @@
|
|
1
1
|
require 'easy_json_matcher/validator'
|
2
2
|
module EasyJSONMatcher
|
3
3
|
class BooleanValidator < Validator
|
4
|
+
|
4
5
|
def _validate
|
6
|
+
errors << "#{content} is not a Boolean" unless _content_is_boolean?
|
7
|
+
end
|
8
|
+
|
9
|
+
def _content_is_boolean?
|
5
10
|
clazz = content.class
|
6
11
|
(clazz == TrueClass) || (clazz == FalseClass)
|
7
12
|
end
|
@@ -1,18 +1,16 @@
|
|
1
1
|
module EasyJSONMatcher
|
2
|
-
|
3
|
-
|
4
|
-
attr_reader :content
|
5
|
-
|
6
|
-
def initialize(content)
|
7
|
-
@content = content
|
8
|
-
end
|
2
|
+
module ContentWrapper
|
9
3
|
|
10
4
|
def [](key)
|
11
5
|
content[key.to_s]
|
12
6
|
end
|
13
7
|
|
14
|
-
def method_missing(method, *args)
|
15
|
-
content.send(method, *args)
|
8
|
+
def method_missing(method, *args, &block)
|
9
|
+
content.send(method, *args, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def keys
|
13
|
+
content.keys.map(&:to_sym)
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
@@ -12,14 +12,15 @@ module EasyJSONMatcher
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def _validate
|
15
|
-
|
15
|
+
_validate_string
|
16
|
+
_validate_date
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
+
def _content_is_a_string?
|
19
20
|
string_validator.valid? content
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
+
def _content_is_a_date?
|
23
24
|
require 'date'
|
24
25
|
begin
|
25
26
|
Date.strptime(content, date_format)
|
@@ -31,5 +32,13 @@ module EasyJSONMatcher
|
|
31
32
|
def date_format
|
32
33
|
@date_format || DEFAULT_DATE_FORMAT
|
33
34
|
end
|
35
|
+
|
36
|
+
def _validate_string
|
37
|
+
errors << "#{content} must be provided as a String for Date validation" unless _content_is_a_string?
|
38
|
+
end
|
39
|
+
|
40
|
+
def _validate_date
|
41
|
+
errors << "#{content} is not a Date" unless _content_is_a_date?
|
42
|
+
end
|
34
43
|
end
|
35
44
|
end
|
@@ -1,30 +1,51 @@
|
|
1
|
-
require 'easy_json_matcher'
|
2
1
|
require 'easy_json_matcher/validator_factory'
|
3
2
|
require 'json'
|
4
3
|
require 'easy_json_matcher/content_wrapper'
|
5
|
-
require 'forwardable'
|
6
4
|
module EasyJSONMatcher
|
7
5
|
class Node < Validator
|
8
|
-
|
6
|
+
include ContentWrapper
|
9
7
|
|
10
|
-
attr_reader :validators
|
11
|
-
|
12
|
-
def_delegators :content, :[]
|
8
|
+
attr_reader :validators, :validity, :strict
|
13
9
|
|
14
10
|
def initialize(opts: {})
|
15
11
|
super(options: opts)
|
16
12
|
@validators = []
|
13
|
+
@validity = true
|
17
14
|
end
|
18
15
|
|
19
16
|
def add_validator(validator)
|
20
17
|
validators << validator
|
21
18
|
end
|
22
19
|
|
20
|
+
def _post_initialise(options)
|
21
|
+
@strict = options[:strict]
|
22
|
+
end
|
23
|
+
|
23
24
|
def _validate
|
25
|
+
_validate_strict_keyset
|
24
26
|
validators.each do |val|
|
25
|
-
|
27
|
+
@validity = false unless _use_validator val
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset!
|
32
|
+
errors.clear
|
33
|
+
validators.each(&:reset!)
|
34
|
+
end
|
35
|
+
|
36
|
+
def _validate_strict_keyset
|
37
|
+
_validate_keyset if strict
|
38
|
+
end
|
39
|
+
|
40
|
+
def _validate_keyset
|
41
|
+
unexpected_keys = keys - _expected_keys
|
42
|
+
errors << "#{unexpected_keys} found in addition to expected keys" unless unexpected_keys.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
def _expected_keys
|
46
|
+
validators.each_with_object([]) do |validator, keyset|
|
47
|
+
keyset << validator.key
|
26
48
|
end
|
27
|
-
true
|
28
49
|
end
|
29
50
|
|
30
51
|
def _use_validator(validator)
|
@@ -32,7 +53,7 @@ module EasyJSONMatcher
|
|
32
53
|
end
|
33
54
|
|
34
55
|
def _get_content_for(key)
|
35
|
-
content[key
|
56
|
+
content[key]
|
36
57
|
end
|
37
58
|
|
38
59
|
def _get_validator_for(key)
|
@@ -40,25 +61,61 @@ module EasyJSONMatcher
|
|
40
61
|
end
|
41
62
|
|
42
63
|
def _set_content(candidate)
|
43
|
-
|
44
|
-
@content = _is_root? ? candidate : candidate[key]
|
64
|
+
@content = _is_root? ? _prep_root_content(candidate) : candidate[key]
|
45
65
|
end
|
46
66
|
|
47
67
|
def _is_root?
|
48
68
|
key.nil?
|
49
69
|
end
|
50
70
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
71
|
+
def get_errors
|
72
|
+
child_errors = _collect_child_errors
|
73
|
+
_wrap_errors(child_errors)
|
74
|
+
end
|
75
|
+
|
76
|
+
def _collect_child_errors
|
77
|
+
validators.each_with_object({}) do |val, container|
|
78
|
+
container.merge!(val.get_errors)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def _wrap_errors(child_errors)
|
83
|
+
_add_local_errors_to child_errors
|
84
|
+
unless _is_root?
|
85
|
+
_wrap_child_errors(child_errors)
|
54
86
|
else
|
55
|
-
|
56
|
-
|
87
|
+
_root_errors(child_errors)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def _add_local_errors_to(child_errors)
|
92
|
+
child_errors.merge!({node_errors_: errors}) unless errors.empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
def _wrap_child_errors(child_errors)
|
96
|
+
errors_wrapper = {}
|
97
|
+
errors_wrapper[key] = child_errors
|
98
|
+
errors_wrapper
|
99
|
+
end
|
100
|
+
|
101
|
+
def _root_errors(child_errors)
|
102
|
+
errors.length > 0 ? {root: errors} : child_errors
|
103
|
+
end
|
104
|
+
|
105
|
+
def _prep_root_content(candidate)
|
106
|
+
candidate.is_a?(String) ? _parse_and_verify_json(candidate) : candidate
|
107
|
+
end
|
108
|
+
|
109
|
+
def _parse_and_verify_json(json)
|
110
|
+
begin
|
111
|
+
JSON.parse(json)
|
112
|
+
rescue JSON::ParserError
|
113
|
+
errors << '#{json} is not a valid JSON String'
|
57
114
|
end
|
58
115
|
end
|
59
116
|
|
60
|
-
def
|
61
|
-
|
117
|
+
def _no_errors?
|
118
|
+
validity && errors.empty?
|
62
119
|
end
|
63
120
|
end
|
64
121
|
end
|
@@ -1,8 +1,14 @@
|
|
1
1
|
# Asserts that a value is a double-precision floating point number in javascript format
|
2
2
|
require 'easy_json_matcher/validator'
|
3
3
|
module EasyJSONMatcher
|
4
|
+
|
4
5
|
class NumberValidator < Validator
|
6
|
+
|
5
7
|
def _validate
|
8
|
+
errors << "#{content} is not a Number" unless _content_is_a_number?
|
9
|
+
end
|
10
|
+
|
11
|
+
def _content_is_a_number?
|
6
12
|
begin
|
7
13
|
Kernel::Float(content)
|
8
14
|
true
|
@@ -12,6 +18,5 @@ module EasyJSONMatcher
|
|
12
18
|
false
|
13
19
|
end
|
14
20
|
end
|
15
|
-
|
16
21
|
end
|
17
22
|
end
|
@@ -2,7 +2,11 @@ require 'easy_json_matcher/validator'
|
|
2
2
|
module EasyJSONMatcher
|
3
3
|
class ObjectValidator < Validator
|
4
4
|
def _validate
|
5
|
-
|
5
|
+
_content_is_object?
|
6
|
+
end
|
7
|
+
|
8
|
+
def _content_is_object?
|
9
|
+
errors << "#{content} is not an Object" unless content.is_a? Hash
|
6
10
|
end
|
7
11
|
end
|
8
12
|
end
|
@@ -5,71 +5,100 @@ require 'easy_json_matcher/exceptions'
|
|
5
5
|
module EasyJSONMatcher
|
6
6
|
class SchemaGenerator
|
7
7
|
|
8
|
-
attr_reader :node
|
9
|
-
attr_reader :name
|
8
|
+
attr_reader :node, :name, :options, :glob_opts
|
10
9
|
|
11
|
-
def initialize(opts: {})
|
12
|
-
@name = opts
|
10
|
+
def initialize(opts: {}, global_opts: {})
|
11
|
+
@name = opts.delete(:key)
|
12
|
+
@options = opts
|
13
|
+
@glob_opts = global_opts
|
13
14
|
yield self if block_given?
|
14
15
|
end
|
15
16
|
|
17
|
+
def has_attribute(key:, opts: {})
|
18
|
+
node.add_validator(_create_validator(key, opts))
|
19
|
+
end
|
20
|
+
|
21
|
+
################ Methods for adding specific attribute types ##############
|
22
|
+
|
16
23
|
def contains_node(key:, opts: {})
|
17
24
|
generator = _node_generator _validator_opts(key, opts)
|
18
25
|
yield generator if block_given?
|
19
|
-
node.add_validator generator.
|
26
|
+
node.add_validator generator.generate_schema
|
20
27
|
end
|
21
28
|
|
22
|
-
def
|
23
|
-
|
29
|
+
def has_boolean(key:, opts: {})
|
30
|
+
has_attribute(key: key, opts: opts.merge({type: :boolean}))
|
24
31
|
end
|
25
32
|
|
26
|
-
def
|
27
|
-
key
|
28
|
-
schema = _create_validator(key, _prep_schema_opts(schema_name, opts))
|
29
|
-
_set_validator_key(schema, opts[:key] || schema_name)
|
30
|
-
node.add_validator schema
|
33
|
+
def has_number(key: , opts: {})
|
34
|
+
has_attribute(key: key, opts: opts.merge({type: :number}))
|
31
35
|
end
|
32
36
|
|
33
|
-
def
|
34
|
-
opts
|
35
|
-
opts[:name] = schema_name
|
36
|
-
opts
|
37
|
+
def has_date(key:, opts: {})
|
38
|
+
has_attribute(key: key, opts: opts.merge({type: :date}))
|
37
39
|
end
|
38
40
|
|
39
|
-
def
|
40
|
-
|
41
|
+
def has_object(key:, opts: {})
|
42
|
+
has_attribute(key: key, opts: opts.merge({type: :object}))
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_value(key:, opts: {})
|
46
|
+
has_attribute(key: key, opts: opts.merge({type: :value}))
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_string(key:, opts: {})
|
50
|
+
has_attribute(key: key, opts: opts.merge({type: :string}))
|
41
51
|
end
|
42
52
|
|
43
53
|
def contains_array(key:, opts: {})
|
44
|
-
opts.merge!({type: :array})
|
54
|
+
opts = opts.merge!({type: :array})
|
45
55
|
array_validator = _create_validator(key, opts)
|
46
56
|
yield array_validator if block_given?
|
47
57
|
node.add_validator array_validator
|
48
58
|
end
|
49
59
|
|
50
|
-
def
|
51
|
-
|
60
|
+
def has_schema(key:, opts: {})
|
61
|
+
has_attribute(key: key, opts: opts.merge({type: :schema}))
|
62
|
+
end
|
63
|
+
|
64
|
+
################ Methods for generating the schema #########################
|
65
|
+
|
66
|
+
def generate_schema
|
67
|
+
node
|
68
|
+
end
|
69
|
+
|
70
|
+
def register(as:)
|
71
|
+
SchemaLibrary.add_schema(name: as, schema: generate_schema)
|
72
|
+
generate_schema
|
73
|
+
end
|
74
|
+
|
75
|
+
################## Private methods #########################################
|
76
|
+
|
77
|
+
def _prep_schema_opts(schema_name, opts)
|
78
|
+
opts[:type] = :schema
|
79
|
+
opts[:name] = schema_name
|
52
80
|
opts
|
53
81
|
end
|
54
82
|
|
55
|
-
def
|
56
|
-
|
83
|
+
def _set_validator_key(validator, key)
|
84
|
+
validator.key = key
|
57
85
|
end
|
58
86
|
|
59
|
-
def
|
60
|
-
|
87
|
+
def _validator_opts(key, opts)
|
88
|
+
opts[:key] = key
|
89
|
+
glob_opts.merge(opts)
|
61
90
|
end
|
62
91
|
|
63
|
-
def
|
64
|
-
|
92
|
+
def _create_validator(key, opts)
|
93
|
+
ValidatorFactory.get_instance type: opts[:type], opts: _validator_opts(key, opts)
|
65
94
|
end
|
66
95
|
|
67
|
-
def
|
68
|
-
|
96
|
+
def _node_generator(opts = {})
|
97
|
+
self.class.new opts: opts, global_opts: glob_opts
|
69
98
|
end
|
70
99
|
|
71
100
|
def node
|
72
|
-
@node ||= Node.new(opts: _validator_opts(name,
|
101
|
+
@node ||= Node.new(opts: _validator_opts(name, options))
|
73
102
|
end
|
74
103
|
end
|
75
104
|
end
|