committee 1.15.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bin/committee-stub +11 -38
- data/lib/committee/bin/committee_stub.rb +67 -0
- data/lib/committee/drivers/driver.rb +47 -0
- data/lib/committee/drivers/hyper_schema/driver.rb +105 -0
- data/lib/committee/drivers/hyper_schema/link.rb +68 -0
- data/lib/committee/drivers/hyper_schema/schema.rb +22 -0
- data/lib/committee/drivers/hyper_schema.rb +12 -0
- data/lib/committee/drivers/open_api_2/driver.rb +252 -0
- data/lib/committee/drivers/open_api_2/header_schema_builder.rb +33 -0
- data/lib/committee/drivers/open_api_2/link.rb +36 -0
- data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +83 -0
- data/lib/committee/drivers/open_api_2/schema.rb +26 -0
- data/lib/committee/drivers/open_api_2/schema_builder.rb +33 -0
- data/lib/committee/drivers/open_api_2.rb +13 -0
- data/lib/committee/drivers/open_api_3/driver.rb +51 -0
- data/lib/committee/drivers/open_api_3/schema.rb +41 -0
- data/lib/committee/drivers/open_api_3.rb +11 -0
- data/lib/committee/drivers/schema.rb +23 -0
- data/lib/committee/drivers.rb +84 -0
- data/lib/committee/errors.rb +17 -0
- data/lib/committee/middleware/base.rb +46 -29
- data/lib/committee/middleware/request_validation.rb +31 -49
- data/lib/committee/middleware/response_validation.rb +48 -25
- data/lib/committee/middleware/stub.rb +62 -37
- data/lib/committee/middleware.rb +11 -0
- data/lib/committee/request_unpacker.rb +58 -50
- data/lib/committee/schema_validator/hyper_schema/parameter_coercer.rb +79 -0
- data/lib/committee/schema_validator/hyper_schema/request_validator.rb +55 -0
- data/lib/committee/schema_validator/hyper_schema/response_generator.rb +102 -0
- data/lib/committee/schema_validator/hyper_schema/response_validator.rb +89 -0
- data/lib/committee/schema_validator/hyper_schema/router.rb +46 -0
- data/lib/committee/schema_validator/hyper_schema/string_params_coercer.rb +105 -0
- data/lib/committee/schema_validator/hyper_schema.rb +119 -0
- data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +139 -0
- data/lib/committee/schema_validator/open_api_3/request_validator.rb +52 -0
- data/lib/committee/schema_validator/open_api_3/response_validator.rb +29 -0
- data/lib/committee/schema_validator/open_api_3/router.rb +45 -0
- data/lib/committee/schema_validator/open_api_3.rb +120 -0
- data/lib/committee/schema_validator/option.rb +60 -0
- data/lib/committee/schema_validator.rb +23 -0
- data/lib/committee/test/methods.rb +68 -38
- data/lib/committee/test/schema_coverage.rb +101 -0
- data/lib/committee/utils.rb +28 -0
- data/lib/committee/validation_error.rb +5 -2
- data/lib/committee/version.rb +5 -0
- data/lib/committee.rb +31 -18
- data/test/bin/committee_stub_test.rb +57 -0
- data/test/bin_test.rb +25 -0
- data/test/committee_test.rb +77 -0
- data/test/drivers/hyper_schema/driver_test.rb +49 -0
- data/test/drivers/hyper_schema/link_test.rb +56 -0
- data/test/drivers/open_api_2/driver_test.rb +156 -0
- data/test/drivers/open_api_2/header_schema_builder_test.rb +26 -0
- data/test/drivers/open_api_2/link_test.rb +52 -0
- data/test/drivers/open_api_2/parameter_schema_builder_test.rb +195 -0
- data/test/drivers/open_api_3/driver_test.rb +84 -0
- data/test/drivers_test.rb +154 -0
- data/test/middleware/base_test.rb +96 -7
- data/test/middleware/request_validation_open_api_3_test.rb +626 -0
- data/test/middleware/request_validation_test.rb +423 -32
- data/test/middleware/response_validation_open_api_3_test.rb +291 -0
- data/test/middleware/response_validation_test.rb +125 -23
- data/test/middleware/stub_test.rb +81 -20
- data/test/request_unpacker_test.rb +126 -52
- data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +111 -0
- data/test/schema_validator/hyper_schema/request_validator_test.rb +151 -0
- data/test/schema_validator/hyper_schema/response_generator_test.rb +142 -0
- data/test/{response_validator_test.rb → schema_validator/hyper_schema/response_validator_test.rb} +43 -6
- data/test/schema_validator/hyper_schema/router_test.rb +88 -0
- data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +137 -0
- data/test/schema_validator/open_api_3/operation_wrapper_test.rb +218 -0
- data/test/schema_validator/open_api_3/request_validator_test.rb +110 -0
- data/test/schema_validator/open_api_3/response_validator_test.rb +92 -0
- data/test/test/methods_new_version_test.rb +97 -0
- data/test/test/methods_test.rb +334 -27
- data/test/test/schema_coverage_test.rb +216 -0
- data/test/test_helper.rb +108 -1
- data/test/validation_error_test.rb +3 -1
- metadata +190 -27
- data/lib/committee/query_params_coercer.rb +0 -45
- data/lib/committee/request_validator.rb +0 -44
- data/lib/committee/response_generator.rb +0 -35
- data/lib/committee/response_validator.rb +0 -59
- data/lib/committee/router.rb +0 -62
- data/test/query_params_coercer_test.rb +0 -70
- data/test/request_validator_test.rb +0 -103
- data/test/response_generator_test.rb +0 -61
- data/test/router_test.rb +0 -38
@@ -1,45 +0,0 @@
|
|
1
|
-
# Attempts to coerce params given in the query hash (which are all strings) into
|
2
|
-
# the types specified by the schema.
|
3
|
-
# Currently supported types: null, integer, number and boolean.
|
4
|
-
# +call+ returns a hash of all params which could be coerced - coercion errors
|
5
|
-
# are simply ignored and expected to be handled later by schema validation.
|
6
|
-
module Committee
|
7
|
-
class QueryParamsCoercer
|
8
|
-
def initialize(query_hash, schema)
|
9
|
-
@query_hash = query_hash
|
10
|
-
@schema = schema
|
11
|
-
end
|
12
|
-
|
13
|
-
def call
|
14
|
-
coerced = {}
|
15
|
-
@schema.properties.each do |k, s|
|
16
|
-
original_val = @query_hash[k]
|
17
|
-
unless original_val.nil?
|
18
|
-
s.type.each do |to_type|
|
19
|
-
case to_type
|
20
|
-
when "null"
|
21
|
-
coerced[k] = nil if original_val.empty?
|
22
|
-
when "integer"
|
23
|
-
begin
|
24
|
-
coerced[k] = Integer(original_val)
|
25
|
-
rescue ArgumentError => e
|
26
|
-
raise e unless e.message =~ /invalid value for Integer/
|
27
|
-
end
|
28
|
-
when "number"
|
29
|
-
begin
|
30
|
-
coerced[k] = Float(original_val)
|
31
|
-
rescue ArgumentError => e
|
32
|
-
raise e unless e.message =~ /invalid value for Float/
|
33
|
-
end
|
34
|
-
when "boolean"
|
35
|
-
coerced[k] = true if original_val == "true"
|
36
|
-
coerced[k] = false if original_val == "false"
|
37
|
-
end
|
38
|
-
break if coerced.key?(k)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
coerced
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Committee
|
2
|
-
class RequestValidator
|
3
|
-
def initialize(link, options = {})
|
4
|
-
@link = link
|
5
|
-
@check_content_type = options.fetch(:check_content_type, true)
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(request, data)
|
9
|
-
check_content_type!(request, data) if @check_content_type
|
10
|
-
if @link.schema
|
11
|
-
valid, errors = @link.schema.validate(data)
|
12
|
-
if !valid
|
13
|
-
errors = JsonSchema::SchemaError.aggregate(errors).join("\n")
|
14
|
-
raise InvalidRequest, "Invalid request.\n\n#{errors}"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def request_media_type(request)
|
22
|
-
request.content_type.to_s.split(";").first.to_s
|
23
|
-
end
|
24
|
-
|
25
|
-
def check_content_type!(request, data)
|
26
|
-
content_type = request_media_type(request)
|
27
|
-
if content_type && !empty_request?(request)
|
28
|
-
unless Rack::Mime.match?(content_type, @link.enc_type)
|
29
|
-
raise Committee::InvalidRequest,
|
30
|
-
%{"Content-Type" request header must be set to "#{@link.enc_type}".}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def empty_request?(request)
|
36
|
-
# small optimization: assume GET and DELETE don't have bodies
|
37
|
-
return true if request.get? || request.delete? || !request.body
|
38
|
-
|
39
|
-
data = request.body.read
|
40
|
-
request.body.rewind
|
41
|
-
data.empty?
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Committee
|
2
|
-
class ResponseGenerator
|
3
|
-
def call(link)
|
4
|
-
data = generate_properties(link.target_schema || link.parent)
|
5
|
-
|
6
|
-
# list is a special case; wrap data in an array
|
7
|
-
data = [data] if link.rel == "instances"
|
8
|
-
|
9
|
-
data
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def generate_properties(schema)
|
15
|
-
# special example attribute was included; use its value
|
16
|
-
if !schema.data["example"].nil?
|
17
|
-
schema.data["example"]
|
18
|
-
# null is allowed; use that
|
19
|
-
elsif schema.type.include?("null")
|
20
|
-
nil
|
21
|
-
elsif schema.type.include?("array") && !schema.items.nil?
|
22
|
-
[generate_properties(schema.items)]
|
23
|
-
elsif !schema.properties.empty?
|
24
|
-
data = {}
|
25
|
-
schema.properties.map do |key, value|
|
26
|
-
data[key] = generate_properties(value)
|
27
|
-
end
|
28
|
-
data
|
29
|
-
else
|
30
|
-
raise(%{At "#{schema.pointer}": no "example" attribute and "null" } +
|
31
|
-
%{is not allowed; don't know how to generate property.})
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
module Committee
|
2
|
-
class ResponseValidator
|
3
|
-
attr_reader :validate_errors
|
4
|
-
|
5
|
-
def initialize(link, options = {})
|
6
|
-
@link = link
|
7
|
-
@validate_errors = options[:validate_errors]
|
8
|
-
|
9
|
-
# we should eventually move off of validating against parent schema too
|
10
|
-
# ... this is a Herokuism and not in the specification
|
11
|
-
schema = link.target_schema || link.parent
|
12
|
-
@validator = JsonSchema::Validator.new(schema)
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.validate?(status, options = {})
|
16
|
-
validate_errors = options[:validate_errors]
|
17
|
-
|
18
|
-
status != 204 and validate_errors || (200...300).include?(status)
|
19
|
-
end
|
20
|
-
|
21
|
-
def call(status, headers, data)
|
22
|
-
unless status == 204 # 204 No Content
|
23
|
-
response = Rack::Response.new(data, status, headers)
|
24
|
-
check_content_type!(response)
|
25
|
-
end
|
26
|
-
|
27
|
-
if @link.rel == "instances" && !@link.target_schema
|
28
|
-
if !data.is_a?(Array)
|
29
|
-
raise InvalidResponse, "List endpoints must return an array of objects."
|
30
|
-
end
|
31
|
-
|
32
|
-
# only consider the first object during the validation from here on
|
33
|
-
# (but only in cases where `targetSchema` is not set)
|
34
|
-
data = data[0]
|
35
|
-
|
36
|
-
# if the array was empty, allow it through
|
37
|
-
return if data == nil
|
38
|
-
end
|
39
|
-
|
40
|
-
if self.class.validate?(status, validate_errors: validate_errors) && !@validator.validate(data)
|
41
|
-
errors = JsonSchema::SchemaError.aggregate(@validator.errors).join("\n")
|
42
|
-
raise InvalidResponse, "Invalid response.\n\n#{errors}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def response_media_type(response)
|
49
|
-
response.content_type.to_s.split(";").first.to_s
|
50
|
-
end
|
51
|
-
|
52
|
-
def check_content_type!(response)
|
53
|
-
unless Rack::Mime.match?(response_media_type(response), @link.media_type)
|
54
|
-
raise Committee::InvalidResponse,
|
55
|
-
%{"Content-Type" response header must be set to "#{@link.media_type}".}
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/lib/committee/router.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
module Committee
|
2
|
-
class Router
|
3
|
-
def initialize(schema, options = {})
|
4
|
-
@routes = build_routes(schema)
|
5
|
-
@prefix = options[:prefix]
|
6
|
-
@prefix_regexp = /\A#{Regexp.escape(@prefix)}/.freeze if @prefix
|
7
|
-
end
|
8
|
-
|
9
|
-
def includes?(path)
|
10
|
-
!@prefix || path =~ @prefix_regexp
|
11
|
-
end
|
12
|
-
|
13
|
-
def includes_request?(request)
|
14
|
-
includes?(request.path)
|
15
|
-
end
|
16
|
-
|
17
|
-
def find_link(method, path)
|
18
|
-
path = path.gsub(@prefix_regexp, "") if @prefix
|
19
|
-
if method_routes = @routes[method]
|
20
|
-
method_routes.each do |pattern, link|
|
21
|
-
if path =~ pattern
|
22
|
-
return link
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
|
-
def find_request_link(request)
|
30
|
-
find_link(request.request_method, request.path_info)
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def build_routes(schema)
|
36
|
-
routes = {}
|
37
|
-
|
38
|
-
schema.links.each do |link|
|
39
|
-
method, href = parse_link(link)
|
40
|
-
next unless method
|
41
|
-
routes[method] ||= []
|
42
|
-
routes[method] << [%r{^#{href}$}, link]
|
43
|
-
end
|
44
|
-
|
45
|
-
# recursively iterate through all `properties` subschemas to build a
|
46
|
-
# complete routing table
|
47
|
-
schema.properties.each do |_, subschema|
|
48
|
-
routes.merge!(build_routes(subschema)) { |_, r1, r2| r1 + r2 }
|
49
|
-
end
|
50
|
-
|
51
|
-
routes
|
52
|
-
end
|
53
|
-
|
54
|
-
def parse_link(link)
|
55
|
-
return nil, nil if !link.method || !link.href
|
56
|
-
method = link.method.to_s.upcase
|
57
|
-
# /apps/{id} --> /apps/([^/]+)
|
58
|
-
href = link.href.gsub(/\{(.*?)\}/, "[^/]+")
|
59
|
-
[method, href]
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
describe Committee::QueryParamsCoercer do
|
4
|
-
before do
|
5
|
-
@schema =
|
6
|
-
JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
|
7
|
-
@schema.expand_references!
|
8
|
-
# GET /search/apps
|
9
|
-
@link = @link = @schema.properties["app"].links[5]
|
10
|
-
end
|
11
|
-
|
12
|
-
it "doesn't coerce params not in the schema" do
|
13
|
-
data = {"owner" => "admin"}
|
14
|
-
assert_equal({}, call(data))
|
15
|
-
end
|
16
|
-
|
17
|
-
it "skips values for string param" do
|
18
|
-
data = {"name" => "foo"}
|
19
|
-
assert_equal({}, call(data))
|
20
|
-
end
|
21
|
-
|
22
|
-
it "coerces valid values for boolean param" do
|
23
|
-
data = {"deleted" => "true"}
|
24
|
-
assert_equal({"deleted" => true}, call(data))
|
25
|
-
data = {"deleted" => "false"}
|
26
|
-
assert_equal({"deleted" => false}, call(data))
|
27
|
-
end
|
28
|
-
|
29
|
-
it "skips invalid values for boolean param" do
|
30
|
-
data = {"deleted" => "foo"}
|
31
|
-
assert_equal({}, call(data))
|
32
|
-
end
|
33
|
-
|
34
|
-
it "coerces valid values for integer param" do
|
35
|
-
data = {"per_page" => "3"}
|
36
|
-
assert_equal({"per_page" => 3}, call(data))
|
37
|
-
end
|
38
|
-
|
39
|
-
it "skips invalid values for integer param" do
|
40
|
-
data = {"per_page" => "3.5"}
|
41
|
-
assert_equal({}, call(data))
|
42
|
-
data = {"per_page" => "false"}
|
43
|
-
assert_equal({}, call(data))
|
44
|
-
data = {"per_page" => ""}
|
45
|
-
assert_equal({}, call(data))
|
46
|
-
end
|
47
|
-
|
48
|
-
it "coerces valid values for number param" do
|
49
|
-
data = {"threshold" => "3"}
|
50
|
-
assert_equal({"threshold" => 3.0}, call(data))
|
51
|
-
data = {"threshold" => "3.5"}
|
52
|
-
assert_equal({"threshold" => 3.5}, call(data))
|
53
|
-
end
|
54
|
-
|
55
|
-
it "skips invalid values for number param" do
|
56
|
-
data = {"threshold" => "false"}
|
57
|
-
assert_equal({}, call(data))
|
58
|
-
end
|
59
|
-
|
60
|
-
it "coerces valid values for null param" do
|
61
|
-
data = {"threshold" => ""}
|
62
|
-
assert_equal({"threshold" => nil}, call(data))
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
|
67
|
-
def call(data)
|
68
|
-
Committee::QueryParamsCoercer.new(data, @link.schema).call
|
69
|
-
end
|
70
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
require "stringio"
|
4
|
-
|
5
|
-
describe Committee::RequestValidator do
|
6
|
-
before do
|
7
|
-
@schema =
|
8
|
-
JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
|
9
|
-
@schema.expand_references!
|
10
|
-
# POST /apps/:id
|
11
|
-
@link = @link = @schema.properties["app"].links[0]
|
12
|
-
@request = Rack::Request.new({
|
13
|
-
"CONTENT_TYPE" => "application/json",
|
14
|
-
"rack.input" => StringIO.new("{}"),
|
15
|
-
"REQUEST_METHOD" => "POST"
|
16
|
-
})
|
17
|
-
end
|
18
|
-
|
19
|
-
it "passes through a valid request with Content-Type options" do
|
20
|
-
@headers = { "Content-Type" => "application/json; charset=utf-8" }
|
21
|
-
call({})
|
22
|
-
end
|
23
|
-
|
24
|
-
it "passes through a valid request" do
|
25
|
-
data = {
|
26
|
-
"name" => "heroku-api",
|
27
|
-
}
|
28
|
-
call(data)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "passes through a valid request with Content-Type options" do
|
32
|
-
@request =
|
33
|
-
Rack::Request.new({
|
34
|
-
"CONTENT_TYPE" => "application/json; charset=utf-8",
|
35
|
-
"rack.input" => StringIO.new("{}"),
|
36
|
-
})
|
37
|
-
data = {
|
38
|
-
"name" => "heroku-api",
|
39
|
-
}
|
40
|
-
call(data)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "detects an invalid request Content-Type" do
|
44
|
-
e = assert_raises(Committee::InvalidRequest) {
|
45
|
-
@request =
|
46
|
-
Rack::Request.new({
|
47
|
-
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
48
|
-
"rack.input" => StringIO.new("{}"),
|
49
|
-
})
|
50
|
-
call({})
|
51
|
-
}
|
52
|
-
message =
|
53
|
-
%{"Content-Type" request header must be set to "application/json".}
|
54
|
-
assert_equal message, e.message
|
55
|
-
end
|
56
|
-
|
57
|
-
it "allows skipping content_type check" do
|
58
|
-
@request =
|
59
|
-
Rack::Request.new({
|
60
|
-
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
61
|
-
"rack.input" => StringIO.new("{}"),
|
62
|
-
})
|
63
|
-
call({}, check_content_type: false)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "detects an missing parameter in GET requests" do
|
67
|
-
# GET /apps/search?query=...
|
68
|
-
@link = @link = @schema.properties["app"].links[5]
|
69
|
-
@request = Rack::Request.new({})
|
70
|
-
e = assert_raises(Committee::InvalidRequest) do
|
71
|
-
call({})
|
72
|
-
end
|
73
|
-
message =
|
74
|
-
%{Invalid request.\n\n#: failed schema #/definitions/app/links/5/schema: "query" wasn't supplied.}
|
75
|
-
assert_equal message, e.message
|
76
|
-
end
|
77
|
-
|
78
|
-
it "allows an invalid Content-Type with an empty body" do
|
79
|
-
@request =
|
80
|
-
Rack::Request.new({
|
81
|
-
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
82
|
-
"rack.input" => StringIO.new(""),
|
83
|
-
})
|
84
|
-
call({})
|
85
|
-
end
|
86
|
-
|
87
|
-
it "detects a parameter of the wrong pattern" do
|
88
|
-
data = {
|
89
|
-
"name" => "%@!"
|
90
|
-
}
|
91
|
-
e = assert_raises(Committee::InvalidRequest) do
|
92
|
-
call(data)
|
93
|
-
end
|
94
|
-
message = %{Invalid request.\n\n#/name: failed schema #/definitions/app/links/0/schema/properties/name: %@! does not match /^[a-z][a-z0-9-]{3,30}$/.}
|
95
|
-
assert_equal message, e.message
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
|
100
|
-
def call(data, options={})
|
101
|
-
Committee::RequestValidator.new(@link, options).call(@request, data)
|
102
|
-
end
|
103
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
describe Committee::ResponseGenerator do
|
4
|
-
before do
|
5
|
-
@schema =
|
6
|
-
JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
|
7
|
-
@schema.expand_references!
|
8
|
-
# GET /apps/:id
|
9
|
-
@get_link = @link = @schema.properties["app"].links[2]
|
10
|
-
# GET /apps
|
11
|
-
@list_link = @schema.properties["app"].links[3]
|
12
|
-
end
|
13
|
-
|
14
|
-
it "generates string properties" do
|
15
|
-
data = call
|
16
|
-
assert data["name"].is_a?(String)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "generates non-string properties" do
|
20
|
-
data = call
|
21
|
-
assert_includes [FalseClass, TrueClass], data["maintenance"].class
|
22
|
-
end
|
23
|
-
|
24
|
-
it "wraps list data in an array" do
|
25
|
-
@link = @list_link
|
26
|
-
data = call
|
27
|
-
assert data.is_a?(Array)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "wraps list data in an array" do
|
31
|
-
@link = @list_link
|
32
|
-
|
33
|
-
@link.rel = nil
|
34
|
-
|
35
|
-
data = call
|
36
|
-
assert data.is_a?(Array)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "errors with no known route for generation" do
|
40
|
-
@link = @get_link
|
41
|
-
|
42
|
-
# tweak the schema so that it can't be generated
|
43
|
-
property = @schema.properties["app"].properties["maintenance"]
|
44
|
-
property.data["example"] = nil
|
45
|
-
property.type = []
|
46
|
-
|
47
|
-
e = assert_raises(RuntimeError) do
|
48
|
-
call
|
49
|
-
end
|
50
|
-
|
51
|
-
expected = <<-eos.gsub(/\n +/, "").strip
|
52
|
-
At "#/definitions/app/properties/maintenance": no "example" attribute and
|
53
|
-
"null" is not allowed; don't know how to generate property.
|
54
|
-
eos
|
55
|
-
assert_equal expected, e.message
|
56
|
-
end
|
57
|
-
|
58
|
-
def call
|
59
|
-
Committee::ResponseGenerator.new.call(@link)
|
60
|
-
end
|
61
|
-
end
|
data/test/router_test.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
describe Committee::Router do
|
4
|
-
it "builds routes without parameters" do
|
5
|
-
refute_nil router.find_link("GET", "/apps")
|
6
|
-
end
|
7
|
-
|
8
|
-
it "builds routes with parameters" do
|
9
|
-
refute_nil router.find_link("GET", "/apps/123")
|
10
|
-
end
|
11
|
-
|
12
|
-
it "doesn't match anything on a /" do
|
13
|
-
assert_nil router.find_link("GET", "/")
|
14
|
-
end
|
15
|
-
|
16
|
-
it "takes a prefix" do
|
17
|
-
# this is a sociopathic example
|
18
|
-
assert router(prefix: "/kpi").find_link("GET", "/kpi/apps/123")
|
19
|
-
end
|
20
|
-
|
21
|
-
it "includes all paths without a prefix" do
|
22
|
-
assert router.includes?("/")
|
23
|
-
assert router.includes?("/apps")
|
24
|
-
end
|
25
|
-
|
26
|
-
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")
|
30
|
-
end
|
31
|
-
|
32
|
-
def router(options = {})
|
33
|
-
data = JSON.parse(File.read("./test/data/schema.json"))
|
34
|
-
schema = JsonSchema.parse!(data)
|
35
|
-
schema.expand_references!
|
36
|
-
Committee::Router.new(schema, options)
|
37
|
-
end
|
38
|
-
end
|