json_schema 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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