committee 1.15.0 → 2.0.0.pre

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/bin/committee-stub +10 -36
  3. data/lib/committee/bin/committee_stub.rb +61 -0
  4. data/lib/committee/drivers/hyper_schema.rb +151 -0
  5. data/lib/committee/drivers/open_api_2.rb +297 -0
  6. data/lib/committee/drivers.rb +57 -0
  7. data/lib/committee/middleware/base.rb +52 -13
  8. data/lib/committee/middleware/request_validation.rb +33 -10
  9. data/lib/committee/middleware/response_validation.rb +2 -1
  10. data/lib/committee/middleware/stub.rb +24 -8
  11. data/lib/committee/request_validator.rb +1 -1
  12. data/lib/committee/response_generator.rb +58 -13
  13. data/lib/committee/response_validator.rb +32 -8
  14. data/lib/committee/router.rb +5 -33
  15. data/lib/committee/{query_params_coercer.rb → string_params_coercer.rb} +11 -6
  16. data/lib/committee/test/methods.rb +49 -12
  17. data/lib/committee.rb +15 -1
  18. data/test/bin/committee_stub_test.rb +45 -0
  19. data/test/bin_test.rb +20 -0
  20. data/test/committee_test.rb +49 -0
  21. data/test/drivers/hyper_schema_test.rb +95 -0
  22. data/test/drivers/open_api_2_test.rb +255 -0
  23. data/test/drivers_test.rb +60 -0
  24. data/test/middleware/base_test.rb +49 -5
  25. data/test/middleware/request_validation_test.rb +39 -25
  26. data/test/middleware/response_validation_test.rb +32 -20
  27. data/test/middleware/stub_test.rb +50 -19
  28. data/test/request_unpacker_test.rb +10 -0
  29. data/test/request_validator_test.rb +4 -3
  30. data/test/response_generator_test.rb +50 -6
  31. data/test/response_validator_test.rb +29 -4
  32. data/test/router_test.rb +40 -13
  33. data/test/{query_params_coercer_test.rb → string_params_coercer_test.rb} +3 -4
  34. data/test/test/methods_test.rb +44 -5
  35. data/test/test_helper.rb +59 -1
  36. metadata +62 -10
@@ -8,26 +8,34 @@ describe Committee::Middleware::ResponseValidation do
8
8
  end
9
9
 
10
10
  it "passes through a valid response" do
11
- @app = new_rack_app(JSON.generate([ValidApp]))
11
+ @app = new_rack_app(JSON.generate([ValidApp]), {}, schema: hyper_schema)
12
12
  get "/apps"
13
13
  assert_equal 200, last_response.status
14
14
  end
15
15
 
16
- it "detects an invalid response" do
17
- @app = new_rack_app("")
16
+ it "detects a response invalid due to schema" do
17
+ @app = new_rack_app("{}", {}, schema: hyper_schema)
18
+ get "/apps"
19
+ assert_equal 500, last_response.status
20
+ assert_match /{} is not an array/i, last_response.body
21
+ end
22
+
23
+ it "detects a response invalid due to not being JSON" do
24
+ @app = new_rack_app("", {}, schema: hyper_schema)
18
25
  get "/apps"
19
26
  assert_equal 500, last_response.status
20
27
  assert_match /valid JSON/i, last_response.body
21
28
  end
22
29
 
23
30
  it "ignores a non-2xx invalid response" do
24
- @app = new_rack_app("[]", {}, app_status: 404)
31
+ @app = new_rack_app("[]", {}, app_status: 404, schema: hyper_schema)
25
32
  get "/apps"
26
33
  assert_equal 404, last_response.status
27
34
  end
28
35
 
29
36
  it "optionally validates non-2xx invalid responses" do
30
- @app = new_rack_app("", {}, {app_status: 404, validate_errors: true})
37
+ @app = new_rack_app("", {}, app_status: 404, validate_errors: true,
38
+ schema: hyper_schema)
31
39
 
32
40
  get "/apps"
33
41
  assert_equal 500, last_response.status
@@ -35,48 +43,52 @@ describe Committee::Middleware::ResponseValidation do
35
43
  end
36
44
 
37
45
  it "passes through a 204 (no content) response" do
