restfulness 0.3.2 → 0.3.3
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -5
- data/README.md +98 -80
- data/lib/restfulness.rb +3 -0
- data/lib/restfulness/dispatchers/rack.rb +1 -0
- data/lib/restfulness/headers/accept.rb +66 -0
- data/lib/restfulness/headers/media_type.rb +127 -0
- data/lib/restfulness/request.rb +43 -15
- data/lib/restfulness/version.rb +1 -1
- data/restfulness.gemspec +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/application_spec.rb +14 -14
- data/spec/unit/dispatcher_spec.rb +1 -1
- data/spec/unit/dispatchers/rack_spec.rb +21 -20
- data/spec/unit/exceptions_spec.rb +5 -5
- data/spec/unit/headers/accept_spec.rb +70 -0
- data/spec/unit/headers/media_type_spec.rb +262 -0
- data/spec/unit/http_authentication/basic_spec.rb +7 -7
- data/spec/unit/path_spec.rb +19 -19
- data/spec/unit/request_spec.rb +96 -44
- data/spec/unit/requests/authorization_header_spec.rb +8 -8
- data/spec/unit/requests/authorization_spec.rb +3 -3
- data/spec/unit/resource_spec.rb +28 -28
- data/spec/unit/resources/authentication_spec.rb +2 -2
- data/spec/unit/resources/events_spec.rb +1 -1
- data/spec/unit/response_spec.rb +53 -53
- data/spec/unit/route_spec.rb +24 -24
- data/spec/unit/router_spec.rb +29 -29
- data/spec/unit/sanitizer_spec.rb +9 -9
- metadata +13 -7
@@ -28,8 +28,8 @@ describe Restfulness::Resources::Authentication do
|
|
28
28
|
obj = AuthResource.new(request, response)
|
29
29
|
expect { |b| obj.authenticate_with_http_basic(&b) }.to yield_control
|
30
30
|
obj.authenticate_with_http_basic do |username, password|
|
31
|
-
username.
|
32
|
-
password.
|
31
|
+
expect(username).to eql('Aladdin')
|
32
|
+
expect(password).to eql('open sesame')
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -54,7 +54,7 @@ describe Restfulness::Resources::Events do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should support bad_request! with paramters" do
|
57
|
-
obj.
|
57
|
+
expect(obj).to receive(:error!).with(400, {:pay => 'load'}, {})
|
58
58
|
obj.instance_eval do
|
59
59
|
bad_request!({:pay => 'load'}, {})
|
60
60
|
end
|
data/spec/unit/response_spec.rb
CHANGED
@@ -25,23 +25,23 @@ describe Restfulness::Response do
|
|
25
25
|
|
26
26
|
describe "#initialize" do
|
27
27
|
it "should assign request and headers" do
|
28
|
-
obj.request.
|
29
|
-
obj.headers.
|
30
|
-
obj.status.
|
31
|
-
obj.payload.
|
28
|
+
expect(obj.request).to eql(request)
|
29
|
+
expect(obj.headers).to eql({})
|
30
|
+
expect(obj.status).to be_nil
|
31
|
+
expect(obj.payload).to be_nil
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
describe "#run" do
|
36
36
|
context "without route" do
|
37
37
|
it "should not do anything" do
|
38
|
-
request.
|
39
|
-
request.
|
38
|
+
allow(request).to receive(:route).and_return(nil)
|
39
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
40
40
|
obj.run
|
41
|
-
obj.status.
|
42
|
-
obj.payload.
|
43
|
-
obj.headers['Content-Type'].
|
44
|
-
obj.headers['Content-Length'].
|
41
|
+
expect(obj.status).to eql(404)
|
42
|
+
expect(obj.payload).to be_empty
|
43
|
+
expect(obj.headers['Content-Type']).to be_nil
|
44
|
+
expect(obj.headers['Content-Length']).to be_nil
|
45
45
|
end
|
46
46
|
end
|
47
47
|
context "with route" do
|
@@ -50,46 +50,46 @@ describe Restfulness::Response do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should try to build resource and run it" do
|
53
|
-
request.
|
53
|
+
allow(request).to receive(:route).and_return(route)
|
54
54
|
request.action = :get
|
55
|
-
request.
|
55
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
56
56
|
resource = double(:Resource)
|
57
|
-
resource.
|
58
|
-
resource.
|
59
|
-
route.
|
57
|
+
expect(resource).to receive(:check_callbacks)
|
58
|
+
expect(resource).to receive(:call).and_return({:foo => 'bar'})
|
59
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
60
60
|
obj.run
|
61
|
-
obj.status.
|
61
|
+
expect(obj.status).to eql(200)
|
62
62
|
str = "{\"foo\":\"bar\"}"
|
63
|
-
obj.payload.
|
64
|
-
obj.headers['Content-Type'].
|
65
|
-
obj.headers['Content-Length'].
|
63
|
+
expect(obj.payload).to eql(str)
|
64
|
+
expect(obj.headers['Content-Type']).to match(/application\/json/)
|
65
|
+
expect(obj.headers['Content-Length']).to eql(str.bytesize.to_s)
|
66
66
|
end
|
67
67
|
|
68
68
|
it "should call resource and set 204 result if no content" do
|
69
|
-
request.
|
69
|
+
allow(request).to receive(:route).and_return(route)
|
70
70
|
request.action = :get
|
71
|
-
request.
|
71
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
72
72
|
resource = double(:Resource)
|
73
|
-
resource.
|
74
|
-
resource.
|
75
|
-
route.
|
73
|
+
expect(resource).to receive(:check_callbacks)
|
74
|
+
expect(resource).to receive(:call).and_return(nil)
|
75
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
76
76
|
obj.run
|
77
|
-
obj.status.
|
78
|
-
obj.headers['Content-Type'].
|
79
|
-
obj.headers['Content-Length'].
|
77
|
+
expect(obj.status).to eql(204)
|
78
|
+
expect(obj.headers['Content-Type']).to be_nil
|
79
|
+
expect(obj.headers['Content-Length']).to be_nil
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should set string content type if payload is a string" do
|
83
|
-
request.
|
83
|
+
allow(request).to receive(:route).and_return(route)
|
84
84
|
request.action = :get
|
85
|
-
request.
|
85
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
86
86
|
resource = double(:Resource)
|
87
|
-
resource.
|
88
|
-
resource.
|
89
|
-
route.
|
87
|
+
expect(resource).to receive(:check_callbacks)
|
88
|
+
expect(resource).to receive(:call).and_return("This is a text message")
|
89
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
90
90
|
obj.run
|
91
|
-
obj.status.
|
92
|
-
obj.headers['Content-Type'].
|
91
|
+
expect(obj.status).to eql(200)
|
92
|
+
expect(obj.headers['Content-Type']).to match(/text\/plain/)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -99,50 +99,50 @@ describe Restfulness::Response do
|
|
99
99
|
end
|
100
100
|
|
101
101
|
it "should update the status and payload" do
|
102
|
-
request.
|
102
|
+
allow(request).to receive(:route).and_return(route)
|
103
103
|
request.action = :get
|
104
|
-
request.
|
104
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
105
105
|
resource = double(:Resource)
|
106
106
|
txt = "This is a text error"
|
107
|
-
resource.
|
107
|
+
allow(resource).to receive(:check_callbacks) do
|
108
108
|
raise Restfulness::HTTPException.new(418, txt)
|
109
109
|
end
|
110
|
-
route.
|
110
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
111
111
|
obj.run
|
112
|
-
obj.status.
|
113
|
-
obj.headers['Content-Type'].
|
114
|
-
obj.payload.
|
112
|
+
expect(obj.status).to eql(418)
|
113
|
+
expect(obj.headers['Content-Type']).to match(/text\/plain/)
|
114
|
+
expect(obj.payload).to eql(txt)
|
115
115
|
end
|
116
116
|
|
117
117
|
it "should update the status and provide JSON payload" do
|
118
|
-
request.
|
118
|
+
allow(request).to receive(:route).and_return(route)
|
119
119
|
request.action = :get
|
120
|
-
request.
|
120
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
121
121
|
resource = double(:Resource)
|
122
122
|
err = {:error => "This is a text error"}
|
123
|
-
resource.
|
123
|
+
allow(resource).to receive(:check_callbacks) do
|
124
124
|
raise Restfulness::HTTPException.new(418, err)
|
125
125
|
end
|
126
|
-
route.
|
126
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
127
127
|
obj.run
|
128
|
-
obj.status.
|
129
|
-
obj.headers['Content-Type'].
|
130
|
-
obj.payload.
|
128
|
+
expect(obj.status).to eql(418)
|
129
|
+
expect(obj.headers['Content-Type']).to match(/application\/json/)
|
130
|
+
expect(obj.payload).to eql(err.to_json)
|
131
131
|
end
|
132
132
|
|
133
133
|
context "for non http errors" do
|
134
134
|
|
135
135
|
it "should catch error and provide result" do
|
136
|
-
request.
|
136
|
+
allow(request).to receive(:route).and_return(route)
|
137
137
|
request.action = :get
|
138
|
-
request.
|
138
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
139
139
|
resource = double(:Resource)
|
140
|
-
resource.
|
140
|
+
allow(resource).to receive(:check_callbacks) do
|
141
141
|
raise SyntaxError, 'Bad writing'
|
142
142
|
end
|
143
|
-
route.
|
143
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
144
144
|
obj.run
|
145
|
-
obj.status.
|
145
|
+
expect(obj.status).to eql(500)
|
146
146
|
end
|
147
147
|
|
148
148
|
end
|
data/spec/unit/route_spec.rb
CHANGED
@@ -18,23 +18,23 @@ describe Restfulness::Route do
|
|
18
18
|
|
19
19
|
it "should assign basic path and resource" do
|
20
20
|
obj = klass.new('project', resource)
|
21
|
-
obj.path.
|
22
|
-
obj.resource_name.
|
21
|
+
expect(obj.path).to eql(['project'])
|
22
|
+
expect(obj.resource_name).to eql(resource.to_s)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should assign path with symbols" do
|
26
26
|
obj = klass.new('project', :project_id, 'states', resource)
|
27
|
-
obj.path.
|
27
|
+
expect(obj.path).to eql(['project', :project_id, 'states'])
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should remove :id from end" do
|
31
31
|
obj = klass.new('project', :project_id, 'states', :id, resource)
|
32
|
-
obj.path.
|
32
|
+
expect(obj.path).to eql(['project', :project_id, 'states'])
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should handle numbers in path" do
|
36
36
|
obj = klass.new('project', 120, resource)
|
37
|
-
obj.path.
|
37
|
+
expect(obj.path).to eql(['project', 120])
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should accept classes as strings" do
|
@@ -60,7 +60,7 @@ describe Restfulness::Route do
|
|
60
60
|
describe "#resource" do
|
61
61
|
it "should provide constant to class" do
|
62
62
|
obj = klass.new('project', resource)
|
63
|
-
obj.resource.
|
63
|
+
expect(obj.resource).to eql(resource)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -68,8 +68,8 @@ describe Restfulness::Route do
|
|
68
68
|
it "should build a new path object including self" do
|
69
69
|
obj = klass.new('project', resource)
|
70
70
|
path = obj.build_path("/project/12345")
|
71
|
-
path.
|
72
|
-
path.route.
|
71
|
+
expect(path).to be_a(Restfulness::Path)
|
72
|
+
expect(path.route).to eql(obj)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -80,16 +80,16 @@ describe Restfulness::Route do
|
|
80
80
|
klass.new('project', resource)
|
81
81
|
end
|
82
82
|
it "should return true for match" do
|
83
|
-
obj.handles?(['project']).
|
83
|
+
expect(obj.handles?(['project'])).to be true
|
84
84
|
end
|
85
85
|
it "should return true for match with id" do
|
86
|
-
obj.handles?(['project', '12345']).
|
86
|
+
expect(obj.handles?(['project', '12345'])).to be true
|
87
87
|
end
|
88
88
|
it "should return false for different name" do
|
89
|
-
obj.handles?(['projects']).
|
89
|
+
expect(obj.handles?(['projects'])).to be false
|
90
90
|
end
|
91
91
|
it "should return false for matching start" do
|
92
|
-
obj.handles?(['project', '12345', 'status']).
|
92
|
+
expect(obj.handles?(['project', '12345', 'status'])).to be false
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -98,13 +98,13 @@ describe Restfulness::Route do
|
|
98
98
|
klass.new(resource)
|
99
99
|
end
|
100
100
|
it "should matching empty path" do
|
101
|
-
obj.handles?([]).
|
101
|
+
expect(obj.handles?([])).to be true
|
102
102
|
end
|
103
103
|
it "should matching empty path with id" do
|
104
|
-
obj.handles?(['12345']).
|
104
|
+
expect(obj.handles?(['12345'])).to be true
|
105
105
|
end
|
106
106
|
it "shold not match extended URL" do
|
107
|
-
obj.handles?(['foobar', '12345']).
|
107
|
+
expect(obj.handles?(['foobar', '12345'])).to be false
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -113,13 +113,13 @@ describe Restfulness::Route do
|
|
113
113
|
klass.new(:project_id, resource)
|
114
114
|
end
|
115
115
|
it "should matching anything" do
|
116
|
-
obj.handles?(['foobar']).
|
116
|
+
expect(obj.handles?(['foobar'])).to be true
|
117
117
|
end
|
118
118
|
it "should matching anything, with id" do
|
119
|
-
obj.handles?(['foobar', '12345']).
|
119
|
+
expect(obj.handles?(['foobar', '12345'])).to be true
|
120
120
|
end
|
121
121
|
it "shold not match extended URL" do
|
122
|
-
obj.handles?(['foobar', 'status', '12345']).
|
122
|
+
expect(obj.handles?(['foobar', 'status', '12345'])).to be false
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
@@ -128,19 +128,19 @@ describe Restfulness::Route do
|
|
128
128
|
klass.new('project', :project_id, 'status', resource)
|
129
129
|
end
|
130
130
|
it "should return true for match" do
|
131
|
-
obj.handles?(['project', '1234', 'status']).
|
131
|
+
expect(obj.handles?(['project', '1234', 'status'])).to be true
|
132
132
|
end
|
133
133
|
it "should return true for match with id" do
|
134
|
-
obj.handles?(['project', '1234', 'status', '12345']).
|
134
|
+
expect(obj.handles?(['project', '1234', 'status', '12345'])).to be true
|
135
135
|
end
|
136
136
|
it "should not match short path" do
|
137
|
-
obj.handles?(['project']).
|
137
|
+
expect(obj.handles?(['project'])).to be false
|
138
138
|
end
|
139
139
|
it "should not match path with different name" do
|
140
|
-
obj.handles?(['project', '12345', 'statuses']).
|
140
|
+
expect(obj.handles?(['project', '12345', 'statuses'])).to be false
|
141
141
|
end
|
142
142
|
it "should not match extended path" do
|
143
|
-
obj.handles?(['project', '12345', 'status', '1234', 'test']).
|
143
|
+
expect(obj.handles?(['project', '12345', 'status', '1234', 'test'])).to be false
|
144
144
|
end
|
145
145
|
|
146
146
|
end
|
@@ -151,7 +151,7 @@ describe Restfulness::Route do
|
|
151
151
|
|
152
152
|
it "should request a new resource" do
|
153
153
|
obj = klass.new('project', resource)
|
154
|
-
resource.
|
154
|
+
expect(resource).to receive(:new).with({}, {}).and_return(nil)
|
155
155
|
obj.build_resource({}, {})
|
156
156
|
end
|
157
157
|
|
data/spec/unit/router_spec.rb
CHANGED
@@ -21,14 +21,14 @@ describe Restfulness::Router do
|
|
21
21
|
|
22
22
|
it "should prepare routes" do
|
23
23
|
obj = klass.new
|
24
|
-
obj.routes.
|
24
|
+
expect(obj.routes).to eql([])
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should prepare routes with instance eval block" do
|
28
28
|
obj = klass.new do
|
29
29
|
@foo = 'bar'
|
30
30
|
end
|
31
|
-
obj.instance_variable_get(:@foo).
|
31
|
+
expect(obj.instance_variable_get(:@foo)).to eql('bar')
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
@@ -37,10 +37,10 @@ describe Restfulness::Router do
|
|
37
37
|
it "should add route to object" do
|
38
38
|
obj = klass.new
|
39
39
|
obj.add 'projects', resource
|
40
|
-
obj.routes.length.
|
40
|
+
expect(obj.routes.length).to eql(1)
|
41
41
|
route = obj.routes.first
|
42
|
-
route.
|
43
|
-
route.path.
|
42
|
+
expect(route).to be_a(Restfulness::Route)
|
43
|
+
expect(route.path).to eql(['projects'])
|
44
44
|
end
|
45
45
|
it "should accept block as scope" do
|
46
46
|
obj = klass.new
|
@@ -48,11 +48,11 @@ describe Restfulness::Router do
|
|
48
48
|
add 'examples', SecondRouterResource
|
49
49
|
end
|
50
50
|
route = obj.routes.first
|
51
|
-
route.resource.
|
52
|
-
route.path.
|
51
|
+
expect(route.resource).to eql(SecondRouterResource)
|
52
|
+
expect(route.path).to eql(['project', 'examples'])
|
53
53
|
route = obj.routes.last
|
54
|
-
route.resource.
|
55
|
-
route.path.
|
54
|
+
expect(route.resource).to eql(RouterResource)
|
55
|
+
expect(route.path).to eql(['project'])
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -63,8 +63,8 @@ describe Restfulness::Router do
|
|
63
63
|
obj.scope 'api' do
|
64
64
|
subscope = current_scope
|
65
65
|
end
|
66
|
-
subscope.
|
67
|
-
obj.current_scope.
|
66
|
+
expect(subscope).to eql(['api'])
|
67
|
+
expect(obj.current_scope).to eql([])
|
68
68
|
end
|
69
69
|
|
70
70
|
it "should add scope properties to add call" do
|
@@ -74,7 +74,7 @@ describe Restfulness::Router do
|
|
74
74
|
add 'projects', res
|
75
75
|
end
|
76
76
|
route = obj.routes.first
|
77
|
-
route.path.
|
77
|
+
expect(route.path).to eql(['api', 'projects'])
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should allow for scopes within scopes" do
|
@@ -89,11 +89,11 @@ describe Restfulness::Router do
|
|
89
89
|
end
|
90
90
|
subscope = current_scope
|
91
91
|
end
|
92
|
-
subsubscope.
|
93
|
-
subscope.
|
94
|
-
obj.current_scope.
|
92
|
+
expect(subsubscope).to eql(['api', 'projects'])
|
93
|
+
expect(subscope).to eql(['api'])
|
94
|
+
expect(obj.current_scope).to eql([])
|
95
95
|
route = obj.routes.first
|
96
|
-
route.path.
|
96
|
+
expect(route.path).to eql(['api', 'projects', 'active'])
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
@@ -110,47 +110,47 @@ describe Restfulness::Router do
|
|
110
110
|
|
111
111
|
it "should determine the route for a simple path" do
|
112
112
|
route = obj.route_for("/projects")
|
113
|
-
route.
|
114
|
-
route.path.
|
113
|
+
expect(route).not_to be_nil
|
114
|
+
expect(route.path).to eql(['projects'])
|
115
115
|
end
|
116
116
|
|
117
117
|
it "should determine the route for a simple path with id" do
|
118
118
|
route = obj.route_for("/projects")
|
119
|
-
route.
|
120
|
-
route.path.
|
119
|
+
expect(route).not_to be_nil
|
120
|
+
expect(route.path).to eql(['projects'])
|
121
121
|
end
|
122
122
|
|
123
123
|
it "should determine the route for a simple path with id and end /" do
|
124
124
|
route = obj.route_for("/projects/12345/")
|
125
|
-
route.
|
126
|
-
route.path.
|
125
|
+
expect(route).not_to be_nil
|
126
|
+
expect(route.path).to eql(['projects'])
|
127
127
|
end
|
128
128
|
|
129
129
|
it "should determine the route for a simple path with end /" do
|
130
130
|
route = obj.route_for("/projects/")
|
131
|
-
route.
|
132
|
-
route.path.
|
131
|
+
expect(route).not_to be_nil
|
132
|
+
expect(route.path).to eql(['projects'])
|
133
133
|
end
|
134
134
|
|
135
135
|
it "should determine route for more complex path" do
|
136
136
|
route = obj.route_for("/project/1235/status/1234")
|
137
|
-
route.
|
138
|
-
route.path.
|
137
|
+
expect(route).not_to be_nil
|
138
|
+
expect(route.path).to eql(['project', :project_id, 'status'])
|
139
139
|
end
|
140
140
|
|
141
141
|
it "should return nil if not matched" do
|
142
142
|
route = obj.route_for("/projects/1235/statuses/")
|
143
|
-
route.
|
143
|
+
expect(route).to be_nil
|
144
144
|
end
|
145
145
|
|
146
146
|
it "should match empty path" do
|
147
147
|
route = obj.route_for("/")
|
148
|
-
route.path.
|
148
|
+
expect(route.path).to eql([])
|
149
149
|
end
|
150
150
|
|
151
151
|
it "should match path with single parameter" do
|
152
152
|
route = obj.route_for("/something")
|
153
|
-
route.path.
|
153
|
+
expect(route.path).to eql([:page])
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|