committee 1.15.0 → 2.0.0.pre

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