json_schema 0.0.7 → 0.0.9

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,103 @@
1
+ require "test_helper"
2
+
3
+ require "commands/validate_schema"
4
+ require "tempfile"
5
+
6
+ describe Commands::ValidateSchema do
7
+ before do
8
+ @command = Commands::ValidateSchema.new
9
+ end
10
+
11
+ it "shows usage with no arguments" do
12
+ success = @command.run([])
13
+ assert_equal [], @command.errors
14
+ assert_equal [], @command.messages
15
+ refute success
16
+ end
17
+
18
+ it "runs successfully in detect mode" do
19
+ temp_file(basic_schema) do |path|
20
+ @command.extra_schemas << schema_path
21
+ @command.detect = true
22
+ success = @command.run([path])
23
+ assert_equal [], @command.errors
24
+ assert_equal ["#{path} is valid."], @command.messages
25
+ assert success
26
+ end
27
+ end
28
+
29
+ it "runs successfully out of detect mode" do
30
+ temp_file(basic_schema) do |path|
31
+ @command.detect = false
32
+ success = @command.run([schema_path, path])
33
+ assert_equal [], @command.errors
34
+ assert_equal ["#{path} is valid."], @command.messages
35
+ assert success
36
+ end
37
+ end
38
+
39
+ it "takes extra schemas" do
40
+ temp_file(basic_hyper_schema) do |path|
41
+ @command.detect = false
42
+ @command.extra_schemas << schema_path
43
+ success = @command.run([hyper_schema_path, path])
44
+ assert_equal [], @command.errors
45
+ assert_equal ["#{path} is valid."], @command.messages
46
+ assert success
47
+ end
48
+ end
49
+
50
+ it "requires at least one argument in detect mode" do
51
+ @command.detect = true
52
+ success = @command.run([])
53
+ assert_equal [], @command.errors
54
+ assert_equal [], @command.messages
55
+ refute success
56
+ end
57
+
58
+ it "requires at least two arguments out of detect mode" do
59
+ @command.detect = false
60
+ success = @command.run([hyper_schema_path])
61
+ assert_equal [], @command.errors
62
+ assert_equal [], @command.messages
63
+ refute success
64
+ end
65
+
66
+ it "errors on invalid files" do
67
+ @command.detect = false
68
+ success = @command.run(["dne-1", "dne-2"])
69
+ assert_equal ["dne-1: No such file or directory."], @command.errors
70
+ assert_equal [], @command.messages
71
+ refute success
72
+ end
73
+
74
+ def basic_hyper_schema
75
+ <<-eos
76
+ { "$schema": "http://json-schema.org/draft-04/hyper-schema" }
77
+ eos
78
+ end
79
+
80
+ def basic_schema
81
+ <<-eos
82
+ { "$schema": "http://json-schema.org/draft-04/schema" }
83
+ eos
84
+ end
85
+
86
+ def hyper_schema_path
87
+ File.expand_path("schema.json", "#{__FILE__}/../../../schemas")
88
+ end
89
+
90
+ def schema_path
91
+ File.expand_path("schema.json", "#{__FILE__}/../../../schemas")
92
+ end
93
+
94
+ def temp_file(contents)
95
+ file = Tempfile.new("schema")
96
+ file.write(contents)
97
+ file.size() # flush
98
+ yield(file.path)
99
+ ensure
100
+ file.close
101
+ file.unlink
102
+ end
103
+ 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_equal 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_equal 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_equal 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_equal 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
@@ -86,12 +86,29 @@ describe JsonSchema::Parser do
86
86
 
87
87
  it "parses the basic set of object validations" do
88
88
  schema = parse.definitions["app"]
89
- assert_equal false, schema.additional_properties
90
89
  assert_equal 10, schema.max_properties
91
90
  assert_equal 1, schema.min_properties
92
91
  assert_equal ["name"], schema.required
93
92
  end
94
93
 
