json_schema 0.0.7

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,149 @@
1
+ require "test_helper"
2
+
3
+ require "json_schema"
4
+
5
+ describe JsonSchema::ReferenceExpander do
6
+ it "expands references" do
7
+ assert expand
8
+
9
+ # this was always a fully-defined property
10
+ referenced = @schema.definitions["app"]
11
+ # this used to be a $ref
12
+ reference = @schema.properties["app"]
13
+
14
+ assert_nil reference.reference
15
+ assert_equal referenced.description, reference.description
16
+ assert_equal referenced.id, reference.id
17
+ assert_equal referenced.type, reference.type
18
+ assert_equal referenced.uri, reference.uri
19
+ end
20
+
21
+ it "will expand anyOf" do
22
+ assert expand
23
+ schema = @schema.properties["app"].definitions["contrived_plus"]
24
+ assert_equal 3, schema.any_of[0].min_length
25
+ assert_equal 5, schema.any_of[1].min_length
26
+ end
27
+
28
+ it "will expand allOf" do
29
+ assert expand
30
+ schema = @schema.properties["app"].definitions["contrived_plus"]
31
+ assert_equal 30, schema.all_of[0].max_length
32
+ assert_equal 3, schema.all_of[1].min_length
33
+ end
34
+
35
+ it "will expand dependencies" do
36
+ assert expand
37
+ schema = @schema.properties["app"].dependencies["ssl"].properties["name"]
38
+ assert_equal ["string"], schema.type
39
+ end
40
+
41
+ it "will expand items list schema" do
42
+ pointer("#/definitions/app/definitions/flags").merge!(
43
+ "items" => {
44
+ "$ref" => "#/definitions/app/definitions/name"
45
+ }
46
+ )
47
+ assert expand
48
+ schema = @schema.properties["app"].properties["flags"].items
49
+ assert_equal ["string"], schema.type
50
+ end
51
+
52
+ it "will expand items tuple schema" do
53
+ pointer("#/definitions/app/definitions/flags").merge!(
54
+ "items" => [
55
+ { "$ref" => "#/definitions/app/definitions/name" },
56
+ { "$ref" => "#/definitions/app/definitions/owner" }
57
+ ]
58
+ )
59
+ assert expand
60
+ schema0 = @schema.properties["app"].properties["flags"].items[0]
61
+ schema1 = @schema.properties["app"].properties["flags"].items[0]
62
+ assert_equal ["string"], schema0.type
63
+ assert_equal ["string"], schema1.type
64
+ end
65
+
66
+ it "will expand oneOf" do
67
+ assert expand
68
+ schema = @schema.properties["app"].definitions["contrived_plus"]
69
+ assert_equal /^(foo|aaa)$/, schema.one_of[0].pattern
70
+ assert_equal /^(foo|zzz)$/, schema.one_of[1].pattern
71
+ end
72
+
73
+ it "will expand not" do
74
+ assert expand
75
+ schema = @schema.properties["app"].definitions["contrived_plus"]
76
+ assert_equal /^$/, schema.not.pattern
77
+ end
78
+
79
+ it "will expand patternProperties" do
80
+ assert expand
81
+ # value ([1]) of the #first tuple in hash
82
+ schema = @schema.properties["app"].definitions["roles"].
83
+ pattern_properties.first[1]
84
+ assert_equal ["string"], schema.type
85
+ end
86
+
87
+ it "will expand hyperschema link schemas" do
88
+ assert expand
89
+ schema = @schema.properties["app"].links[0].schema.properties["name"]
90
+ assert_equal ["string"], schema.type
91
+ end
92
+
93
+ it "will perform multiple passes to resolve all references" do
94
+ schema_sample["properties"] = {
95
+ "app" => {
96
+ "$ref" => "#/properties/my-app"
97
+ },
98
+ "my-app" => {
99
+ "$ref" => "#/definitions/app"
100
+ }
101
+ }
102
+ assert expand
103
+ end
104
+
105
+ it "errors on a JSON Pointer that can't be resolved" do
106
+ schema_sample["properties"]["app"] = {
107
+ "$ref" => "#/definitions/nope"
108
+ }
109
+ refute expand
110
+ assert_includes error_messages,
111
+ %{Couldn't resolve pointer "#/definitions/nope".}
112
+ end
113
+
114
+ it "errors on a schema that can't be resolved" do
115
+ schema_sample["properties"]["app"] = {
116
+ "$ref" => "/schemata/user#/definitions/name"
117
+ }
118
+ refute expand
119
+ assert_includes error_messages,
120
+ %{Couldn't resolve references (possible circular dependency): /schemata/user#/definitions/name.}
121
+ end
122
+
123
+ it "errors on a circular reference" do
124
+ schema_sample["definitions"]["app"] = {
125
+ "$ref" => "#/properties/app"
126
+ }
127
+ refute expand
128
+ assert_includes error_messages,
129
+ %{Couldn't resolve references (possible circular dependency): #/definitions/app.}
130
+ end
131
+
132
+ def error_messages
133
+ @expander.errors.map { |e| e.message }
134
+ end
135
+
136
+ def pointer(path)
137
+ JsonPointer.evaluate(schema_sample, path)
138
+ end
139
+
140
+ def schema_sample
141
+ @schema_sample ||= DataScaffold.schema_sample
142
+ end
143
+
144
+ def expand
145
+ @schema = JsonSchema::Parser.new.parse!(schema_sample)
146
+ @expander = JsonSchema::ReferenceExpander.new
147
+ @expander.expand(@schema)
148
+ end
149
+ end
@@ -0,0 +1,606 @@
1
+ require "test_helper"
2
+
3
+ require "json_schema"
4
+
5
+ describe JsonSchema::Validator do
6
+ it "can find data valid" do
7
+ assert validate
8
+ end
9
+
10
+ it "validates enum successfully" do
11
+ pointer("#/definitions/app/definitions/visibility").merge!(
12
+ "enum" => ["private", "public"]
13
+ )
14
+ data_sample["visibility"] = "public"
15
+ assert validate
16
+ end
17
+
18
+ it "validates enum unsuccessfully" do
19
+ pointer("#/definitions/app/definitions/visibility").merge!(
20
+ "enum" => ["private", "public"]
21
+ )
22
+ data_sample["visibility"] = "personal"
23
+ refute validate
24
+ assert_includes error_messages,
25
+ %{Expected data to be a member of enum ["private", "public"], value was: personal.}
26
+ end
27
+
28
+ it "validates type successfully" do
29
+ pointer("#/definitions/app").merge!(
30
+ "type" => ["object"]
31
+ )
32
+ @data_sample = { "name" => "cloudnasium" }
33
+ assert validate
34
+ end
35
+
36
+ it "validates type unsuccessfully" do
37
+ pointer("#/definitions/app").merge!(
38
+ "type" => ["object"]
39
+ )
40
+ @data_sample = 4
41
+ refute validate
42
+ assert_includes error_messages,
43
+ %{Expected data to be of type "object"; value was: 4.}
44
+ end
45
+
46
+ it "validates items with list successfully" do
47
+ pointer("#/definitions/app/definitions/flags").merge!(
48
+ "items" => {
49
+ "pattern" => "^[a-z][a-z\\-]*[a-z]$"
50
+ }
51
+ )
52
+ data_sample["flags"] = ["websockets"]
53
+ assert validate
54
+ end
55
+
56
+ it "validates items with list unsuccessfully" do
57
+ pointer("#/definitions/app/definitions/flags").merge!(
58
+ "items" => {
59
+ "pattern" => "^[a-z][a-z\\-]*[a-z]$"
60
+ }
61
+ )
62
+ data_sample["flags"] = ["1337"]
63
+ refute validate
64
+ assert_includes error_messages,
65
+ %{Expected string to match pattern "/^[a-z][a-z\\-]*[a-z]$/", value was: 1337.}
66
+ end
67
+
68
+ it "validates items with tuple successfully" do
69
+ pointer("#/definitions/app/definitions/flags").merge!(
70
+ "items" => [
71
+ { "enum" => ["bamboo", "cedar"] },
72
+ { "enum" => ["http", "https"] }
73
+ ]
74
+ )
75
+ data_sample["flags"] = ["cedar", "https"]
76
+ assert validate
77
+ end
78
+
79
+ it "validates items with tuple successfully with additionalItems" do
80
+ pointer("#/definitions/app/definitions/flags").merge!(
81
+ "additionalItems" => true,
82
+ "items" => [
83
+ { "enum" => ["bamboo", "cedar"] },
84
+ { "enum" => ["http", "https"] }
85
+ ]
86
+ )
87
+ data_sample["flags"] = ["cedar", "https", "websockets"]
88
+ assert validate
89
+ end
90
+
91
+ it "validates items with tuple unsuccessfully for not enough items" do
92
+ pointer("#/definitions/app/definitions/flags").merge!(
93
+ "items" => [
94
+ { "enum" => ["bamboo", "cedar"] },
95
+ { "enum" => ["http", "https"] }
96
+ ]
97
+ )
98
+ data_sample["flags"] = ["cedar"]
99
+ refute validate
100
+ assert_includes error_messages,
101
+ %{Expected array to have at least 2 item(s), had 1 item(s).}
102
+ end
103
+
104
+ it "validates items with tuple unsuccessfully for too many items" do
105
+ pointer("#/definitions/app/definitions/flags").merge!(
106
+ "additionalItems" => false,
107
+ "items" => [
108
+ { "enum" => ["bamboo", "cedar"] },
109
+ { "enum" => ["http", "https"] }
110
+ ]
111
+ )
112
+ data_sample["flags"] = ["cedar", "https", "websockets"]
113
+ refute validate
114
+ assert_includes error_messages,
115
+ %{Expected array to have no more than 2 item(s), had 3 item(s).}
116
+ end
117
+
118
+ it "validates items with tuple unsuccessfully for non-conforming items" do
119
+ pointer("#/definitions/app/definitions/flags").merge!(
120
+ "additionalItems" => false,
121
+ "items" => [
122
+ { "enum" => ["bamboo", "cedar"] },
123
+ { "enum" => ["http", "https"] }
124
+ ]
125
+ )
126
+ data_sample["flags"] = ["cedar", "1337"]
127
+ refute validate
128
+ assert_includes error_messages,
129
+ %{Expected data to be a member of enum ["http", "https"], value was: 1337.}
130
+ end
131
+
132
+ it "validates maxItems successfully" do
133
+ pointer("#/definitions/app/definitions/flags").merge!(
134
+ "maxItems" => 10
135
+ )
136
+ data_sample["flags"] = (0...10).to_a
137
+ assert validate
138
+ end
139
+
140
+ it "validates maxItems unsuccessfully" do
141
+ pointer("#/definitions/app/definitions/flags").merge!(
142
+ "maxItems" => 10
143
+ )
144
+ data_sample["flags"] = (0...11).to_a
145
+ refute validate
146
+ assert_includes error_messages,
147
+ %{Expected array to have no more than 10 item(s), had 11 item(s).}
148
+ end
149
+
150
+ it "validates minItems successfully" do
151
+ pointer("#/definitions/app/definitions/flags").merge!(
152
+ "minItems" => 1
153
+ )
154
+ data_sample["flags"] = ["websockets"]
155
+ assert validate
156
+ end
157
+
158
+ it "validates minItems unsuccessfully" do
159
+ pointer("#/definitions/app/definitions/flags").merge!(
160
+ "minItems" => 1
161
+ )
162
+ data_sample["flags"] = []
163
+ refute validate
164
+ assert_includes error_messages,
165
+ %{Expected array to have at least 1 item(s), had 0 item(s).}
166
+ end
167
+
168
+ it "validates uniqueItems successfully" do
169
+ pointer("#/definitions/app/definitions/flags").merge!(
170
+ "uniqueItems" => true
171
+ )
172
+ data_sample["flags"] = ["websockets"]
173
+ assert validate
174
+ end
175
+
176
+ it "validates uniqueItems unsuccessfully" do
177
+ pointer("#/definitions/app/definitions/flags").merge!(
178
+ "uniqueItems" => true
179
+ )
180
+ data_sample["flags"] = ["websockets", "websockets"]
181
+ refute validate
182
+ assert_includes error_messages,
183
+ %{Expected array items to be unique, but duplicate items were found.}
184
+ end
185
+
186
+ it "validates maximum for an integer with exclusiveMaximum false" do
187
+ pointer("#/definitions/app/definitions/id").merge!(
188
+ "exclusiveMaximum" => false,
189
+ "maximum" => 10
190
+ )
191
+ data_sample["id"] = 11
192
+ refute validate
193
+ assert_includes error_messages,
194
+ %{Expected data to be smaller than maximum 10 (exclusive: false), value was: 11.}
195
+ end
196
+
197
+ it "validates maximum for an integer with exclusiveMaximum true" do
198
+ pointer("#/definitions/app/definitions/id").merge!(
199
+ "exclusiveMaximum" => true,
200
+ "maximum" => 10
201
+ )
202
+ data_sample["id"] = 10
203
+ refute validate
204
+ assert_includes error_messages,
205
+ %{Expected data to be smaller than maximum 10 (exclusive: true), value was: 10.}
206
+ end
207
+
208
+ it "validates maximum for a number with exclusiveMaximum false" do
209
+ pointer("#/definitions/app/definitions/cost").merge!(
210
+ "exclusiveMaximum" => false,
211
+ "maximum" => 10.0
212
+ )
213
+ data_sample["cost"] = 10.1
214
+ refute validate
215
+ assert_includes error_messages,
216
+ %{Expected data to be smaller than maximum 10.0 (exclusive: false), value was: 10.1.}
217
+ end
218
+
219
+ it "validates maximum for a number with exclusiveMaximum true" do
220
+ pointer("#/definitions/app/definitions/cost").merge!(
221
+ "exclusiveMaximum" => true,
222
+ "maximum" => 10.0
223
+ )
224
+ data_sample["cost"] = 10.0
225
+ refute validate
226
+ assert_includes error_messages,
227
+ %{Expected data to be smaller than maximum 10.0 (exclusive: true), value was: 10.0.}
228
+ end
229
+
230
+ it "validates minimum for an integer with exclusiveMaximum false" do
231
+ pointer("#/definitions/app/definitions/id").merge!(
232
+ "exclusiveMinimum" => false,
233
+ "minimum" => 1
234
+ )
235
+ data_sample["id"] = 0
236
+ refute validate
237
+ assert_includes error_messages,
238
+ %{Expected data to be larger than minimum 1 (exclusive: false), value was: 0.}
239
+ end
240
+
241
+ it "validates minimum for an integer with exclusiveMaximum true" do
242
+ pointer("#/definitions/app/definitions/id").merge!(
243
+ "exclusiveMinimum" => true,
244
+ "minimum" => 1
245
+ )
246
+ data_sample["id"] = 1
247
+ refute validate
248
+ assert_includes error_messages,
249
+ %{Expected data to be larger than minimum 1 (exclusive: true), value was: 1.}
250
+ end
251
+
252
+ it "validates minimum for a number with exclusiveMaximum false" do
253
+ pointer("#/definitions/app/definitions/cost").merge!(
254
+ "exclusiveMinimum" => false,
255
+ "minimum" => 0.0
256
+ )
257
+ data_sample["cost"] = -0.01
258
+ refute validate
259
+ assert_includes error_messages,
260
+ %{Expected data to be larger than minimum 0.0 (exclusive: false), value was: -0.01.}
261
+ end
262
+
263
+ it "validates minimum for a number with exclusiveMaximum true" do
264
+ pointer("#/definitions/app/definitions/cost").merge!(
265
+ "exclusiveMinimum" => true,
266
+ "minimum" => 0.0
267
+ )
268
+ data_sample["cost"] = 0.0
269
+ refute validate
270
+ assert_includes error_messages,
271
+ %{Expected data to be larger than minimum 0.0 (exclusive: true), value was: 0.0.}
272
+ end
273
+
274
+ it "validates multipleOf for an integer" do
275
+ pointer("#/definitions/app/definitions/id").merge!(
276
+ "multipleOf" => 2
277
+ )
278
+ data_sample["id"] = 1
279
+ refute validate
280
+ assert_includes error_messages,
281
+ %{Expected data to be a multiple of 2, value was: 1.}
282
+ end
283
+
284
+ it "validates multipleOf for a number" do
285
+ pointer("#/definitions/app/definitions/cost").merge!(
286
+ "multipleOf" => 0.01
287
+ )
288
+ data_sample["cost"] = 0.005
289
+ refute validate
290
+ assert_includes error_messages,
291
+ %{Expected data to be a multiple of 0.01, value was: 0.005.}
292
+ end
293
+
294
+ it "validates additionalProperties" do
295
+ pointer("#/definitions/app").merge!(
296
+ "additionalProperties" => false
297
+ )
298
+ data_sample["foo"] = "bar"
299
+ refute validate
300
+ assert_includes error_messages, %{Extra keys in object: foo.}
301
+ end
302
+
303
+ it "validates simple dependencies" do
304
+ pointer("#/definitions/app/dependencies").merge!(
305
+ "production" => "ssl"
306
+ )
307
+ data_sample["production"] = true
308
+ refute validate
309
+ assert_includes error_messages, %{Missing required keys in object: ssl.}
310
+ end
311
+
312
+ it "validates schema dependencies" do
313
+ pointer("#/definitions/app/dependencies").merge!(
314
+ "ssl" => {
315
+ "properties" => {
316
+ "cost" => {
317
+ "minimum" => 20.0,
318
+ }
319
+ }
320
+ }
321
+ )
322
+ data_sample["cost"] = 10.0
323
+ data_sample["ssl"] = true
324
+ refute validate
325
+ assert_includes error_messages, %{Expected data to be larger than minimum 20.0 (exclusive: false), value was: 10.0.}
326
+ end
327
+
328
+ it "validates maxProperties" do
329
+ pointer("#/definitions/app").merge!(
330
+ "maxProperties" => 0
331
+ )
332
+ data_sample["name"] = "cloudnasium"
333
+ refute validate
334
+ assert_includes error_messages, %{Expected object to have a maximum of 0 property/ies; it had 1.}
335
+ end
336
+
337
+ it "validates minProperties" do
338
+ pointer("#/definitions/app").merge!(
339
+ "minProperties" => 2
340
+ )
341
+ data_sample["name"] = "cloudnasium"
342
+ refute validate
343
+ assert_includes error_messages, %{Expected object to have a minimum of 2 property/ies; it had 1.}
344
+ end
345
+
346
+ it "validates patternProperties" do
347
+ pointer("#/definitions/app/definitions/config_vars").merge!(
348
+ "patternProperties" => {
349
+ "^\\w+$" => {
350
+ "type" => ["null", "string"]
351
+ }
352
+ }
353
+ )
354
+ data_sample["config_vars"] = {
355
+ "" => 123,
356
+ "KEY" => 456
357
+ }
358
+ refute validate
359
+ assert_includes error_messages,
360
+ %{Expected data to be of type "null/string"; value was: 456.}
361
+ end
362
+
363
+ it "validates required" do
364
+ pointer("#/definitions/app/dependencies").merge!(
365
+ "required" => ["name"]
366
+ )
367
+ data_sample.delete("name")
368
+ refute validate
369
+ assert_includes error_messages, %{Missing required keys in object: name.}
370
+ end
371
+
372
+ it "validates allOf" do
373
+ pointer("#/definitions/app/definitions/contrived").merge!(
374
+ "allOf" => [
375
+ { "maxLength" => 30 },
376
+ { "minLength" => 3 }
377
+ ]
378
+ )
379
+ data_sample["contrived"] = "ab"
380
+ refute validate
381
+ assert_includes error_messages,
382
+ %{Expected string to have a minimum length of 3, was 2 character(s) long.}
383
+ end
384
+
385
+ it "validates anyOf" do
386
+ pointer("#/definitions/app/definitions/contrived").merge!(
387
+ "anyOf" => [
388
+ { "minLength" => 5 },
389
+ { "minLength" => 3 }
390
+ ]
391
+ )
392
+ data_sample["contrived"] = "ab"
393
+ refute validate
394
+ assert_includes error_messages,
395
+ %{Data did not match any subschema of "anyOf" condition.}
396
+ end
397
+
398
+ it "validates oneOf" do
399
+ pointer("#/definitions/app/definitions/contrived").merge!(
400
+ "oneOf" => [
401
+ { "pattern" => "^(foo|aaa)$" },
402
+ { "pattern" => "^(foo|zzz)$" }
403
+ ]
404
+ )
405
+ data_sample["contrived"] = "foo"
406
+ refute validate
407
+ assert_includes error_messages,
408
+ %{Data did not match exactly one subschema of "oneOf" condition.}
409
+ end
410
+
411
+ it "validates not" do
412
+ pointer("#/definitions/app/definitions/contrived").merge!(
413
+ "not" => { "pattern" => "^$" }
414
+ )
415
+ data_sample["contrived"] = ""
416
+ refute validate
417
+ assert_includes error_messages,
418
+ %{Data matched subschema of "not" condition.}
419
+ end
420
+
421
+ it "validates date-time format successfully" do
422
+ pointer("#/definitions/app/definitions/owner").merge!(
423
+ "format" => "date-time"
424
+ )
425
+ data_sample["owner"] = "2014-05-13T08:42:40Z"
426
+ assert validate
427
+ end
428
+
429
+ it "validates date-time format with time zone successfully" do
430
+ pointer("#/definitions/app/definitions/owner").merge!(
431
+ "format" => "date-time"
432
+ )
433
+ data_sample["owner"] = "2014-05-13T08:42:40-00:00"
434
+ assert validate
435
+ end
436
+
437
+ it "validates date-time format unsuccessfully" do
438
+ pointer("#/definitions/app/definitions/owner").merge!(
439
+ "format" => "date-time"
440
+ )
441
+ data_sample["owner"] = "2014-05-13T08:42:40"
442
+ refute validate
443
+ assert_includes error_messages,
444
+ %{Expected data to match "date-time" format, value was: 2014-05-13T08:42:40.}
445
+ end
446
+
447
+ it "validates email format successfully" do
448
+ pointer("#/definitions/app/definitions/owner").merge!(
449
+ "format" => "email"
450
+ )
451
+ data_sample["owner"] = "dwarf@example.com"
452
+ assert validate
453
+ end
454
+
455
+ it "validates email format unsuccessfully" do
456
+ pointer("#/definitions/app/definitions/owner").merge!(
457
+ "format" => "email"
458
+ )
459
+ data_sample["owner"] = "@example.com"
460
+ refute validate
461
+ assert_includes error_messages,
462
+ %{Expected data to match "email" format, value was: @example.com.}
463
+ end
464
+
465
+ it "validates hostname format successfully" do
466
+ pointer("#/definitions/app/definitions/owner").merge!(
467
+ "format" => "hostname"
468
+ )
469
+ data_sample["owner"] = "example.com"
470
+ assert validate
471
+ end
472
+
473
+ it "validates hostname format unsuccessfully" do
474
+ pointer("#/definitions/app/definitions/owner").merge!(
475
+ "format" => "hostname"
476
+ )
477
+ data_sample["owner"] = "@example.com"
478
+ refute validate
479
+ assert_includes error_messages,
480
+ %{Expected data to match "hostname" format, value was: @example.com.}
481
+ end
482
+
483
+ it "validates ipv4 format successfully" do
484
+ pointer("#/definitions/app/definitions/owner").merge!(
485
+ "format" => "ipv4"
486
+ )
487
+ data_sample["owner"] = "1.2.3.4"
488
+ assert validate
489
+ end
490
+
491
+ it "validates ipv4 format unsuccessfully" do
492
+ pointer("#/definitions/app/definitions/owner").merge!(
493
+ "format" => "ipv4"
494
+ )
495
+ data_sample["owner"] = "1.2.3.4.5"
496
+ refute validate
497
+ assert_includes error_messages,
498
+ %{Expected data to match "ipv4" format, value was: 1.2.3.4.5.}
499
+ end
500
+
501
+ it "validates ipv6 format successfully" do
502
+ pointer("#/definitions/app/definitions/owner").merge!(
503
+ "format" => "ipv6"
504
+ )
505
+ data_sample["owner"] = "1::3:4:5:6:7:8"
506
+ assert validate
507
+ end
508
+
509
+ it "validates ipv6 format unsuccessfully" do
510
+ pointer("#/definitions/app/definitions/owner").merge!(
511
+ "format" => "ipv6"
512
+ )
513
+ data_sample["owner"] = "1::3:4:5:6:7:8:9"
514
+ refute validate
515
+ assert_includes error_messages,
516
+ %{Expected data to match "ipv6" format, value was: 1::3:4:5:6:7:8:9.}
517
+ end
518
+
519
+ it "validates uri format successfully" do
520
+ pointer("#/definitions/app/definitions/owner").merge!(
521
+ "format" => "uri"
522
+ )
523
+ data_sample["owner"] = "https://example.com"
524
+ assert validate
525
+ end
526
+
527
+ it "validates uri format unsuccessfully" do
528
+ pointer("#/definitions/app/definitions/owner").merge!(
529
+ "format" => "uri"
530
+ )
531
+ data_sample["owner"] = "example.com"
532
+ refute validate
533
+ assert_includes error_messages,
534
+ %{Expected data to match "uri" format, value was: example.com.}
535
+ end
536
+
537
+ it "validates uuid format successfully" do
538
+ pointer("#/definitions/app/definitions/owner").merge!(
539
+ "format" => "uuid"
540
+ )
541
+ data_sample["owner"] = "01234567-89ab-cdef-0123-456789abcdef"
542
+ assert validate
543
+ end
544
+
545
+ it "validates uuid format unsuccessfully" do
546
+ pointer("#/definitions/app/definitions/owner").merge!(
547
+ "format" => "uuid"
548
+ )
549
+ data_sample["owner"] = "123"
550
+ refute validate
551
+ assert_includes error_messages,
552
+ %{Expected data to match "uuid" format, value was: 123.}
553
+ end
554
+
555
+ it "validates maxLength" do
556
+ pointer("#/definitions/app/definitions/name").merge!(
557
+ "maxLength" => 3
558
+ )
559
+ data_sample["name"] = "abcd"
560
+ refute validate
561
+ assert_includes error_messages,
562
+ %{Expected string to have a maximum length of 3, was 4 character(s) long.}
563
+ end
564
+
565
+ it "validates minLength" do
566
+ pointer("#/definitions/app/definitions/name").merge!(
567
+ "minLength" => 3
568
+ )
569
+ data_sample["name"] = "ab"
570
+ refute validate
571
+ assert_includes error_messages,
572
+ %{Expected string to have a minimum length of 3, was 2 character(s) long.}
573
+ end
574
+
575
+ it "validates pattern" do
576
+ pointer("#/definitions/app/definitions/name").merge!(
577
+ "pattern" => "^[a-z][a-z0-9-]{3,30}$",
578
+ )
579
+ data_sample["name"] = "ab"
580
+ refute validate
581
+ assert_includes error_messages,
582
+ %{Expected string to match pattern "/^[a-z][a-z0-9-]{3,30}$/", value was: ab.}
583
+ end
584
+
585
+ def data_sample
586
+ @data_sample ||= DataScaffold.data_sample
587
+ end
588
+
589
+ def error_messages
590
+ @validator.errors.map { |e| e.message }
591
+ end
592
+
593
+ def pointer(path)
594
+ JsonPointer.evaluate(schema_sample, path)
595
+ end
596
+
597
+ def schema_sample
598
+ @schema_sample ||= DataScaffold.schema_sample
599
+ end
600
+
601
+ def validate
602
+ @schema = JsonSchema.parse!(schema_sample).definitions["app"]
603
+ @validator = JsonSchema::Validator.new(@schema)
604
+ @validator.validate(data_sample)
605
+ end
606
+ end