38
- @app = new_rack_app("", {}, app_status: 204)
46
+ @app = new_rack_app("", {}, app_status: 204, schema: hyper_schema)
39
47
  get "/apps"
40
48
  assert_equal 204, last_response.status
41
49
  end
42
50
 
43
51
  it "rescues JSON errors" do
44
- @app = new_rack_app("[{x:y}]")
52
+ @app = new_rack_app("[{x:y}]", {}, schema: hyper_schema)
45
53
  get "/apps"
46
54
  assert_equal 500, last_response.status
47
55
  assert_match /valid json/i, last_response.body
48
56
  end
49
57
 
50
58
  it "takes a prefix" do
51
- @app = new_rack_app(JSON.generate([ValidApp]), {}, prefix: "/v1")
59
+ @app = new_rack_app(JSON.generate([ValidApp]), {}, prefix: "/v1",
60
+ schema: hyper_schema)
52
61
  get "/v1/apps"
53
62
  assert_equal 200, last_response.status
54
63
  end
55
64
 
56
- it "warns when sending a deprecated string" do
57
- mock(Committee).warn_deprecated.with_any_args
58
- @app = new_rack_app(JSON.generate([ValidApp]), {},
59
- schema: File.read("./test/data/schema.json"))
60
- get "/apps"
61
- assert_equal 200, last_response.status
62
- end
63
-
64
65
  it "rescues JSON errors" do
65
- @app = new_rack_app("[{x:y}]", {}, raise: true)
66
+ @app = new_rack_app("[{x:y}]", {}, raise: true, schema: hyper_schema)
66
67
  assert_raises(Committee::InvalidResponse) do
67
68
  get "/apps"
68
69
  end
69
70
  end
70
71
 
72
+ it "passes through a valid response for OpenAPI" do
73
+ @app = new_rack_app(JSON.generate([ValidPet]), {},
74
+ schema: open_api_2_schema)
75
+ get "/api/pets"
76
+ assert_equal 200, last_response.status
77
+ end
78
+
79
+ it "detects an invalid response for OpenAPI" do
80
+ @app = new_rack_app("", {}, schema: open_api_2_schema)
81
+ get "/api/pets"
82
+ assert_equal 500, last_response.status
83
+ assert_match /valid JSON/i, last_response.body
84
+ end
85
+
71
86
  private
72
87
 
73
88
  def new_rack_app(response, headers = {}, options = {})
74
89
  headers = {
75
90
  "Content-Type" => "application/json"
76
91
  }.merge(headers)