94
+ it "parses the additionalProperties object validation as boolean" do
95
+ pointer("#/definitions/app").merge!(
96
+ "additionalProperties" => false
97
+ )
98
+ schema = parse.definitions["app"]
99
+ assert_equal false, schema.additional_properties
100
+ end
101
+
102
+ it "parses the additionalProperties object validation as schema" do
103
+ pointer("#/definitions/app").merge!(
104
+ "additionalProperties" => {
105
+ "type" => "boolean"
106
+ }
107
+ )
108
+ schema = parse.definitions["app"].additional_properties
109
+ assert_equal ["boolean"], schema.type
110
+ end
111
+
95
112
  it "parses the dependencies object validation" do
96
113
  schema = parse.definitions["app"]
97
114
  assert_equal ["ssl"], schema.dependencies["production"]
@@ -4,36 +4,46 @@ require "json_schema"
4
4
 
5
5
  describe JsonSchema::ReferenceExpander do
6
6
  it "expands references" do
7
- assert expand
7
+ expand
8
+ assert_equal [], errors
8
9
 
9
10
  # this was always a fully-defined property
10
11
  referenced = @schema.definitions["app"]
11
12
  # this used to be a $ref
12
13
  reference = @schema.properties["app"]
13
14
 
14
- assert_nil reference.reference
15
+ assert_equal "#/definitions/app", reference.reference.pointer
15
16
  assert_equal referenced.description, reference.description
16
17
  assert_equal referenced.id, reference.id
17
18
  assert_equal referenced.type, reference.type
18
19
  assert_equal referenced.uri, reference.uri
19
20
  end
20
21
 
22
+ it "takes a document store" do
23
+ store = JsonSchema::DocumentStore.new
24
+ expand(store: store)
25
+ assert store.lookup_uri("/")
26
+ end
27
+
21
28
  it "will expand anyOf" do
22
- assert expand
29
+ expand
30
+ assert_equal [], errors
23
31
  schema = @schema.properties["app"].definitions["contrived_plus"]
24
32
  assert_equal 3, schema.any_of[0].min_length
25
33
  assert_equal 5, schema.any_of[1].min_length
26
34
  end
27
35
 
28
36
  it "will expand allOf" do
29
- assert expand
37
+ expand
38
+ assert_equal [], errors
30
39
  schema = @schema.properties["app"].definitions["contrived_plus"]
31
40
  assert_equal 30, schema.all_of[0].max_length
32
41
  assert_equal 3, schema.all_of[1].min_length
33
42
  end
34
43
 
35
44
  it "will expand dependencies" do
36
- assert expand
45
+ expand
46
+ assert_equal [], errors
37
47
  schema = @schema.properties["app"].dependencies["ssl"].properties["name"]
38
48
  assert_equal ["string"], schema.type
39
49
  end
@@ -44,7 +54,8 @@ describe JsonSchema::ReferenceExpander do
44
54
  "$ref" => "#/definitions/app/definitions/name"
45
55
  }
46
56
  )
47
- assert expand
57
+ expand
58
+ assert_equal [], errors
48
59
  schema = @schema.properties["app"].properties["flags"].items
49
60
  assert_equal ["string"], schema.type
50
61
  end
@@ -56,7 +67,8 @@ describe JsonSchema::ReferenceExpander do
56
67
  { "$ref" => "#/definitions/app/definitions/owner" }
57
68
  ]
58
69
  )
59
- assert expand
70
+ expand
71
+ assert_equal [], errors
60
72
  schema0 = @schema.properties["app"].properties["flags"].items[0]
61
73
  schema1 = @schema.properties["app"].properties["flags"].items[0]
62
74
  assert_equal ["string"], schema0.type
@@ -64,20 +76,33 @@ describe JsonSchema::ReferenceExpander do
64
76
  end
65
77
 
66
78
  it "will expand oneOf" do
67
- assert expand
79
+ expand
80
+ assert_equal [], errors
68
81
  schema = @schema.properties["app"].definitions["contrived_plus"]
69
82
  assert_equal /^(foo|aaa)$/, schema.one_of[0].pattern
70
83
  assert_equal /^(foo|zzz)$/, schema.one_of[1].pattern
71
84
  end
72
85
 
73
86
  it "will expand not" do
74
- assert expand
87
+ expand
88
+ assert_equal [], errors
75
89
  schema = @schema.properties["app"].definitions["contrived_plus"]
76
90
  assert_equal /^$/, schema.not.pattern
77
91
  end
78
92
 
