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.
- 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
|