77
- options = {
78
- schema: JSON.parse(File.read("./test/data/schema.json"))
79
- }.merge(options)
80
92
  Rack::Builder.new {
81
93
  use Committee::Middleware::ResponseValidation, options
82
94
  run lambda { |_|
@@ -8,7 +8,7 @@ describe Committee::Middleware::Stub do
8
8
  end
9
9
 
10
10
  it "responds with a stubbed response" do
11
- @app = new_rack_app
11
+ @app = new_rack_app(schema: hyper_schema)
12
12
  get "/apps/heroku-api"
13
13
  assert_equal 200, last_response.status
14
14
  data = JSON.parse(last_response.body)
@@ -16,13 +16,13 @@ describe Committee::Middleware::Stub do
16
16
  end
17
17
 
18
18
  it "responds with 201 on create actions" do
19
- @app = new_rack_app
19
+ @app = new_rack_app(schema: hyper_schema)
20
20
  post "/apps"
21
21
  assert_equal 201, last_response.status
22
22
  end
23
23
 
24
24
  it "optionally calls into application" do
25
- @app = new_rack_app(call: true)
25
+ @app = new_rack_app(call: true, schema: hyper_schema)
26
26
  get "/apps/heroku-api"
27
27
  assert_equal 200, last_response.status
28
28
  assert_equal ValidApp,
@@ -30,37 +30,61 @@ describe Committee::Middleware::Stub do
30
30
  end
31
31
 
32
32
  it "optionally returns the application's response" do
33
- @app = new_rack_app(call: true, suppress: true)
33
+ @app = new_rack_app(call: true, schema: hyper_schema, suppress: true)
34
34
  get "/apps/heroku-api"
35
35
  assert_equal 429, last_response.status
36
36
  assert_equal ValidApp,
37
37
  JSON.parse(last_response.headers["Committee-Response"])
38
- assert_equal "", last_response.body
38
+ assert_equal "", last_response.body
39
39
  end
40
40
 
41
41
  it "takes a prefix" do
42
- @app = new_rack_app(prefix: "/v1")
42
+ @app = new_rack_app(prefix: "/v1", schema: hyper_schema)
43
43
  get "/v1/apps/heroku-api"
44
44
  assert_equal 200, last_response.status
45
45
  data = JSON.parse(last_response.body)
46
46
  assert_equal ValidApp.keys.sort, data.keys.sort
47
47
  end
48
48
 
49
- it "warns when sending a deprecated string" do
50
- mock(Committee).warn_deprecated.with_any_args
51
- @app = new_rack_app(schema: File.read("./test/data/schema.json"))
49
+ it "allows the stub's response to be replaced" do
50
+ response = { replaced: true }
51
+ @app = new_rack_app(call: true, response: response, schema: hyper_schema)
52
52
  get "/apps/heroku-api"
53
53
  assert_equal 200, last_response.status
54
+ assert_equal response, JSON.parse(last_response.body, symbolize_names: true)
55
+ end
56
+
57
+ it "responds with a stubbed response for OpenAPI" do
58
+ @app = new_rack_app(schema: open_api_2_schema)
59
+ get "/api/pets/fido"
60
+ assert_equal 200, last_response.status
54
61
  data = JSON.parse(last_response.body)
55
- assert_equal ValidApp.keys.sort, data.keys.sort
62
+ assert_equal ValidPet.keys.sort, data.keys.sort
56
63
  end
57
64
 
58
- it "allows the stub's response to be replaced" do
59
- response = { replaced: true }
60
- @app = new_rack_app(call: true, response: response)
65
+ it "calls into app for links that are undefined" do
66
+ @app = new_rack_app(call: false, schema: hyper_schema)
67
+ post "/foos"
68
+ assert_equal 429, last_response.status
69
+ end
70
+
71
+ it "caches the response if called multiple times" do
72
+ cache = {}
73
+ @app = new_rack_app(cache: cache, schema: hyper_schema)
74
+
61
75
  get "/apps/heroku-api"
62
76
  assert_equal 200, last_response.status
63
- assert_equal response, JSON.parse(last_response.body, symbolize_names: true)
77
+
78
+ data = cache[cache.first[0]]
79
+ assert_equal ValidApp.keys.sort, data.keys.sort
80
+
81
+ # replace what we have in the cache
82
+ cache[cache.first[0]] = { "cached" => true }
83
+
84
+ get "/apps/heroku-api"
85
+ assert_equal 200, last_response.status
86
+ data = JSON.parse(last_response.body)
87
+ assert_equal({ "cached" => true }, data)
64
88
  end
65
89
 
66
90
  private
@@ -68,15 +92,22 @@ describe Committee::Middleware::Stub do
68
92
  def new_rack_app(options = {})
69
93
  response = options.delete(:response)
70
94
  suppress = options.delete(:suppress)
71
- options = {
72
- schema: JSON.parse(File.read("./test/data/schema.json"))
73
- }.merge(options)
74
95
  Rack::Builder.new {
75
96
  use Committee::Middleware::Stub, options
76
97
  run lambda { |env|
77
- env["committee.response"] = response if response
78
- headers = { "Committee-Response" => JSON.generate(env["committee.response"]) }
98
+ if response
99
+ env["committee.response"] = response
100
+ end
101
+
102
+ headers = {}
103
+ if res = env["committee.response"]
104
+ headers.merge!({
105
+ "Committee-Response" => JSON.generate(res)
106
+ })
107
+ end
108
+
79
109
  env["committee.suppress"] = suppress
110
+
80
111
  [429, headers, []]
81
112
  }
82
113
  }
@@ -123,4 +123,14 @@ describe Committee::RequestUnpacker do
123
123
  params = Committee::RequestUnpacker.new(request).call
124
124
  assert_equal({}, params)
125
125
  end
126
+
127
+ # this is mostly here for line coverage
128
+ it "unpacks JSON containing an array" do
129
+ env = {
130
+ "rack.input" => StringIO.new('{"x":[]}'),
131
+ }
132
+ request = Rack::Request.new(env)
133
+ params = Committee::RequestUnpacker.new(request).call
134
+ assert_equal({ "x" => [] }, params)
135
+ end
126
136
  end
@@ -4,8 +4,7 @@ require "stringio"
4
4
 
5
5
  describe Committee::RequestValidator do
6
6
  before do
7
- @schema =
8
- JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
7
+ @schema = JsonSchema.parse!(hyper_schema_data)
9
8
  @schema.expand_references!
10
9
  # POST /apps/:id
11
10
  @link = @link = @schema.properties["app"].links[0]
@@ -98,6 +97,8 @@ describe Committee::RequestValidator do
98
97
  private
99
98
 
100
99
  def call(data, options={})
101
- Committee::RequestValidator.new(@link, options).call(@request, data)
100
+ # hyper-schema link should be dropped into driver wrapper before it's used
101
+ link = Committee::Drivers::HyperSchema::Link.new(@link)
102
+ Committee::RequestValidator.new(link, options).call(@request, data)
102
103
  end
103
104
  end
@@ -2,8 +2,7 @@ require_relative "test_helper"
2
2
 
3
3
  describe Committee::ResponseGenerator do
4
4
  before do
5
- @schema =
6
- JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
5
+ @schema = JsonSchema.parse!(hyper_schema_data)
7
6
  @schema.expand_references!
8
7
  # GET /apps/:id
9
8
  @get_link = @link = @schema.properties["app"].links[2]
@@ -23,16 +22,26 @@ describe Committee::ResponseGenerator do
23
22
 
24
23
  it "wraps list data in an array" do
25
24
  @link = @list_link
25
+
26
+ @link.rel = nil
27
+
26
28
  data = call
27
29
  assert data.is_a?(Array)
28
30
  end
29
31
 
30
- it "wraps list data in an array" do
32
+ it "wraps list data tagged with rel 'instances' in an array" do
31
33
  @link = @list_link
32
34
 
33
- @link.rel = nil
35
+ # forces the link to use `parent`
36
+ @link.target_schema = nil
34
37
 
35
38
  data = call
39
+
40
+ # We're testing for legacy behavior here: even without a `targetSchema` as
41
+ # long as `rel` is set to `instances` we still wrap the the result in an
42
+ # array.
43
+ assert_equal "instances", @list_link.rel
44
+
36
45
  assert data.is_a?(Array)
37
46
  end
38
47
 
@@ -49,13 +58,48 @@ describe Committee::ResponseGenerator do
49
58
  end
50
59
 
51
60
  expected = <<-eos.gsub(/\n +/, "").strip
52
- At "#/definitions/app/properties/maintenance": no "example" attribute and
61
+ At "get /apps/{(%23%2Fdefinitions%2Fapp%2Fdefinitions%2Fname)}"
62
+ "#/definitions/app/properties/maintenance": no "example" attribute and
53
63
  "null" is not allowed; don't know how to generate property.
54
64
  eos
55
65
  assert_equal expected, e.message
56
66
  end
57
67
 
68
+ it "generates basic types" do
69
+ link = Committee::Drivers::OpenAPI2::Link.new
70
+ link.target_schema = JsonSchema::Schema.new
71
+
72
+ link.target_schema.type = ["integer"]
73
+ assert_equal 0, Committee::ResponseGenerator.new.call(link)
74
+
75
+ link.target_schema.type = ["null"]
76
+ assert_equal nil, Committee::ResponseGenerator.new.call(link)
77
+
78
+ link.target_schema.type = ["string"]
79
+ assert_equal "", Committee::ResponseGenerator.new.call(link)
80
+ end
81
+
82
+ it "prefers an example to a built-in value" do
83
+ link = Committee::Drivers::OpenAPI2::Link.new
84
+ link.target_schema = JsonSchema::Schema.new
85
+
86
+ link.target_schema.data = { "example" => 123 }
87
+ link.target_schema.type = ["integer"]
88
+
89
+ assert_equal 123, Committee::ResponseGenerator.new.call(link)
90
+ end
91
+
92
+ it "prefers non-null types to null types" do
93
+ link = Committee::Drivers::OpenAPI2::Link.new
94
+ link.target_schema = JsonSchema::Schema.new
95
+
96
+ link.target_schema.type = ["null", "integer"]
97
+ assert_equal 0, Committee::ResponseGenerator.new.call(link)
98
+ end
99
+
58
100
  def call
59
- Committee::ResponseGenerator.new.call(@link)
101
+ # hyper-schema link should be dropped into driver wrapper before it's used
102
+ link = Committee::Drivers::HyperSchema::Link.new(@link)
103
+ Committee::ResponseGenerator.new.call(link)
60
104
  end
61
105
  end
@@ -7,8 +7,7 @@ describe Committee::ResponseValidator do
7
7
  "Content-Type" => "application/json"
8
8
  }
9
9
  @data = ValidApp.dup
10
- @schema =
11
- JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
10
+ @schema = JsonSchema.parse!(hyper_schema_data)
12
11
  @schema.expand_references!
13
12
  # GET /apps/:id
14
13
  @get_link = @link = @schema.properties["app"].links[2]
@@ -37,9 +36,33 @@ describe Committee::ResponseValidator do
37
36
  call
38
37
  end
39
38
 
40
- it "detects an improperly formatted list response" do
39
+ it "passes through a valid list response for for rel instances links" do
41
40
  @link = @list_link
41
+
42
+ # forces the link to use `parent`
42
43
  @link.target_schema = nil
44
+
45
+ # We're testing for legacy behavior here: even without a `targetSchema` as
46
+ # long as `rel` is set to `instances` we still wrap the the result in an
47
+ # array.
48
+ assert_equal "instances", @link.rel
49
+
50
+ @data = [@data]
51
+ @link = @list_link
52
+ call
53
+ end
54
+
55
+ it "detects an improperly formatted list response for rel instances link" do
56
+ @link = @list_link
57
+
58
+ # forces the link to use `parent`
59
+ @link.target_schema = nil
60
+
61
+ # We're testing for legacy behavior here: even without a `targetSchema` as
62
+ # long as `rel` is set to `instances` we still wrap the the result in an
63
+ # array.
64
+ assert_equal "instances", @link.rel
65
+
43
66
  e = assert_raises(Committee::InvalidResponse) { call }
44
67
  message = "List endpoints must return an array of objects."
45
68
  assert_equal message, e.message
@@ -76,6 +99,8 @@ describe Committee::ResponseValidator do
76
99
  private
77
100
 
78
101
  def call
79
- Committee::ResponseValidator.new(@link).call(@status, @headers, @data)
102
+ # hyper-schema link should be dropped into driver wrapper before it's used
103
+ link = Committee::Drivers::HyperSchema::Link.new(@link)
104
+ Committee::ResponseValidator.new(link).call(@status, @headers, @data)
80
105
  end
81
106
  end
data/test/router_test.rb CHANGED
@@ -2,37 +2,64 @@ require_relative "test_helper"
2
2
 
3
3
  describe Committee::Router do
4
4
  it "builds routes without parameters" do
5
- refute_nil router.find_link("GET", "/apps")
5
+ link, _ = hyper_schema_router.find_link("GET", "/apps")
6
+ refute_nil link
6
7
  end
7
8
 
8
9
  it "builds routes with parameters" do
9
- refute_nil router.find_link("GET", "/apps/123")
10
+ link, _ = hyper_schema_router.find_link("GET", "/apps/123")
11
+ refute_nil link
10
12
  end
11
13
 
12
14
  it "doesn't match anything on a /" do
13
- assert_nil router.find_link("GET", "/")
15
+ link, _ = hyper_schema_router.find_link("GET", "/")
16
+ assert_nil link
14
17
  end
15
18
 
16
19
  it "takes a prefix" do
17
20
  # this is a sociopathic example
18
- assert router(prefix: "/kpi").find_link("GET", "/kpi/apps/123")
21
+ link, _ = hyper_schema_router(prefix: "/kpi").find_link("GET", "/kpi/apps/123")
22
+ refute_nil link
19
23
  end
20
24
 
21
25
  it "includes all paths without a prefix" do
22
- assert router.includes?("/")
23
- assert router.includes?("/apps")
26
+ link, _ = hyper_schema_router.includes?("/")
27
+ refute_nil link
28
+
29
+ link, _ = hyper_schema_router.includes?("/apps")
30
+ refute_nil link
24
31
  end
25
32
 
26
33
  it "only includes the prefix path with a prefix" do
27
- refute router(prefix: "/kpi").includes?("/")
28
- assert router(prefix: "/kpi").includes?("/kpi")
29
- assert router(prefix: "/kpi").includes?("/kpi/apps")
34
+ link, _ = hyper_schema_router(prefix: "/kpi").includes?("/")
35
+ assert_nil link
36
+
37
+ link, _ = hyper_schema_router(prefix: "/kpi").includes?("/kpi")
38
+ refute_nil link
39
+
40
+ link, _ = hyper_schema_router(prefix: "/kpi").includes?("/kpi/apps")
41
+ refute_nil link
42
+ end
43
+
44
+ it "provides named parameters" do
45
+ link, param_matches = open_api_2_router.find_link("GET", "/api/pets/fido")
46
+ refute_nil link
47
+ assert_equal({ "id" => "fido" }, param_matches)
48
+ end
49
+
50
+ it "doesn't provide named parameters where none are available" do
51
+ link, param_matches = open_api_2_router.find_link("GET", "/api/pets")
52
+ refute_nil link
53
+ assert_equal({}, param_matches)
54
+ end
55
+
56
+ def hyper_schema_router(options = {})
57
+ schema = Committee::Drivers::HyperSchema.new.parse(hyper_schema_data)
58
+ Committee::Router.new(schema, options)
30
59
  end
31
60
 
32
- def router(options = {})
33
- data = JSON.parse(File.read("./test/data/schema.json"))
34
- schema = JsonSchema.parse!(data)
35
- schema.expand_references!
61
+ def open_api_2_router(options = {})
62
+ schema = Committee::Drivers::OpenAPI2.new.parse(open_api_2_data)
36
63
  Committee::Router.new(schema, options)
37
64
  end
38
65
  end
@@ -1,9 +1,8 @@
1
1
  require_relative "test_helper"
2
2
 
3
- describe Committee::QueryParamsCoercer do
3
+ describe Committee::StringParamsCoercer do
4
4
  before do
5
- @schema =
6
- JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
5
+ @schema = JsonSchema.parse!(hyper_schema_data)
7
6
  @schema.expand_references!
8
7
  # GET /search/apps
9
8
  @link = @link = @schema.properties["app"].links[5]
@@ -65,6 +64,6 @@ describe Committee::QueryParamsCoercer do
65
64
  private
66
65
 
67
66
  def call(data)
68
- Committee::QueryParamsCoercer.new(data, @link.schema).call
67
+ Committee::StringParamsCoercer.new(data, @link.schema).call
69
68
  end
70
69
  end
@@ -1,6 +1,6 @@
1
1
  require_relative "../test_helper"
2
2
 
3
- describe Committee::Middleware::Stub do
3
+ describe Committee::Test::Methods do
4
4
  include Committee::Test::Methods
5
5
  include Rack::Test::Methods
6
6
 
@@ -8,8 +8,16 @@ describe Committee::Middleware::Stub do
8
8
  @app
9
9
  end
10
10
 
11
- def schema_path
12
- "./test/data/schema.json"
11
+ def committee_schema
12
+ hyper_schema
13
+ end
14
+
15
+ before do
16
+ # This is a little icky, but the test methods will cache router and schema
17
+ # values between tests. This makes sense in real life, but is harmful for
18
+ # our purposes here in testing the module.
19
+ @committee_router = nil
20
+ @committee_schema = nil
13
21
  end
14
22
 
15
23
  describe "#assert_schema_content_type" do
@@ -35,9 +43,40 @@ describe Committee::Middleware::Stub do
35
43
  assert_match /response header must be set to/i, e.message
36
44
  end
37
45
 
38
- it "warns when sending a deprecated string" do
39
- stub(self).schema_contents { File.read(schema_path) }
46
+ it "accepts schema string (legacy behavior)" do
47
+ mock(Committee).warn_deprecated.with_any_args
48
+
49
+ stub(self).committee_schema { nil }
50
+ stub(self).schema_contents { JSON.dump(hyper_schema_data) }
51
+
52
+ @app = new_rack_app(JSON.generate([ValidApp]))
53
+ get "/apps"
54
+ assert_schema_conform
55
+ end
56
+
57
+ it "accepts schema hash (legacy behavior)" do
40
58
  mock(Committee).warn_deprecated.with_any_args
59
+
60
+ stub(self).committee_schema { nil }
61
+ stub(self).schema_contents { hyper_schema_data }
62
+
63
+ @app = new_rack_app(JSON.generate([ValidApp]))
64
+ get "/apps"
65
+ assert_schema_conform
66
+ end
67
+
68
+ it "accepts schema JsonSchema::Schema object (legacy behavior)" do
69
+ # Note we don't warn here because this is a recent deprecation and
70
+ # passing a schema object will not be a huge performance hit. We should
71
+ # probably start warning on the next version.
72
+
73
+ stub(self).committee_schema { nil }
74
+ stub(self).schema_contents do
75
+ schema = JsonSchema.parse!(hyper_schema_data)
76
+ schema.expand_references!
77
+ schema
78
+ end
79
+
41
80
  @app = new_rack_app(JSON.generate([ValidApp]))
42
81
  get "/apps"
43
82
  assert_schema_conform
data/test/test_helper.rb CHANGED
@@ -1,13 +1,71 @@
1
+ if RUBY_VERSION >= '2.0.0'
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start do
5
+ # We do our utmost to test our executables by modularizing them into
6
+ # testable pieces, but testing them to completion is nearly impossible as
7
+ # far as I can tell, so include them in our tests but don't calculate
8
+ # coverage.
9
+ add_filter "/bin/"
10
+
11
+ add_filter "/test/"
12
+
13
+ # This library has a pretty modest number of lines, so let's try to stick
14
+ # to a 100% coverage target for a while and see what happens.
15
+ minimum_coverage 100
16
+ end
17
+ end
18
+
1
19
  require "minitest"
2
20
  require "minitest/spec"
3
21
  require "minitest/autorun"
4
- #require "pry-rescue/minitest"
5
22
  require "rack/test"
6
23
  require "rr"
7
24
 
8
25
  require_relative "../lib/committee"
9
26
 
27
+ # The OpenAPI sample specification provided directly from the organization uses
28
+ # a couple custom "format" values for JSON schema, namely "int32" and "int64".
29
+ # Provide basic definitions for them here so that we don't error when trying to
30
+ # parse the sample.
31
+ JsonSchema.configure do |c|
32
+ c.register_format 'int32', ->(data) {}
33
+ c.register_format 'int64', ->(data) {}
34
+ end
35
+
36
+ # For our hyper-schema example.
10
37
  ValidApp = {
11
38
  "maintenance" => false,
12
39
  "name" => "example",
13
40
  }.freeze
41
+
42
+ # For our OpenAPI example.
43
+ ValidPet = {
44
+ "id" => 123,
45
+ "name" => "example",
46
+ "tag" => "tag-123",
47
+ }.freeze
48
+
49
+ def hyper_schema
50
+ @hyper_schema ||= begin
51
+ driver = Committee::Drivers::HyperSchema.new
52
+ driver.parse(hyper_schema_data)
53
+ end
54
+ end
55
+
56
+ def open_api_2_schema
57
+ @open_api_2_schema ||= begin
58
+ driver = Committee::Drivers::OpenAPI2.new
59
+ driver.parse(open_api_2_data)
60
+ end
61
+ end
62
+
63
+ # Don't cache this because we'll often manipulate the created hash in tests.
64
+ def hyper_schema_data
65
+ JSON.parse(File.read("./test/data/hyperschema/paas.json"))
66
+ end
67
+
68
+ # Don't cache this because we'll often manipulate the created hash in tests.
69
+ def open_api_2_data
70
+ JSON.parse(File.read("./test/data/openapi2/petstore-expanded.json"))
71
+ end