hyperdrive 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +12 -4
- data/Gemfile +2 -0
- data/hyperdrive.gemspec +6 -2
- data/lib/hyperdrive/docs.rb +10 -11
- data/lib/hyperdrive/dsl/resource.rb +10 -15
- data/lib/hyperdrive/dsl.rb +49 -3
- data/lib/hyperdrive/endpoint.rb +65 -0
- data/lib/hyperdrive/errors/missing_required_param.rb +19 -0
- data/lib/hyperdrive/errors/not_acceptable.rb +18 -0
- data/lib/hyperdrive/errors.rb +13 -8
- data/lib/hyperdrive/filter.rb +20 -0
- data/lib/hyperdrive/hateoas.rb +45 -0
- data/lib/hyperdrive/middleware/accept.rb +16 -0
- data/lib/hyperdrive/middleware/content_negotiation.rb +19 -0
- data/lib/hyperdrive/middleware/cors.rb +36 -0
- data/lib/hyperdrive/middleware/error.rb +35 -0
- data/lib/hyperdrive/middleware/request_method.rb +31 -0
- data/lib/hyperdrive/middleware/required_params.rb +35 -0
- data/lib/hyperdrive/middleware/resource.rb +18 -0
- data/lib/hyperdrive/middleware/sanitize_params.rb +25 -0
- data/lib/hyperdrive/middleware.rb +10 -0
- data/lib/hyperdrive/param.rb +44 -0
- data/lib/hyperdrive/resource.rb +74 -30
- data/lib/hyperdrive/server.rb +16 -17
- data/lib/hyperdrive/utils.rb +27 -0
- data/lib/hyperdrive/values.rb +37 -3
- data/lib/hyperdrive/version.rb +1 -1
- data/lib/hyperdrive.rb +21 -7
- data/spec/hyperdrive/docs_spec.rb +14 -8
- data/spec/hyperdrive/dsl/resource_spec.rb +27 -37
- data/spec/hyperdrive/dsl_spec.rb +52 -0
- data/spec/hyperdrive/endpoint_spec.rb +22 -0
- data/spec/hyperdrive/filter_spec.rb +34 -0
- data/spec/hyperdrive/hateoas_spec.rb +42 -0
- data/spec/hyperdrive/middleware/accept_spec.rb +15 -0
- data/spec/hyperdrive/middleware/content_negotiation_spec.rb +29 -0
- data/spec/hyperdrive/middleware/cors_spec.rb +47 -0
- data/spec/hyperdrive/middleware/error_spec.rb +25 -0
- data/spec/hyperdrive/middleware/request_method_spec.rb +28 -0
- data/spec/hyperdrive/middleware/required_params_spec.rb +43 -0
- data/spec/hyperdrive/middleware/resource_spec.rb +15 -0
- data/spec/hyperdrive/middleware/sanitize_params_spec.rb +24 -0
- data/spec/hyperdrive/param_spec.rb +34 -0
- data/spec/hyperdrive/resource_spec.rb +87 -25
- data/spec/hyperdrive/server_spec.rb +48 -7
- data/spec/hyperdrive/utils_spec.rb +38 -0
- data/spec/hyperdrive/values_spec.rb +37 -0
- data/spec/spec_helper.rb +71 -12
- metadata +106 -11
- data/.coveralls.yml +0 -1
- data/lib/hyperdrive/dsl/main.rb +0 -19
- data/lib/hyperdrive/response.rb +0 -42
- data/spec/hyperdrive/dsl/main_spec.rb +0 -16
- data/spec/hyperdrive/response_spec.rb +0 -23
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::ContentNegotiation do
|
6
|
+
def app
|
7
|
+
Rack::Builder.new do
|
8
|
+
use Hyperdrive::Middleware::ContentNegotiation
|
9
|
+
map '/' do
|
10
|
+
run ->(env) { [200, {}, ["#{env['hyperdrive.media_type']}"]] }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
@resource = default_resource
|
17
|
+
@env = default_rack_env(@resource)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns the best supported media type" do
|
21
|
+
get '/', {}, @env
|
22
|
+
last_response.body.must_equal 'application/vnd.hyperdrive.things+hal+json'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "throws an error if the media type requested is not supported" do
|
26
|
+
bad_env = @env.merge('hyperdrive.accept' => Rack::Accept::MediaType.new('application/xml'), 'HTTP_ACCEPT' => 'application/xml')
|
27
|
+
-> { get '/', {}, bad_env }.must_raise Hyperdrive::Errors::NotAcceptable
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::CORS do
|
6
|
+
def app
|
7
|
+
cors_options = {
|
8
|
+
origins: '*',
|
9
|
+
allow_headers: '*, Content-Type, Accept, AUTHORIZATION, Cache-Control',
|
10
|
+
credentials: true,
|
11
|
+
expose_headers: 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma',
|
12
|
+
max_age: 86400
|
13
|
+
}
|
14
|
+
inner_app = ->(env) { [200, {}, ['']] }
|
15
|
+
Hyperdrive::Middleware::CORS.new(inner_app, cors_options)
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
env = default_rack_env(default_resource)
|
20
|
+
get '/', {}, env
|
21
|
+
@headers = last_response.headers
|
22
|
+
end
|
23
|
+
|
24
|
+
it "allows origins" do
|
25
|
+
@headers['Access-Control-Allow-Origin'].must_equal '*'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "allows methods" do
|
29
|
+
@headers['Access-Control-Allow-Methods'].must_equal 'OPTIONS, GET, HEAD'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "allows headers" do
|
33
|
+
@headers['Access-Control-Allow-Headers'].must_equal '*, Content-Type, Accept, AUTHORIZATION, Cache-Control'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "allows credentials" do
|
37
|
+
@headers['Access-Control-Allow-Credentials'].must_equal "true"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "has a max age" do
|
41
|
+
@headers['Access-Control-Max-Age'].must_equal "86400"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "exposes headers" do
|
45
|
+
@headers['Access-Control-Expose-Headers'].must_equal 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma'
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::Error do
|
6
|
+
def app
|
7
|
+
Rack::Builder.new do
|
8
|
+
use Hyperdrive::Middleware::Error
|
9
|
+
run ->(env) { raise Hyperdrive::Errors::HTTPError }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
@response = %Q({"_links":{"root":{"href":"/","title":"API Root"}},"error":{"type":"HTTPError","message":"Hyperdrive::Errors::HTTPError"}})
|
15
|
+
get '/'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "traps errors" do
|
19
|
+
last_response.status.must_equal 500
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns a formatted error message" do
|
23
|
+
last_response.body.must_equal @response
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::RequestMethod do
|
6
|
+
def app
|
7
|
+
inner_app = ->(env) { [200, {}, ['']] }
|
8
|
+
Hyperdrive::Middleware::RequestMethod.new(inner_app)
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
@resource = default_resource
|
13
|
+
@env = default_rack_env(@resource)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "is successful if the request method is supported" do
|
17
|
+
get '/', {}, @env
|
18
|
+
last_response.successful?.must_equal true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "throws an error if hyperdrive doesn't support the request method" do
|
22
|
+
->{ request('/', @env.merge('REQUEST_METHOD' => 'TRACE')) }.must_raise Hyperdrive::Errors::NotImplemented
|
23
|
+
end
|
24
|
+
|
25
|
+
it "throws an error if the resource doesn't support the request method" do
|
26
|
+
->{ post('/', {}, @env.merge('REQUEST_METHOD' => 'POST')) }.must_raise Hyperdrive::Errors::MethodNotAllowed
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::RequiredParams do
|
6
|
+
def app
|
7
|
+
inner_app = ->(env) { [200, {}, [env['hyperdrive.params'][:id]]] }
|
8
|
+
Hyperdrive::Middleware::RequiredParams.new(inner_app)
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
@resource = default_resource
|
13
|
+
@env = default_rack_env(@resource).merge('hyperdrive.params' => {})
|
14
|
+
@filters = { parent_id: '1000' }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "Filters" do
|
18
|
+
it "responds successfully if required filter is present" do
|
19
|
+
get '/', @filters, @env.merge('hyperdrive.params' => @filters)
|
20
|
+
last_response.successful?.must_equal true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "raises an error if required filter is missing" do
|
24
|
+
->{ get '/', {}, @env }.must_raise Hyperdrive::Errors::MissingRequiredParam
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "Params" do
|
29
|
+
before do
|
30
|
+
@env.merge!('REQUEST_METHOD' => 'PUT')
|
31
|
+
@params = { id: '1001', name: 'yoda' }
|
32
|
+
end
|
33
|
+
|
34
|
+
it "responds successfully if required params are present" do
|
35
|
+
put '/', @params, @env.merge('hyperdrive.params' => @params)
|
36
|
+
last_response.successful?.must_equal true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "raises an error if required param is missing" do
|
40
|
+
->{ put '/', {}, @env }.must_raise Hyperdrive::Errors::MissingRequiredParam
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::Resource do
|
6
|
+
def app
|
7
|
+
inner_app = ->(env) { [200, {}, [env['hyperdrive.resource'].namespace]] }
|
8
|
+
Hyperdrive::Middleware::Resource.new(inner_app, default_resource)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "adds the requested resource to rack's env" do
|
12
|
+
get '/'
|
13
|
+
last_response.body.must_equal "things"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Middleware::SanitizeParams do
|
6
|
+
before do
|
7
|
+
@env = default_rack_env(default_resource)
|
8
|
+
end
|
9
|
+
|
10
|
+
def app
|
11
|
+
inner_app = ->(env) { [200, {}, [env['hyperdrive.params']]] }
|
12
|
+
Hyperdrive::Middleware::SanitizeParams.new(inner_app)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "will sanitize filters" do
|
16
|
+
get '/', { 'id' => '1001', 'removed' => 'me' }, @env
|
17
|
+
last_response.body.must_equal "{:id=>\"1001\"}"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "will sanitize params" do
|
21
|
+
post '/', { 'id' => '1001', 'removed' => 'me' }, @env
|
22
|
+
last_response.body.must_equal "{:id=>\"1001\"}"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Param do
|
6
|
+
before do
|
7
|
+
@param = default_param
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has a name" do
|
11
|
+
@param.name.must_equal 'id'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "has a description" do
|
15
|
+
@param.description.must_equal 'Identifier'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns an array of HTTP methods it's required for" do
|
19
|
+
@param.required.must_equal %w(PUT PATCH DELETE)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns true if the param is required for the given HTTP method" do
|
23
|
+
@param.required?('PUT').must_equal true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns false if the param is not required for the given HTTP method" do
|
27
|
+
@param.required?('POST').must_equal false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "converts itself as a hash" do
|
31
|
+
constraints = { name: 'id', description: 'Identifier', type: 'String', constraints: 'Required for: PUT, PATCH, DELETE. Must be a valid BSON Object ID.' }
|
32
|
+
@param.to_hash.must_equal constraints
|
33
|
+
end
|
34
|
+
end
|
@@ -2,7 +2,27 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Hyperdrive::Resource do
|
4
4
|
before do
|
5
|
-
@resource = Hyperdrive::Resource.new(:thing)
|
5
|
+
@resource = Hyperdrive::Resource.new(:thing, { vendor: 'hyperdrive', media_types: ['json'] })
|
6
|
+
@resource.register_param(:name, 'Thing Name')
|
7
|
+
@resource.register_filter(:parent_id, 'Parent ID', required: true)
|
8
|
+
@resource.register_request_handler(:get, Proc.new { |env| 'v1' })
|
9
|
+
@resource.register_request_handler(:get, Proc.new { |env| 'v2' }, 'v2')
|
10
|
+
@media_types = ["application/vnd.hyperdrive.things.v2+json",
|
11
|
+
"application/vnd.hyperdrive.things.v1+json",
|
12
|
+
"application/vnd.hyperdrive.things+json",
|
13
|
+
"application/vnd.hyperdrive+json"]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has an ID" do
|
17
|
+
@resource.id.must_equal "hyperdrive:things"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has a namespace" do
|
21
|
+
@resource.namespace.must_equal 'things'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "has an endpoint" do
|
25
|
+
@resource.endpoint.must_equal '/things'
|
6
26
|
end
|
7
27
|
|
8
28
|
it "has a name" do
|
@@ -11,57 +31,99 @@ describe Hyperdrive::Resource do
|
|
11
31
|
end
|
12
32
|
|
13
33
|
it "has a description" do
|
14
|
-
@resource.
|
15
|
-
@resource.
|
34
|
+
@resource.description = 'Thing Description'
|
35
|
+
@resource.description.must_equal 'Thing Description'
|
16
36
|
end
|
17
37
|
|
18
|
-
it "
|
19
|
-
@resource.
|
38
|
+
it "auto-registers the :id param" do
|
39
|
+
@resource.params[:id].description.must_equal 'Identifier'
|
20
40
|
end
|
21
41
|
|
22
|
-
it "
|
23
|
-
@resource.
|
24
|
-
@resource.allowed_params[:id][:required].must_equal %w(PUT PATCH DELETE)
|
42
|
+
it "registers a param" do
|
43
|
+
@resource.params[:name].description.must_equal 'Thing Name'
|
25
44
|
end
|
26
45
|
|
27
|
-
it "
|
28
|
-
@resource.
|
29
|
-
|
30
|
-
|
46
|
+
it "returns true if the param is required for the given HTTP Method" do
|
47
|
+
@resource.required_param?(:name, 'POST').must_equal true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns false if the param is not required for the given HTTP Method" do
|
51
|
+
@resource.required_param?(:name, 'DELETE').must_equal false
|
31
52
|
end
|
32
53
|
|
33
54
|
it "auto-registers the :id filter" do
|
34
|
-
@resource.filters[:id]
|
35
|
-
@resource.filters[:id][:required].must_equal false
|
55
|
+
@resource.filters[:id].description.must_equal 'Resource Identifier'
|
36
56
|
end
|
37
57
|
|
38
58
|
it "registers a filter" do
|
39
|
-
@resource.
|
40
|
-
|
41
|
-
|
59
|
+
@resource.filters[:parent_id].description.must_equal 'Parent ID'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns true if the filter is required for the given HTTP Method" do
|
63
|
+
@resource.required_filter?(:parent_id, 'GET').must_equal true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns false if the filter is not required for the given HTTP Method" do
|
67
|
+
@resource.required_filter?(:parent_id, 'OPTIONS').must_equal false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns true if the param (or filter) is required" do
|
71
|
+
@resource.required?(:name, 'POST').must_equal true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns true if the filter (or param) is required" do
|
75
|
+
@resource.required?(:parent_id, 'GET').must_equal true
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns false if the param (or filter) is not required" do
|
79
|
+
@resource.required?(:name, 'GET').must_equal false
|
42
80
|
end
|
43
81
|
|
44
|
-
it "
|
45
|
-
@resource.
|
46
|
-
|
82
|
+
it "returns false if the filter (or param) is not required" do
|
83
|
+
@resource.required?(:parent_id, 'DELETE').must_equal false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "registers a request handler" do
|
87
|
+
@resource.request_handlers[:get]['v1'].must_be :===, Proc
|
88
|
+
end
|
89
|
+
|
90
|
+
it "auto-registers HEAD request handler when GET handler is registered" do
|
91
|
+
@resource.request_handlers[:head]['v1'].must_be :===, Proc
|
47
92
|
end
|
48
93
|
|
49
94
|
it "returns the specified request handler" do
|
50
|
-
@resource.
|
51
|
-
@resource.request_handler('GET').call.must_equal 'ok'
|
95
|
+
@resource.request_handler('GET').must_be :===, Proc
|
52
96
|
end
|
53
97
|
|
54
98
|
it "returns true if the request can be handled" do
|
55
|
-
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
56
99
|
@resource.request_method_allowed?('GET').must_equal true
|
57
100
|
end
|
58
101
|
|
59
102
|
it "returns false if the request can not be handled" do
|
60
|
-
@resource.request_method_allowed?('
|
103
|
+
@resource.request_method_allowed?('POST').must_equal false
|
61
104
|
end
|
62
105
|
|
63
106
|
it "returns the request methods that can handled" do
|
64
|
-
@resource.define_request_handler(:get, Proc.new { return 'ok' })
|
65
107
|
@resource.allowed_methods.must_equal ['OPTIONS','GET','HEAD']
|
66
108
|
end
|
109
|
+
|
110
|
+
it "returns the request handler for the specified version" do
|
111
|
+
@resource.request_handler('GET', 'v2').must_be :===, Proc
|
112
|
+
end
|
113
|
+
|
114
|
+
it "returns the acceptable content types" do
|
115
|
+
@resource.acceptable_content_types('GET').must_equal @media_types
|
116
|
+
end
|
117
|
+
|
118
|
+
it "returns the available versions for this resource" do
|
119
|
+
@resource.available_versions('GET').must_equal ['v2','v1']
|
120
|
+
end
|
121
|
+
|
122
|
+
it "returns the latest available version for this resource" do
|
123
|
+
@resource.latest_version('GET').must_equal 'v2'
|
124
|
+
end
|
125
|
+
|
126
|
+
it "returns a hash representation of the resource" do
|
127
|
+
@resource.to_hash.must_be_kind_of Hash
|
128
|
+
end
|
67
129
|
end
|
@@ -1,11 +1,52 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'spec_helper'
|
4
|
+
|
3
5
|
describe Hyperdrive::Server do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
def app
|
7
|
+
Hyperdrive::Server
|
8
|
+
end
|
9
|
+
|
10
|
+
before do
|
11
|
+
sample_api
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
hyperdrive.send(:reset!)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "responds to GET requests successfully" do
|
19
|
+
get '/things', { parent_id: 42 }
|
20
|
+
last_response.successful?.must_equal true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "responds to HEAD requests successfully" do
|
24
|
+
head '/things', { parent_id: 42 }
|
25
|
+
last_response.successful?.must_equal true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "responds to OPTIONS requests successfully" do
|
29
|
+
options '/things'
|
30
|
+
last_response.successful?.must_equal true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "responds to POST requests successfully" do
|
34
|
+
post '/things', { name: 'bender' }
|
35
|
+
last_response.successful?.must_equal true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "responds to PUT requests successfully" do
|
39
|
+
put '/things', { id: 1, name: 'bender' }
|
40
|
+
last_response.successful?.must_equal true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "responds to PATCH requests successfully" do
|
44
|
+
patch '/things', { id: 1, name: 'bender' }
|
45
|
+
last_response.successful?.must_equal true
|
46
|
+
end
|
47
|
+
|
48
|
+
it "responds to DELETE requests successfully" do
|
49
|
+
delete '/things', { id: 1 }
|
50
|
+
last_response.successful?.must_equal true
|
51
|
+
end
|
11
52
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Utils do
|
6
|
+
context '.sanitize_keys' do
|
7
|
+
before do
|
8
|
+
@subject = Hyperdrive::Utils.sanitize_keys([:keep], { keep: 'this', remove: 'that' })
|
9
|
+
end
|
10
|
+
|
11
|
+
it "removes keys that were specified from the given hash" do
|
12
|
+
@subject.key?(:remove).must_equal false
|
13
|
+
end
|
14
|
+
|
15
|
+
it "keeps keys that were not specified from the given hash" do
|
16
|
+
@subject.key?(:keep).must_equal true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context '.symbolize_keys' do
|
21
|
+
before do
|
22
|
+
@hash = { 'string' => 'cheese', 'collection' => [{'skylanders' => 155}], 'map' => { 'oceans' => 'blue' } }
|
23
|
+
@subject = Hyperdrive::Utils.symbolize_keys(@hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can symbolize the keys of a hash" do
|
27
|
+
@subject[:string].must_equal 'cheese'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "can symbolize the keys of nested hashes" do
|
31
|
+
@subject[:map][:oceans].must_equal 'blue'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can symbolize the keys of arrays of hashes" do
|
35
|
+
@subject[:collection].first[:skylanders].must_equal 155
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Hyperdrive::Values do
|
6
|
+
before do
|
7
|
+
@values = Hyperdrive::Values
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns a list of request methods that are definable" do
|
11
|
+
@values.definable_request_methods.must_be_kind_of Array
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns a list of request_methods that are supported" do
|
15
|
+
@values.supported_request_methods.must_be_kind_of Array
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns a map of request methods to http request methods" do
|
19
|
+
@values.request_methods.must_be_kind_of Hash
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns a map of http request methods to request methods" do
|
23
|
+
@values.http_request_methods.must_be_kind_of Hash
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns a map of default cors options" do
|
27
|
+
@values.default_cors_options.must_be_kind_of Hash
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns a map of default config options" do
|
31
|
+
@values.default_cors_options.must_be_kind_of Hash
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns a map of default headers" do
|
35
|
+
@values.default_cors_options.must_be_kind_of Hash
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'rubinius/coverage' if RUBY_ENGINE == 'rubinius'
|
4
|
+
require "codeclimate-test-reporter"
|
5
|
+
CodeClimate::TestReporter.start
|
6
|
+
|
3
7
|
# bootstrap the environment
|
4
8
|
ENV['RACK_ENV'] = 'test'
|
5
9
|
lib_path = File.expand_path('../lib', __FILE__)
|
@@ -13,27 +17,82 @@ Bundler.setup(:default, ENV['RACK_ENV'])
|
|
13
17
|
require 'hyperdrive'
|
14
18
|
|
15
19
|
# Fire up the BDD Stack
|
20
|
+
require 'rack/test'
|
16
21
|
require 'minitest/autorun'
|
17
22
|
require "minitest-spec-context"
|
18
23
|
require 'minitest/reporters'
|
19
24
|
|
20
25
|
# all systems go
|
21
26
|
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
22
|
-
|
27
|
+
include Rack::Test::Methods
|
28
|
+
|
29
|
+
module Hyperdrive
|
30
|
+
module TestData
|
31
|
+
def default_rack_env(resource = nil)
|
32
|
+
default_env = {
|
33
|
+
"rack.version" => Rack::VERSION,
|
34
|
+
"rack.input" => StringIO.new,
|
35
|
+
"rack.errors" => StringIO.new,
|
36
|
+
"rack.multithread" => true,
|
37
|
+
"rack.multiprocess" => true,
|
38
|
+
"rack.run_once" => false,
|
39
|
+
'HTTP_ACCEPT_CHARSET' => 'UTF-8',
|
40
|
+
'HTTP_ACCEPT' => 'application/vnd.hyperdrive.things+hal+json;q=0.8, application/json;q=1',
|
41
|
+
'HTTP_ACCEPT_LANGUAGE' => 'en',
|
42
|
+
'REQUEST_METHOD' => 'GET',
|
43
|
+
'QUERY_STRING' => 'id=1001'
|
44
|
+
}
|
45
|
+
default_env.merge!('hyperdrive.accept' => Rack::Accept::MediaType.new(default_env['HTTP_ACCEPT']))
|
46
|
+
default_env.merge!('hyperdrive.resource' => resource) if resource
|
47
|
+
default_env
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_resource
|
51
|
+
resource = Hyperdrive::Resource.new(:thing, { vendor: 'hyperdrive', media_types: ['hal+json', 'json'] })
|
52
|
+
resource.register_request_handler(:get, Proc.new { |env| }, 'v1')
|
53
|
+
resource.register_filter(:parent_id, '', required: true)
|
54
|
+
resource
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_filter
|
58
|
+
Hyperdrive::Filter.new(:parent_id, 'Parent Identifier', required: true, constraints: 'Must be a valid BSON Object ID.')
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_param
|
62
|
+
Hyperdrive::Param.new(:id, 'Identifier', required: %w(PUT PATCH DELETE), constraints: 'Must be a valid BSON Object ID.')
|
63
|
+
end
|
64
|
+
|
65
|
+
def sample_api
|
66
|
+
hyperdrive do
|
67
|
+
resource(:thing) do
|
68
|
+
name 'Thing Resource'
|
69
|
+
description 'Description of Thing Resource'
|
70
|
+
|
71
|
+
param :name, '50 Chars or less', required: true
|
72
|
+
filter :parent_id, 'Parent ID of Thing', required: true
|
73
|
+
|
74
|
+
request(:get) do
|
75
|
+
'ok'
|
76
|
+
end
|
77
|
+
|
78
|
+
request(:post) do
|
79
|
+
'ok'
|
80
|
+
end
|
23
81
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
name 'Thing Resource'
|
28
|
-
desc 'Description of Thing Resource'
|
82
|
+
request(:put) do
|
83
|
+
'ok'
|
84
|
+
end
|
29
85
|
|
30
|
-
|
31
|
-
|
32
|
-
|
86
|
+
request(:patch) do
|
87
|
+
'ok'
|
88
|
+
end
|
33
89
|
|
34
|
-
|
35
|
-
|
36
|
-
|
90
|
+
request(:delete) do
|
91
|
+
''
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
37
95
|
end
|
38
96
|
end
|
39
97
|
end
|
98
|
+
include Hyperdrive::TestData
|