93
+ it "will expand additionalProperties" do
94
+ pointer("#").merge!(
95
+ "additionalProperties" => { "$ref" => "#" }
96
+ )
97
+ expand
98
+ assert_equal [], errors
99
+ schema = @schema.additional_properties
100
+ assert_equal ["object"], schema.type
101
+ end
102
+
79
103
  it "will expand patternProperties" do
80
- assert expand
104
+ expand
105
+ assert_equal [], errors
81
106
  # value ([1]) of the #first tuple in hash
82
107
  schema = @schema.properties["app"].definitions["roles"].
83
108
  pattern_properties.first[1]
@@ -85,51 +110,68 @@ describe JsonSchema::ReferenceExpander do
85
110
  end
86
111
 
87
112
  it "will expand hyperschema link schemas" do
88
- assert expand
113
+ expand
114
+ assert_equal [], errors
89
115
  schema = @schema.properties["app"].links[0].schema.properties["name"]
90
116
  assert_equal ["string"], schema.type
91
117
  end
92
118
 
93
119
  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
120
+ pointer("#/properties").merge!(
121
+ "app0" => { "$ref" => "#/properties/app1" },
122
+ "app1" => { "$ref" => "#/properties/app2" },
123
+ "app2" => { "$ref" => "#/definitions/app" },
124
+ )
125
+ expand
126
+ assert_equal [], errors
127
+ schema = @schema.properties["app0"]
128
+ assert_equal ["object"], schema.type
129
+ end
130
+
131
+ it "will resolve circular dependencies" do
132
+ pointer("#/properties").merge!(
133
+ "app" => { "$ref" => "#" }
134
+ )
135
+ expand
136
+ assert_equal [], errors
137
+ schema = @schema.properties["app"]
138
+ assert_equal ["object"], schema.type
103
139
  end
104
140
 
105
141
  it "errors on a JSON Pointer that can't be resolved" do
106
- schema_sample["properties"]["app"] = {
107
- "$ref" => "#/definitions/nope"
108
- }
142
+ pointer("#/properties").merge!(
143
+ "app" => { "$ref" => "#/definitions/nope" }
144
+ )
109
145
  refute expand
