strong_json 0.9.0 → 1.0.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/CHANGELOG.md +4 -0
- data/README.md +68 -16
- data/lib/strong_json/error_reporter.rb +130 -0
- data/lib/strong_json/type.rb +232 -86
- data/lib/strong_json/types.rb +11 -14
- data/lib/strong_json/version.rb +1 -1
- data/lib/strong_json.rb +3 -1
- data/sig/strong_json.rbi +25 -6
- data/sig/type.rbi +55 -28
- data/spec/array_spec.rb +3 -3
- data/spec/basetype_spec.rb +16 -8
- data/spec/enum_spec.rb +87 -9
- data/spec/error_spec.rb +62 -4
- data/spec/json_spec.rb +133 -7
- data/spec/object_spec.rb +122 -57
- data/spec/optional_spec.rb +4 -1
- metadata +3 -2
data/sig/type.rbi
CHANGED
@@ -1,89 +1,116 @@
|
|
1
1
|
module StrongJSON::Type
|
2
2
|
end
|
3
3
|
|
4
|
-
StrongJSON::Type::NONE: any
|
5
|
-
|
6
4
|
module StrongJSON::Type::Match: _Schema<any>
|
7
5
|
def =~: (any) -> bool
|
8
6
|
def ===: (any) -> bool
|
9
7
|
end
|
10
8
|
|
11
|
-
|
9
|
+
module StrongJSON::Type::WithAlias: ::Object
|
10
|
+
@alias: Symbol?
|
11
|
+
def alias: -> Symbol?
|
12
|
+
def with_alias: (Symbol) -> self
|
13
|
+
end
|
14
|
+
|
15
|
+
type StrongJSON::base_type_name = :any | :number | :string | :boolean | :numeric | :symbol
|
12
16
|
|
13
17
|
class StrongJSON::Type::Base<'a>
|
14
18
|
include Match
|
19
|
+
include WithAlias
|
15
20
|
|
16
21
|
attr_reader type: base_type_name
|
17
22
|
|
18
23
|
def initialize: (base_type_name) -> any
|
19
24
|
def test: (any) -> bool
|
20
|
-
def coerce: (any, ?path:
|
25
|
+
def coerce: (any, ?path: ErrorPath) -> 'a
|
21
26
|
end
|
22
27
|
|
23
28
|
class StrongJSON::Type::Optional<'t>
|
24
29
|
include Match
|
30
|
+
include WithAlias
|
25
31
|
|
26
|
-
|
32
|
+
attr_reader type: _Schema<'t>
|
27
33
|
|
28
34
|
def initialize: (_Schema<'t>) -> any
|
29
|
-
def coerce: (any, ?path:
|
35
|
+
def coerce: (any, ?path: ErrorPath) -> ('t | nil)
|
30
36
|
end
|
31
37
|
|
32
38
|
class StrongJSON::Type::Literal<'t>
|
33
39
|
include Match
|
40
|
+
include WithAlias
|
34
41
|
|
35
42
|
attr_reader value: 't
|
36
43
|
|
37
44
|
def initialize: ('t) -> any
|
38
|
-
def coerce: (any, ?path:
|
45
|
+
def coerce: (any, ?path: ErrorPath) -> 't
|
39
46
|
end
|
40
47
|
|
41
48
|
class StrongJSON::Type::Array<'t>
|
42
49
|
include Match
|
50
|
+
include WithAlias
|
43
51
|
|
44
|
-
|
52
|
+
attr_reader type: _Schema<'t>
|
45
53
|
|
46
54
|
def initialize: (_Schema<'t>) -> any
|
47
|
-
def coerce: (any, ?path:
|
55
|
+
def coerce: (any, ?path: ErrorPath) -> ::Array<'t>
|
48
56
|
end
|
49
57
|
|
50
58
|
class StrongJSON::Type::Object<'t>
|
51
59
|
include Match
|
60
|
+
include WithAlias
|
52
61
|
|
53
|
-
|
62
|
+
attr_reader fields: Hash<Symbol, _Schema<any>>
|
63
|
+
attr_reader ignored_attributes: :any | Set<Symbol> | nil
|
64
|
+
attr_reader prohibited_attributes: Set<Symbol>
|
54
65
|
|
55
|
-
def initialize: (Hash<Symbol, _Schema<'t
|
56
|
-
def coerce: (any, ?path:
|
57
|
-
|
58
|
-
def
|
59
|
-
def
|
66
|
+
def initialize: (Hash<Symbol, _Schema<'t>>, ignored_attributes: :any | Set<Symbol> | nil, prohibited_attributes: Set<Symbol>) -> any
|
67
|
+
def coerce: (any, ?path: ErrorPath) -> 't
|
68
|
+
|
69
|
+
def ignore: (:any | Set<Symbol> | nil) -> self
|
70
|
+
def ignore!: (:any | Set<Symbol> | nil) -> self
|
71
|
+
def prohibit: (Set<Symbol>) -> self
|
72
|
+
def prohibit!: (Set<Symbol>) -> self
|
73
|
+
def update_fields: <'x> { (Hash<Symbol, _Schema<any>>) -> void } -> Object<'x>
|
60
74
|
end
|
61
75
|
|
76
|
+
type StrongJSON::Type::detector = ^(any) -> _Schema<any>?
|
77
|
+
|
62
78
|
class StrongJSON::Type::Enum<'t>
|
63
79
|
include Match
|
80
|
+
include WithAlias
|
64
81
|
|
65
82
|
attr_reader types: ::Array<_Schema<any>>
|
83
|
+
attr_reader detector: detector?
|
66
84
|
|
67
|
-
def initialize: (::Array<_Schema<any
|
68
|
-
def coerce: (any, ?path:
|
85
|
+
def initialize: (::Array<_Schema<any>>, ?detector?) -> any
|
86
|
+
def coerce: (any, ?path: ErrorPath) -> 't
|
69
87
|
end
|
70
88
|
|
71
|
-
class StrongJSON::Type::
|
72
|
-
attr_reader
|
73
|
-
attr_reader
|
74
|
-
|
89
|
+
class StrongJSON::Type::ErrorPath
|
90
|
+
attr_reader type: _Schema<any>
|
91
|
+
attr_reader parent: [Symbol | Integer | nil, instance]?
|
92
|
+
|
93
|
+
def initialize: (type: _Schema<any>, parent: [Symbol | Integer | nil, instance]?) -> any
|
94
|
+
def (constructor) dig: (key: Symbol | Integer, type: _Schema<any>) -> self
|
95
|
+
def (constructor) expand: (type: _Schema<any>) -> self
|
75
96
|
|
76
|
-
def
|
97
|
+
def self.root: (_Schema<any>) -> instance
|
98
|
+
def root?: -> bool
|
77
99
|
end
|
78
100
|
|
79
|
-
class StrongJSON::Type::
|
80
|
-
attr_reader path:
|
101
|
+
class StrongJSON::Type::TypeError < StandardError
|
102
|
+
attr_reader path: ErrorPath
|
81
103
|
attr_reader value: any
|
82
104
|
|
83
|
-
def initialize: (path:
|
105
|
+
def initialize: (path: ErrorPath, value: any) -> any
|
106
|
+
def type: -> _Schema<any>
|
84
107
|
end
|
85
108
|
|
86
|
-
class StrongJSON::Type::
|
87
|
-
attr_reader
|
88
|
-
|
109
|
+
class StrongJSON::Type::UnexpectedAttributeError < StandardError
|
110
|
+
attr_reader path: ErrorPath
|
111
|
+
attr_reader attribute: Symbol
|
112
|
+
|
113
|
+
def initialize: (path: ErrorPath, attribute: Symbol) -> any
|
114
|
+
def type: -> _Schema<any>
|
89
115
|
end
|
116
|
+
|
data/spec/array_spec.rb
CHANGED
@@ -21,19 +21,19 @@ describe StrongJSON::Type::Array, "#coerce" do
|
|
21
21
|
it "reject non array" do
|
22
22
|
type = StrongJSON::Type::Array.new(StrongJSON::Type::Base.new(:number))
|
23
23
|
|
24
|
-
expect { type.coerce({}) }.to raise_error(StrongJSON::Type::
|
24
|
+
expect { type.coerce({}) }.to raise_error(StrongJSON::Type::TypeError)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "reject membership" do
|
28
28
|
type = StrongJSON::Type::Array.new(StrongJSON::Type::Base.new(:number))
|
29
29
|
|
30
|
-
expect { type.coerce(["a"]) }.to raise_error(StrongJSON::Type::
|
30
|
+
expect { type.coerce(["a"]) }.to raise_error(StrongJSON::Type::TypeError)
|
31
31
|
end
|
32
32
|
|
33
33
|
it "rejects nil" do
|
34
34
|
type = StrongJSON::Type::Array.new(StrongJSON::Type::Base.new(:number))
|
35
35
|
|
36
|
-
expect { type.coerce(nil) }.to raise_error(StrongJSON::Type::
|
36
|
+
expect { type.coerce(nil) }.to raise_error(StrongJSON::Type::TypeError)
|
37
37
|
end
|
38
38
|
|
39
39
|
describe "=~" do
|
data/spec/basetype_spec.rb
CHANGED
@@ -2,14 +2,6 @@ require "strong_json"
|
|
2
2
|
|
3
3
|
describe StrongJSON::Type::Base do
|
4
4
|
describe "#test" do
|
5
|
-
context ":ignored" do
|
6
|
-
let (:type) { StrongJSON::Type::Base.new(:ignored) }
|
7
|
-
|
8
|
-
it "can not be placed on toplevel" do
|
9
|
-
expect { type.coerce(3, path: []) }.to raise_error(StrongJSON::Type::IllegalTypeError)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
5
|
context ":number" do
|
14
6
|
let (:type) { StrongJSON::Type::Base.new(:number) }
|
15
7
|
|
@@ -178,4 +170,20 @@ describe StrongJSON::Type::Base do
|
|
178
170
|
end
|
179
171
|
end
|
180
172
|
end
|
173
|
+
|
174
|
+
describe "alias" do
|
175
|
+
let (:type) { StrongJSON::Type::Base.new(:number) }
|
176
|
+
|
177
|
+
it "returns nil" do
|
178
|
+
expect(type.alias).to be_nil
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "with_alias" do
|
182
|
+
let (:aliased_type) { type.with_alias(:count) }
|
183
|
+
|
184
|
+
it "returns alias name" do
|
185
|
+
expect(aliased_type.alias).to eq(:count)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
181
189
|
end
|
data/spec/enum_spec.rb
CHANGED
@@ -22,14 +22,28 @@ describe StrongJSON::Type::Enum do
|
|
22
22
|
|
23
23
|
describe "#coerce" do
|
24
24
|
let (:type) {
|
25
|
-
StrongJSON::Type::Enum.new(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
StrongJSON::Type::Enum.new(
|
26
|
+
[
|
27
|
+
StrongJSON::Type::Object.new(
|
28
|
+
{
|
29
|
+
id: StrongJSON::Type::Literal.new("id1"),
|
30
|
+
value: StrongJSON::Type::Base.new(:string)
|
31
|
+
},
|
32
|
+
ignored_attributes: nil,
|
33
|
+
prohibited_attributes: Set.new
|
34
|
+
),
|
35
|
+
StrongJSON::Type::Object.new(
|
36
|
+
{
|
37
|
+
id: StrongJSON::Type::Base.new(:string),
|
38
|
+
value: StrongJSON::Type::Base.new(:symbol)
|
39
|
+
},
|
40
|
+
ignored_attributes: nil,
|
41
|
+
prohibited_attributes: Set.new
|
42
|
+
),
|
43
|
+
StrongJSON::Type::Optional.new(StrongJSON::Type::Literal.new(3)),
|
44
|
+
StrongJSON::Type::Literal.new(false),
|
45
|
+
]
|
46
|
+
)
|
33
47
|
}
|
34
48
|
|
35
49
|
it "returns object with string value" do
|
@@ -49,7 +63,71 @@ describe StrongJSON::Type::Enum do
|
|
49
63
|
end
|
50
64
|
|
51
65
|
it "raises error" do
|
52
|
-
expect { type.coerce(3.14) }.to raise_error(StrongJSON::Type::
|
66
|
+
expect { type.coerce(3.14) }.to raise_error(StrongJSON::Type::TypeError)
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with detector" do
|
70
|
+
let(:regexp_pattern) {
|
71
|
+
StrongJSON::Type::Object.new(
|
72
|
+
{
|
73
|
+
regexp: StrongJSON::Type::Base.new(:string),
|
74
|
+
option: StrongJSON::Type::Base.new(:string),
|
75
|
+
},
|
76
|
+
ignored_attributes: nil,
|
77
|
+
prohibited_attributes: Set.new
|
78
|
+
)
|
79
|
+
}
|
80
|
+
|
81
|
+
let(:literal_pattern) {
|
82
|
+
StrongJSON::Type::Object.new(
|
83
|
+
{
|
84
|
+
literal: StrongJSON::Type::Base.new(:string)
|
85
|
+
},
|
86
|
+
ignored_attributes: nil,
|
87
|
+
prohibited_attributes: Set.new
|
88
|
+
)
|
89
|
+
}
|
90
|
+
|
91
|
+
let(:type) {
|
92
|
+
StrongJSON::Type::Enum.new(
|
93
|
+
[
|
94
|
+
regexp_pattern,
|
95
|
+
literal_pattern,
|
96
|
+
StrongJSON::Type::Base.new(:string),
|
97
|
+
],
|
98
|
+
-> (value) {
|
99
|
+
case value
|
100
|
+
when Hash
|
101
|
+
case
|
102
|
+
when value.key?(:regexp)
|
103
|
+
regexp_pattern
|
104
|
+
when value.key?(:literal)
|
105
|
+
literal_pattern
|
106
|
+
end
|
107
|
+
end
|
108
|
+
}
|
109
|
+
)
|
110
|
+
}
|
111
|
+
|
112
|
+
it "accepts regexp pattern" do
|
113
|
+
expect(type.coerce({ regexp: "foo", option: "x" })).to eq({regexp: "foo", option: "x"})
|
114
|
+
end
|
115
|
+
|
116
|
+
it "raises error with base type" do
|
117
|
+
expect {
|
118
|
+
type.coerce({ regexp: "foo", option: 123 })
|
119
|
+
}.to raise_error(StrongJSON::Type::TypeError) {|x|
|
120
|
+
expect(x.type).to be_a(StrongJSON::Type::Base)
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
it "raises error with enum type" do
|
125
|
+
expect {
|
126
|
+
type.coerce({ option: 3 })
|
127
|
+
}.to raise_error(StrongJSON::Type::TypeError) {|x|
|
128
|
+
expect(x.type).to eq(type)
|
129
|
+
}
|
130
|
+
end
|
53
131
|
end
|
54
132
|
end
|
55
133
|
end
|
data/spec/error_spec.rb
CHANGED
@@ -1,8 +1,66 @@
|
|
1
|
-
|
1
|
+
require "strong_json"
|
2
|
+
|
3
|
+
describe StrongJSON::Type::ErrorPath do
|
4
|
+
ErrorPath = StrongJSON::Type::ErrorPath
|
2
5
|
include StrongJSON::Types
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
+
describe "root path" do
|
8
|
+
let(:path) { ErrorPath.root(string) }
|
9
|
+
|
10
|
+
it "does not have parent" do
|
11
|
+
expect(path.parent).to be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "has type" do
|
15
|
+
expect(path.type).to be_a(StrongJSON::Type::Base)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "prints" do
|
19
|
+
expect(path.to_s).to eq("$")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "appended path" do
|
24
|
+
let(:path) {
|
25
|
+
ErrorPath.root(object(foo: array(number)))
|
26
|
+
.dig(key: :foo, type: array(number))
|
27
|
+
.dig(key: 0, type: number)
|
28
|
+
}
|
29
|
+
|
30
|
+
it "does have parent" do
|
31
|
+
expect(path.parent).to be_a(Array)
|
32
|
+
expect(path.parent[0]).to eq(0)
|
33
|
+
expect(path.parent[1]).to be_a(ErrorPath)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "has type" do
|
37
|
+
expect(path.type).to be_a(StrongJSON::Type::Base)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "prints" do
|
41
|
+
expect(path.to_s).to eq("$.foo[0]")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "expanded path" do
|
46
|
+
let(:path) {
|
47
|
+
ErrorPath.root(array(enum(number, string)))
|
48
|
+
.dig(key: 0, type: enum(number, string))
|
49
|
+
.expand(type: string)
|
50
|
+
}
|
51
|
+
|
52
|
+
it "does have parent" do
|
53
|
+
expect(path.parent).to be_a(Array)
|
54
|
+
expect(path.parent[0]).to be_nil
|
55
|
+
expect(path.parent[1]).to be_a(ErrorPath)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "has type" do
|
59
|
+
expect(path.type).to be_a(StrongJSON::Type::Base)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "prints" do
|
63
|
+
expect(path.to_s).to eq("$[0]")
|
64
|
+
end
|
7
65
|
end
|
8
66
|
end
|
data/spec/json_spec.rb
CHANGED
@@ -3,11 +3,90 @@ require "strong_json"
|
|
3
3
|
describe "StrongJSON.new" do
|
4
4
|
it "tests the structure of a JSON object" do
|
5
5
|
s = StrongJSON.new do
|
6
|
-
let :item, object(name: string, count: numeric, price: numeric
|
7
|
-
let :
|
6
|
+
let :item, object(name: string, count: numeric, price: numeric).ignore(Set.new([:comment]))
|
7
|
+
let :items, array(item)
|
8
|
+
let :checkout,
|
9
|
+
object(items: items,
|
10
|
+
change: optional(number),
|
11
|
+
type: enum(literal(1), symbol),
|
12
|
+
customer: object?(
|
13
|
+
name: string,
|
14
|
+
id: string,
|
15
|
+
birthday: string,
|
16
|
+
gender: enum(literal("man"), literal("woman"), literal("other")),
|
17
|
+
phone: string
|
18
|
+
)
|
19
|
+
)
|
8
20
|
end
|
9
21
|
|
10
|
-
expect(
|
22
|
+
expect(
|
23
|
+
s.checkout.coerce(items: [{ name: "test", count: 1, price: "2.33", comment: "dummy" }], type: 1)
|
24
|
+
).to eq(items: [ { name: "test", count: 1, price: "2.33" }], type: 1, change: nil, customer: nil)
|
25
|
+
|
26
|
+
expect {
|
27
|
+
s.checkout.coerce(items: [{ name: "test", count: 1, price: [], comment: "dummy" }], type: 1)
|
28
|
+
}.to raise_error(StrongJSON::Type::TypeError) {|e|
|
29
|
+
expect(e.path.to_s).to eq("$.items[0].price")
|
30
|
+
expect(e.type).to be_a(StrongJSON::Type::Base)
|
31
|
+
|
32
|
+
expect(e.message).to eq("TypeError at $.items[0].price: expected=numeric, value=[]")
|
33
|
+
reporter = StrongJSON::ErrorReporter.new(path: e.path)
|
34
|
+
expect(reporter.to_s).to eq(<<MSG.chop)
|
35
|
+
"price" expected to be numeric
|
36
|
+
0 expected to be item
|
37
|
+
"items" expected to be items
|
38
|
+
$ expected to be checkout
|
39
|
+
|
40
|
+
Where:
|
41
|
+
item = { "name": string, "count": numeric, "price": numeric }
|
42
|
+
items = array(item)
|
43
|
+
checkout = {
|
44
|
+
"items": items,
|
45
|
+
"change": optional(number),
|
46
|
+
"type": enum(1, symbol),
|
47
|
+
"customer": optional(
|
48
|
+
{
|
49
|
+
"name": string,
|
50
|
+
"id": string,
|
51
|
+
"birthday": string,
|
52
|
+
"gender": enum("man", "woman", "other"),
|
53
|
+
"phone": string
|
54
|
+
}
|
55
|
+
)
|
56
|
+
}
|
57
|
+
MSG
|
58
|
+
}
|
59
|
+
|
60
|
+
expect {
|
61
|
+
s.checkout.coerce(items: [], change: "", type: 1)
|
62
|
+
}.to raise_error(StrongJSON::Type::TypeError) {|e|
|
63
|
+
expect(e.path.to_s).to eq("$.change")
|
64
|
+
expect(e.type).to be_a(StrongJSON::Type::Base)
|
65
|
+
|
66
|
+
expect(e.message).to eq('TypeError at $.change: expected=number, value=""')
|
67
|
+
reporter = StrongJSON::ErrorReporter.new(path: e.path)
|
68
|
+
expect(reporter.to_s).to eq(<<MSG.chop)
|
69
|
+
Expected to be number
|
70
|
+
"change" expected to be optional(number)
|
71
|
+
$ expected to be checkout
|
72
|
+
|
73
|
+
Where:
|
74
|
+
checkout = {
|
75
|
+
"items": items,
|
76
|
+
"change": optional(number),
|
77
|
+
"type": enum(1, symbol),
|
78
|
+
"customer": optional(
|
79
|
+
{
|
80
|
+
"name": string,
|
81
|
+
"id": string,
|
82
|
+
"birthday": string,
|
83
|
+
"gender": enum("man", "woman", "other"),
|
84
|
+
"phone": string
|
85
|
+
}
|
86
|
+
)
|
87
|
+
}
|
88
|
+
MSG
|
89
|
+
}
|
11
90
|
end
|
12
91
|
|
13
92
|
it "tests enums" do
|
@@ -15,11 +94,58 @@ describe "StrongJSON.new" do
|
|
15
94
|
let :enum, object(e1: enum(boolean, number), e2: enum?(literal(1), literal(2)))
|
16
95
|
end
|
17
96
|
|
18
|
-
expect(s.enum.coerce(e1: false)).to eq(e1: false)
|
19
|
-
expect(s.enum.coerce(e1: 0)).to eq(e1: 0)
|
97
|
+
expect(s.enum.coerce(e1: false)).to eq(e1: false, e2: nil)
|
98
|
+
expect(s.enum.coerce(e1: 0)).to eq(e1: 0, e2: nil)
|
20
99
|
expect(s.enum.coerce(e1: 0, e2: 1)).to eq(e1: 0, e2: 1)
|
21
100
|
expect(s.enum.coerce(e1: 0, e2: 2)).to eq(e1: 0, e2: 2)
|
22
|
-
expect{ s.enum.coerce(e1: "", e2: 3) }.to raise_error(StrongJSON::Type::
|
23
|
-
|
101
|
+
expect{ s.enum.coerce(e1: "", e2: 3) }.to raise_error(StrongJSON::Type::TypeError) {|e|
|
102
|
+
expect(e.path.to_s).to eq("$.e1")
|
103
|
+
}
|
104
|
+
expect{ s.enum.coerce(e1: false, e2: "") }.to raise_error(StrongJSON::Type::TypeError) {|e|
|
105
|
+
expect(e.path.to_s).to eq("$.e2")
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#let" do
|
110
|
+
it "defines aliased type" do
|
111
|
+
s = StrongJSON.new do
|
112
|
+
let :count, number
|
113
|
+
let :age, number
|
114
|
+
end
|
115
|
+
|
116
|
+
expect(s.count.alias).to eq(:count)
|
117
|
+
expect(s.age.alias).to eq(:age)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "pretty print" do
|
122
|
+
s = StrongJSON.new do
|
123
|
+
let :regexp_pattern, object(pattern: string, multiline: boolean?, case_sensitive: boolean?)
|
124
|
+
let :token_pattern, object(token: string, case_sensitive: boolean?)
|
125
|
+
let :literal_pattern, object(literal: string)
|
126
|
+
let :string_pattern, string
|
127
|
+
let :pattern, enum(regexp_pattern, token_pattern, literal_pattern, string_pattern, string?)
|
128
|
+
|
129
|
+
let :rule, object(pattern: pattern, glob: enum?(string, array(string)))
|
130
|
+
end
|
131
|
+
|
132
|
+
expect { s.rule.coerce({ pattern: { pattern: 3 } }) }.to raise_error(StrongJSON::Type::TypeError) {|e|
|
133
|
+
expect(e.message).to eq("TypeError at $.pattern: expected=pattern, value={:pattern=>3}")
|
134
|
+
reporter = StrongJSON::ErrorReporter.new(path: e.path)
|
135
|
+
expect(reporter.to_s).to eq(<<MSG.chop)
|
136
|
+
"pattern" expected to be pattern
|
137
|
+
$ expected to be rule
|
138
|
+
|
139
|
+
Where:
|
140
|
+
pattern = enum(
|
141
|
+
regexp_pattern,
|
142
|
+
token_pattern,
|
143
|
+
literal_pattern,
|
144
|
+
string_pattern,
|
145
|
+
optional(string)
|
146
|
+
)
|
147
|
+
rule = { "pattern": pattern, "glob": optional(enum(string, array(string))) }
|
148
|
+
MSG
|
149
|
+
}
|
24
150
|
end
|
25
151
|
end
|