dato_json_schema 0.20.8

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.
@@ -0,0 +1,241 @@
1
+ module DataScaffold
2
+ def self.data_sample
3
+ {
4
+ "name" => "cloudnasium"
5
+ }
6
+ end
7
+
8
+ def self.schema_sample
9
+ {
10
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
11
+ "title" => "Example API",
12
+ "description" => "An example API.",
13
+ "type" => [
14
+ "object"
15
+ ],
16
+ "definitions" => {
17
+ "app" => {
18
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
19
+ "title" => "App",
20
+ "description" => "An app.",
21
+ "id" => "schemata/app",
22
+ "type" => [
23
+ "object"
24
+ ],
25
+ "definitions" => {
26
+ "config_vars" => {
27
+ "patternProperties" => {
28
+ "^\\w+$" => {
29
+ "type" => ["null", "string"]
30
+ }
31
+ }
32
+ },
33
+ "contrived" => {
34
+ "allOf" => [
35
+ { "maxLength" => 30 },
36
+ { "minLength" => 3 }
37
+ ],
38
+ "anyOf" => [
39
+ { "minLength" => 3 },
40
+ { "minLength" => 5 }
41
+ ],
42
+ "oneOf" => [
43
+ { "pattern" => "^(foo|aaa)$" },
44
+ { "pattern" => "^(foo|zzz)$" }
45
+ ],
46
+ "not" => { "pattern" => "^$" }
47
+ },
48
+ "contrived_plus" => {
49
+ "allOf" => [
50
+ { "$ref" => "/schemata/app#/definitions/contrived/allOf/0" },
51
+ { "$ref" => "/schemata/app#/definitions/contrived/allOf/1" }
52
+ ],
53
+ "anyOf" => [
54
+ { "$ref" => "/schemata/app#/definitions/contrived/anyOf/0" },
55
+ { "$ref" => "/schemata/app#/definitions/contrived/anyOf/1" }
56
+ ],
57
+ "oneOf" => [
58
+ { "$ref" => "/schemata/app#/definitions/contrived/oneOf/0" },
59
+ { "$ref" => "/schemata/app#/definitions/contrived/oneOf/1" }
60
+ ],
61
+ "not" => {
62
+ "$ref" => "/schemata/app#/definitions/contrived/not"
63
+ }
64
+ },
65
+ "cost" => {
66
+ "description" => "running price of an app",
67
+ "example" => 35.01,
68
+ "maximum" => 1000.00,
69
+ "exclusiveMaximum" => true,
70
+ "minimum" => 0.0,
71
+ "exclusiveMinimum" => false,
72
+ "multipleOf" => 0.01,
73
+ "readOnly" => false,
74
+ "type" => ["number"],
75
+ },
76
+ "flags" => {
77
+ "description" => "flags for an app",
78
+ "example" => ["websockets"],
79
+ "items" => {
80
+ "pattern" => "^[a-z][a-z\\-]*[a-z]$"
81
+ },
82
+ "maxItems" => 10,
83
+ "minItems" => 1,
84
+ "readOnly" => false,
85
+ "type" => ["array"],
86
+ "uniqueItems" => true
87
+ },
88
+ "id" => {
89
+ "description" => "integer identifier of an app",
90
+ "example" => 1,
91
+ "maximum" => 10000,
92
+ "exclusiveMaximum" => false,
93
+ "minimum" => 0,
94
+ "exclusiveMinimum" => true,
95
+ "multipleOf" => 1,
96
+ "readOnly" => true,
97
+ "type" => ["integer"],
98
+ },
99
+ "identity" => {
100
+ "anyOf" => [
101
+ { "$ref" => "/schemata/app#/definitions/id" },
102
+ { "$ref" => "/schemata/app#/definitions/name" },
103
+ ]
104
+ },
105
+ "name" => {
106
+ "default" => "hello-world",
107
+ "description" => "unique name of app",
108
+ "example" => "name",
109
+ "maxLength" => 30,
110
+ "minLength" => 3,
111
+ "pattern" => "^[a-z][a-z0-9-]{3,30}$",
112
+ "readOnly" => false,
113
+ "type" => ["string"]
114
+ },
115
+ "owner" => {
116
+ "description" => "owner of the app",
117
+ "format" => "email",
118
+ "example" => "dwarf@example.com",
119
+ "readOnly" => false,
120
+ "type" => ["string"]
121
+ },
122
+ "production" => {
123
+ "description" => "whether this is a production app",
124
+ "example" => false,
125
+ "readOnly" => false,
126
+ "type" => ["boolean"]
127
+ },
128
+ "role" => {
129
+ "description" => "name of a role on an app",
130
+ "example" => "collaborator",
131
+ "readOnly" => true,
132
+ "type" => ["string"],
133
+ },
134
+ "roles" => {
135
+ "additionalProperties" => true,
136
+ "patternProperties" => {
137
+ "^\\w+$" => {
138
+ "$ref" => "/schemata/app#/definitions/role"
139
+ }
140
+ }
141
+ },
142
+ "ssl" => {
143
+ "description" => "whether this app has SSL termination",
144
+ "example" => false,
145
+ "readOnly" => false,
146
+ "type" => ["boolean"]
147
+ },
148
+ "visibility" => {
149
+ "description" => "the visibility of hte app",
150
+ "enum" => ["private", "public"],
151
+ "example" => false,
152
+ "readOnly" => false,
153
+ "type" => ["string"]
154
+ },
155
+ },
156
+ "properties" => {
157
+ "config_vars" => {
158
+ "$ref" => "/schemata/app#/definitions/config_vars"
159
+ },
160
+ "contrived" => {
161
+ "$ref" => "/schemata/app#/definitions/contrived"
162
+ },
163
+ "cost" => {
164
+ "$ref" => "/schemata/app#/definitions/cost"
165
+ },
166
+ "flags" => {
167
+ "$ref" => "/schemata/app#/definitions/flags"
168
+ },
169
+ "id" => {
170
+ "$ref" => "/schemata/app#/definitions/id"
171
+ },
172
+ "name" => {
173
+ "$ref" => "/schemata/app#/definitions/name"
174
+ },
175
+ "owner" => {
176
+ "$ref" => "/schemata/app#/definitions/owner"
177
+ },
178
+ "production" => {
179
+ "$ref" => "/schemata/app#/definitions/production"
180
+ },
181
+ "ssl" => {
182
+ "$ref" => "/schemata/app#/definitions/ssl"
183
+ },
184
+ "visibility" => {
185
+ "$ref" => "/schemata/app#/definitions/visibility"
186
+ }
187
+ },
188
+ "additionalProperties" => false,
189
+ "dependencies" => {
190
+ "production" => "ssl",
191
+ "ssl" => {
192
+ "properties" => {
193
+ "cost" => {
194
+ "minimum" => 20.0,
195
+ },
196
+ "name" => {
197
+ "$ref" => "/schemata/app#/definitions/name"
198
+ },
199
+ }
200
+ }
201
+ },
202
+ "maxProperties" => 10,
203
+ "minProperties" => 1,
204
+ "required" => ["name"],
205
+ "links" => [
206
+ "description" => "Create a new app.",
207
+ "href" => "/apps",
208
+ "method" => "POST",
209
+ "rel" => "create",
210
+ "schema" => {
211
+ "properties" => {
212
+ "name" => {
213
+ "$ref" => "#/definitions/app/definitions/name"
214
+ },
215
+ }
216
+ },
217
+ "targetSchema" => {
218
+ "$ref" => "#/definitions/app"
219
+ }
220
+ ],
221
+ "media" => {
222
+ "type" => "application/json"
223
+ },
224
+ "pathStart" => "/",
225
+ "readOnly" => false
226
+ }
227
+ },
228
+ "properties" => {
229
+ "app" => {
230
+ "$ref" => "#/definitions/app"
231
+ },
232
+ },
233
+ "links" => [
234
+ {
235
+ "href" => "http://example.com",
236
+ "rel" => "self"
237
+ }
238
+ ]
239
+ }
240
+ end
241
+ end
@@ -0,0 +1,69 @@
1
+ require "test_helper"
2
+
3
+ require "json_pointer"
4
+ require "json_schema"
5
+
6
+ describe JsonPointer::Evaluator do
7
+ before do
8
+ @evaluator = JsonPointer::Evaluator.new(data)
9
+ end
10
+
11
+ it "evaluates pointers according to spec" do
12
+ assert_equal data, @evaluator.evaluate("")
13
+ assert_equal ["bar", "baz"], @evaluator.evaluate("/foo")
14
+ assert_equal "bar", @evaluator.evaluate("/foo/0")
15
+ assert_equal 0, @evaluator.evaluate("/")
16
+ assert_equal 1, @evaluator.evaluate("/a~1b")
17
+ assert_equal 2, @evaluator.evaluate("/c%d")
18
+ assert_equal 3, @evaluator.evaluate("/e^f")
19
+ assert_equal 4, @evaluator.evaluate("/g|h")
20
+ assert_equal 5, @evaluator.evaluate("/i\\j")
21
+ assert_equal 6, @evaluator.evaluate("/k\"l")
22
+ assert_equal 7, @evaluator.evaluate("/ ")
23
+ assert_equal 8, @evaluator.evaluate("/m~0n")
24
+ end
25
+
26
+ it "takes a leading #" do
27
+ assert_equal 0, @evaluator.evaluate("#/")
28
+ end
29
+
30
+ it "returns nils on missing values" do
31
+ assert_nil @evaluator.evaluate("/bar")
32
+ end
33
+
34
+ it "raises when a path doesn't being with /" do
35
+ e = assert_raises(ArgumentError) { @evaluator.evaluate("foo") }
36
+ assert_equal %{Path must begin with a leading "/": foo.}, e.message
37
+ e = assert_raises(ArgumentError) { @evaluator.evaluate("#foo") }
38
+ assert_equal %{Path must begin with a leading "/": #foo.}, e.message
39
+ end
40
+
41
+ it "raises when a non-digit is specified on an array" do
42
+ e = assert_raises(ArgumentError) { @evaluator.evaluate("/foo/bar") }
43
+ assert_equal %{Key operating on an array must be a digit or "-": bar.},
44
+ e.message
45
+ end
46
+
47
+ it "can evaluate on a schema object" do
48
+ schema = JsonSchema.parse!(DataScaffold.schema_sample)
49
+ evaluator = JsonPointer::Evaluator.new(schema)
50
+ res = evaluator.evaluate("#/definitions/app/definitions/contrived/allOf/0")
51
+ assert_kind_of JsonSchema::Schema, res
52
+ assert 30, res.max_length
53
+ end
54
+
55
+ def data
56
+ {
57
+ "foo" => ["bar", "baz"],
58
+ "" => 0,
59
+ "a/b" => 1,
60
+ "c%d" => 2,
61
+ "e^f" => 3,
62
+ "g|h" => 4,
63
+ "i\\j" => 5,
64
+ "k\"l" => 6,
65
+ " " => 7,
66
+ "m~n" => 8
67
+ }
68
+ end
69
+ end
@@ -0,0 +1,45 @@
1
+ require "test_helper"
2
+
3
+ require "json_reference"
4
+
5
+ describe JsonReference::Reference do
6
+ it "expands a reference without a URI" do
7
+ ref = reference("#/definitions")
8
+ assert_nil ref.uri
9
+ assert_equal "#/definitions", ref.pointer
10
+ end
11
+
12
+ it "expands a reference with a URI" do
13
+ ref = reference("http://example.com#/definitions")
14
+ assert_equal URI.parse("http://example.com"), ref.uri
15
+ assert_equal "#/definitions", ref.pointer
16
+ end
17
+
18
+ it "expands just a root sign" do
19
+ ref = reference("#")
20
+ assert_nil ref.uri
21
+ assert_equal "#", ref.pointer
22
+ end
23
+
24
+ it "expands a URI with just a root sign" do
25
+ ref = reference("http://example.com#")
26
+ assert_equal URI.parse("http://example.com"), ref.uri
27
+ assert_equal "#", ref.pointer
28
+ end
29
+
30
+ it "normalizes pointers by adding a root sign prefix" do
31
+ ref = reference("/definitions")
32
+ assert_nil ref.uri
33
+ assert_equal "#/definitions", ref.pointer
34
+ end
35
+
36
+ it "normalizes pointers by stripping a trailing slash" do
37
+ ref = reference("#/definitions/")
38
+ assert_nil ref.uri
39
+ assert_equal "#/definitions", ref.pointer
40
+ end
41
+
42
+ def reference(str)
43
+ JsonReference::Reference.new(str)
44
+ end
45
+ end
@@ -0,0 +1,121 @@
1
+ require "test_helper"
2
+
3
+ require "json_schema"
4
+
5
+ describe JsonSchema::Attributes do
6
+ it "defines copyable attributes" do
7
+ obj = TestAttributes.new
8
+ obj.copyable = "foo"
9
+ assert_equal "foo", obj.copyable
10
+ assert_includes obj.class.copyable_attrs, :@copyable
11
+ end
12
+
13
+ it "defines schema attributes" do
14
+ obj = TestAttributes.new
15
+ obj.schema = "foo"
16
+ assert_equal "foo", obj.schema
17
+ assert_equal({:schema => :schema, :named => :schema_named, :cached => :cached},
18
+ obj.class.schema_attrs)
19
+ end
20
+
21
+ it "defines attributes with default readers" do
22
+ obj = TestAttributes.new
23
+ assert_equal [], obj.copyable_default
24
+
25
+ assert_equal "application/json", obj.copyable_default_with_string
26
+
27
+ hash = obj.copyable_default_with_object
28
+ assert_equal({}, hash)
29
+ ex = if defined?(FrozenError)
30
+ FrozenError
31
+ else
32
+ RuntimeError
33
+ end
34
+
35
+ assert_raises(ex) do
36
+ hash[:x] = 123
37
+ end
38
+
39
+ # This is a check to make sure that the new object is not the same object
40
+ # as the one that we just mutated above. When assigning defaults the module
41
+ # should dup any common data strcutures that it puts in here.
42
+ obj = TestAttributes.new
43
+ hash = obj.copyable_default_with_object
44
+ assert_equal({}, hash)
45
+ end
46
+
47
+ it "inherits attributes when so instructed" do
48
+ obj = TestAttributesDescendant.new
49
+ assert_includes obj.class.copyable_attrs, :@copyable
50
+ end
51
+
52
+ it "allows schema attributes to be indexed but not others" do
53
+ obj = TestAttributes.new
54
+
55
+ obj.copyable = "non-schema"
56
+ obj.schema = "schema"
57
+
58
+ assert_raises NoMethodError do
59
+ assert_nil obj[:copyable]
60
+ end
61
+
62
+ assert_equal "schema", obj[:schema]
63
+ end
64
+
65
+ it "copies attributes with #copy_from" do
66
+ obj = TestAttributes.new
67
+
68
+ obj.copyable = "copyable"
69
+ obj.schema = "schema"
70
+
71
+ obj2 = TestAttributes.new
72
+ obj2.copy_from(obj)
73
+
74
+ assert_equal "copyable", obj2.copyable
75
+ assert_equal "schema", obj2.schema
76
+ end
77
+
78
+ it "initializes attributes with #initialize_attrs" do
79
+ obj = TestAttributes.new
80
+
81
+ # should produce a nil value *without* a Ruby warning
82
+ assert_nil obj.copyable
83
+ assert_nil obj.schema
84
+ end
85
+
86
+ it "cleans cached values when assigning parent attribute" do
87
+ obj = TestAttributes.new
88
+
89
+ obj.cached = "test"
90
+ assert_equal "test_123", obj.cached_parsed
91
+
92
+ obj.cached = "other"
93
+ assert_equal "other_123", obj.cached_parsed
94
+ end
95
+
96
+ class TestAttributes
97
+ include JsonSchema::Attributes
98
+
99
+ def initialize
100
+ initialize_attrs
101
+ end
102
+
103
+ attr_copyable :copyable
104
+
105
+ attr_schema :schema
106
+ attr_schema :schema_named, :schema_name => :named
107
+
108
+ attr_schema :cached, :clear_cache => :@cached_parsed
109
+ def cached_parsed
110
+ @cached_parsed ||= "#{cached}_123"
111
+ end
112
+
113
+ attr_copyable :copyable_default, :default => []
114
+ attr_copyable :copyable_default_with_string, :default => "application/json"
115
+ attr_copyable :copyable_default_with_object, :default => {}
116
+ end
117
+
118
+ class TestAttributesDescendant < TestAttributes
119
+ inherit_attrs
120
+ end
121
+ end