110
- assert_includes error_messages,
146
+ assert_includes errors,
111
147
  %{Couldn't resolve pointer "#/definitions/nope".}
148
+ assert_includes errors,
149
+ %{Couldn't resolve references: #/definitions/nope.}
112
150
  end
113
151
 
114
- it "errors on a schema that can't be resolved" do
115
- schema_sample["properties"]["app"] = {
116
- "$ref" => "/schemata/user#/definitions/name"
117
- }
152
+ it "errors on a URI that can't be resolved" do
153
+ pointer("#/properties").merge!(
154
+ "app" => { "$ref" => "/schemata/user#/definitions/name" }
155
+ )
118
156
  refute expand
119
- assert_includes error_messages,
120
- %{Couldn't resolve references (possible circular dependency): /schemata/user#/definitions/name.}
157
+ assert_includes errors,
158
+ %{Couldn't resolve references: /schemata/user#/definitions/name.}
159
+ assert_includes errors, %{Couldn't resolve URI: /schemata/user.}
121
160
  end
122
161
 
123
- it "errors on a circular reference" do
124
- schema_sample["definitions"]["app"] = {
125
- "$ref" => "#/properties/app"
126
- }
162
+ it "errors on a reference cycle" do
163
+ pointer("#/properties").merge!(
164
+ "app0" => { "$ref" => "#/properties/app2" },
165
+ "app1" => { "$ref" => "#/properties/app0" },
166
+ "app2" => { "$ref" => "#/properties/app1" },
167
+ )
127
168
  refute expand
128
- assert_includes error_messages,
129
- %{Couldn't resolve references (possible circular dependency): #/definitions/app.}
169
+ properties = "#/properties/app0, #/properties/app1, #/properties/app2"
170
+ assert_includes errors, %{Reference cycle detected: #{properties}.}
171
+ assert_includes errors, %{Couldn't resolve references: #{properties}.}
130
172
  end
131
173
 
132
- def error_messages
174
+ def errors
133
175
  @expander.errors.map { |e| e.message }
134
176
  end
135
177
 
@@ -141,9 +183,9 @@ describe JsonSchema::ReferenceExpander do
141
183
  @schema_sample ||= DataScaffold.schema_sample
142
184
  end
143
185
 
144
- def expand
186
+ def expand(options = {})
145
187
  @schema = JsonSchema::Parser.new.parse!(schema_sample)
146
188
  @expander = JsonSchema::ReferenceExpander.new
147
- @expander.expand(@schema)
189
+ @expander.expand(@schema, options)
148
190
  end
149
191
  end
@@ -291,7 +291,15 @@ describe JsonSchema::Validator do
291
291
  %{Expected data to be a multiple of 0.01, value was: 0.005.}
292
292
  end
293
293
 
294
- it "validates additionalProperties" do
294
+ it "validates additionalProperties boolean successfully" do
295
+ pointer("#/definitions/app").merge!(
296
+ "additionalProperties" => true
297
+ )
298
+ data_sample["foo"] = "bar"
299
+ assert validate
300
+ end
301
+
302
+ it "validates additionalProperties boolean unsuccessfully" do
295
303
  pointer("#/definitions/app").merge!(
296
304
  "additionalProperties" => false
297
305
  )
@@ -300,6 +308,28 @@ describe JsonSchema::Validator do
300
308
  assert_includes error_messages, %{Extra keys in object: foo.}
301
309
  end
302
310
 
311
+ it "validates additionalProperties schema successfully" do
312
+ pointer("#/definitions/app").merge!(
313
+ "additionalProperties" => {
314
+ "type" => ["boolean"]
315
+ }
316
+ )
317
+ data_sample["foo"] = true
318
+ assert validate
319
+ end
320
+
321
+ it "validates additionalProperties schema unsuccessfully" do
322
+ pointer("#/definitions/app").merge!(
323
+ "additionalProperties" => {
324
+ "type" => ["boolean"]
325
+ }
326
+ )
327
+ data_sample["foo"] = 4
328
+ refute validate
329
+ assert_includes error_messages,
330
+ %{Expected data to be of type "boolean"; value was: 4.}
331
+ end
332
+
303
333
  it "validates simple dependencies" do
304
334
  pointer("#/definitions/app/dependencies").merge!(
305
335
  "production" => "ssl"
@@ -516,7 +546,25 @@ describe JsonSchema::Validator do
516
546
  %{Expected data to match "ipv6" format, value was: 1::3:4:5:6:7:8:9.}
517
547
  end
518
548
 
519
- it "validates uri format successfully" do
549
+ it "validates regex format successfully" do
550
+ pointer("#/definitions/app/definitions/owner").merge!(
551
+ "format" => "regex"
552
+ )
553
+ data_sample["owner"] = "^owner@heroku\.com$"
554
+ assert validate
555
+ end
556
+
557
+ it "validates regex format successfully" do
558
+ pointer("#/definitions/app/definitions/owner").merge!(
559
+ "format" => "regex"
560
+ )
561
+ data_sample["owner"] = "^owner($"
562
+ refute validate
563
+ assert_includes error_messages,
564
+ %{Expected data to match "regex" format, value was: ^owner($.}
565
+ end
566
+
567
+ it "validates absolute uri format successfully" do
520
568
  pointer("#/definitions/app/definitions/owner").merge!(
521
569
  "format" => "uri"
522
570
  )
@@ -524,14 +572,22 @@ describe JsonSchema::Validator do
524
572
  assert validate
525
573
  end
526
574
 
575
+ it "validates relative uri format successfully" do
576
+ pointer("#/definitions/app/definitions/owner").merge!(
577
+ "format" => "uri"
578
+ )
579
+ data_sample["owner"] = "schemata/app"
580
+ assert validate
581
+ end
582
+
527
583
  it "validates uri format unsuccessfully" do
528
584
  pointer("#/definitions/app/definitions/owner").merge!(
529
585
  "format" => "uri"
530
586
  )
531
- data_sample["owner"] = "example.com"
587
+ data_sample["owner"] = "http://"
532
588
  refute validate
533
589
  assert_includes error_messages,
534
- %{Expected data to match "uri" format, value was: example.com.}
590
+ %{Expected data to match "uri" format, value was: http://.}
535
591
  end
536
592
 
537
593
  it "validates uuid format successfully" do