api_client 0.5.24-java → 0.6.0-java

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/lib/api_client/base.rb +77 -0
  4. data/lib/api_client/connection/abstract.rb +81 -0
  5. data/lib/api_client/connection/basic.rb +131 -0
  6. data/lib/api_client/connection/json.rb +14 -0
  7. data/lib/api_client/connection/middlewares/request/json.rb +34 -0
  8. data/lib/api_client/connection/middlewares/request/logger.rb +64 -0
  9. data/lib/api_client/connection/middlewares/request/oauth.rb +22 -0
  10. data/lib/api_client/connection/oauth.rb +18 -0
  11. data/lib/api_client/errors.rb +32 -0
  12. data/lib/api_client/mixins/configuration.rb +24 -0
  13. data/lib/api_client/mixins/connection_hooks.rb +24 -0
  14. data/lib/api_client/mixins/delegation.rb +23 -0
  15. data/lib/api_client/mixins/inheritance.rb +19 -0
  16. data/lib/api_client/mixins/instantiation.rb +29 -0
  17. data/lib/api_client/mixins/scoping.rb +49 -0
  18. data/lib/api_client/resource/base.rb +67 -0
  19. data/lib/api_client/resource/name_resolver.rb +37 -0
  20. data/lib/api_client/resource/scope.rb +73 -0
  21. data/lib/api_client/scope.rb +125 -0
  22. data/lib/api_client/utils.rb +18 -0
  23. data/lib/api_client/version.rb +3 -0
  24. data/spec/api_client/base/connection_hook_spec.rb +18 -0
  25. data/spec/api_client/base/delegation_spec.rb +15 -0
  26. data/spec/api_client/base/inheritance_spec.rb +44 -0
  27. data/spec/api_client/base/instantiation_spec.rb +55 -0
  28. data/spec/api_client/base/marshalling_spec.rb +33 -0
  29. data/spec/api_client/base/parsing_spec.rb +38 -0
  30. data/spec/api_client/base/scoping_spec.rb +60 -0
  31. data/spec/api_client/base_spec.rb +107 -0
  32. data/spec/api_client/connection/abstract_spec.rb +21 -0
  33. data/spec/api_client/connection/basic_spec.rb +198 -0
  34. data/spec/api_client/connection/oauth_spec.rb +23 -0
  35. data/spec/api_client/connection/request/json_spec.rb +30 -0
  36. data/spec/api_client/connection/request/logger_spec.rb +18 -0
  37. data/spec/api_client/connection/request/oauth_spec.rb +26 -0
  38. data/spec/api_client/resource/base_spec.rb +97 -0
  39. data/spec/api_client/resource/name_spec.rb +19 -0
  40. data/spec/api_client/resource/scope_spec.rb +122 -0
  41. data/spec/api_client/scope_spec.rb +204 -0
  42. data/spec/api_client/utils_spec.rb +32 -0
  43. data/spec/support/matchers.rb +5 -0
  44. metadata +72 -11
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Connection::Abstract do
4
+
5
+ class ConnectionSubclass < ApiClient::Connection::Abstract
6
+ end
7
+
8
+ it "does not raise an error when instantiating a subclass" do
9
+ lambda {
10
+ ConnectionSubclass.new("http://google.com")
11
+ }.should_not raise_error()
12
+ end
13
+
14
+ it "raises an error when instantiating directly and not as a subclass" do
15
+ lambda {
16
+ ApiClient::Connection::Abstract.new("http://google.com")
17
+ }.should raise_error("Cannot instantiate abstract class")
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,198 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Connection::Basic do
4
+
5
+ it "has a nice inspect" do
6
+ instance = ApiClient::Connection::Basic.new("http://google.com")
7
+ instance.inspect.should == '#<ApiClient::Connection::Basic endpoint: "http://google.com">'
8
+ end
9
+
10
+ it "uses correct adapter" do
11
+ instance = ApiClient::Connection::Basic.new("http://google.com")
12
+ expect(instance.handler.builder.adapter.name).to eq("Faraday::Adapter::NetHttp")
13
+ end
14
+
15
+ it "adds basic middlewares to faraday" do
16
+ instance = ApiClient::Connection::Basic.new("http://google.com")
17
+ expect(instance.handler.builder.handlers.collect(&:name)).to include("Faraday::Request::UrlEncoded")
18
+ end
19
+
20
+ it "adds the logger middlewares to faraday if ApiClient.logger is available" do
21
+ logger = double
22
+ ApiClient.stub(:logger).and_return(logger)
23
+ instance = ApiClient::Connection::Basic.new("http://google.com")
24
+ expect(instance.handler.builder.handlers.collect(&:name)).to include("ApiClient::Connection::Middlewares::Request::Logger", "Faraday::Request::UrlEncoded")
25
+ end
26
+
27
+ it "creates a Faraday object on initialize" do
28
+ instance = ApiClient::Connection::Basic.new("http://google.com")
29
+ instance.handler.should be_an_instance_of(Faraday::Connection)
30
+ end
31
+
32
+ describe "requests" do
33
+
34
+ before do
35
+ @instance = ApiClient::Connection::Basic.new("http://google.com")
36
+ @headers = { "header" => "token" }
37
+ @params = { "param" => "1", "nested" => { "param" => "1" } }
38
+ @response = Faraday::Response.new(:status => 200)
39
+ @faraday_request_params = double
40
+ @faraday_request = double(:params => @faraday_request_params)
41
+ end
42
+
43
+ it "can perform GET requests" do
44
+ @instance.handler.
45
+ should_receive(:run_request).
46
+ with(:get, '/home', nil, @headers).
47
+ and_yield(@faraday_request).
48
+ and_return(@response)
49
+ @faraday_request_params.should_receive(:update).with(@params)
50
+ @instance.get "/home", @params, @headers
51
+ end
52
+
53
+ it "can perform POST requests" do
54
+ @instance.handler.
55
+ should_receive(:run_request).
56
+ with(:post, '/home', @params, @headers).
57
+ and_return(@response)
58
+ @instance.post "/home", @params, @headers
59
+ end
60
+
61
+ it "can perform PATCH requests" do
62
+ @instance.handler.
63
+ should_receive(:run_request).
64
+ with(:patch, '/home', @params, @headers).
65
+ and_return(@response)
66
+ @instance.patch "/home", @params, @headers
67
+ end
68
+
69
+ it "can perform PUT requests" do
70
+ @instance.handler.
71
+ should_receive(:run_request).
72
+ with(:put, '/home', @params, @headers).
73
+ and_return(@response)
74
+ @instance.put "/home", @params, @headers
75
+ end
76
+
77
+ it "can perform DELETE requests" do
78
+ @instance.handler.
79
+ should_receive(:run_request).
80
+ with(:delete, '/home', nil, @headers).
81
+ and_yield(@faraday_request).
82
+ and_return(@response)
83
+ @faraday_request_params.should_receive(:update).with(@params)
84
+ @instance.delete "/home", @params, @headers
85
+ end
86
+
87
+ end
88
+
89
+ describe "#handle_response" do
90
+ let(:request) { double }
91
+
92
+ before do
93
+ @instance = ApiClient::Connection::Basic.new("http://google.com")
94
+ @response = Faraday::Response.new(:status => 200)
95
+ end
96
+
97
+ it "raises an ApiClient::Errors::ConnectionFailed if there is no response" do
98
+ lambda {
99
+ @instance.send :handle_response, request, nil
100
+ }.should raise_error(ApiClient::Errors::ConnectionFailed, "ApiClient::Errors::ConnectionFailed")
101
+ end
102
+
103
+ it "raises an ApiClient::Errors::Unauthorized if status is 401" do
104
+ @response.env[:status] = 401
105
+ lambda {
106
+ @instance.send :handle_response, request, @response
107
+ }.should raise_error(ApiClient::Errors::Unauthorized, "Status code: 401")
108
+ end
109
+
110
+ it "raises an ApiClient::Errors::Forbidden if status is 403" do
111
+ @response.env[:status] = 403
112
+ lambda {
113
+ @instance.send :handle_response, request, @response
114
+ }.should raise_error(ApiClient::Errors::Forbidden, "Status code: 403")
115
+ end
116
+
117
+ it "raises an ApiClient::Errors::NotFound if status is 404" do
118
+ @response.env[:status] = 404
119
+ lambda {
120
+ @instance.send :handle_response, request, @response
121
+ }.should raise_error(ApiClient::Errors::NotFound, "Status code: 404")
122
+ end
123
+
124
+ it "raises an ApiClient::Errors::BadRequest if status is 400" do
125
+ @response.env[:status] = 400
126
+ lambda {
127
+ @instance.send :handle_response, request, @response
128
+ }.should raise_error(ApiClient::Errors::BadRequest, "Status code: 400")
129
+ end
130
+
131
+ it "raises an ApiClient::Errors::Unsupported if status is 406" do
132
+ @response.env[:status] = 406
133
+ lambda {
134
+ @instance.send :handle_response, request, @response
135
+ }.should raise_error(ApiClient::Errors::Unsupported, "Status code: 406")
136
+ end
137
+
138
+ it "raises an ApiClient::Errors::Conflict if status is 409" do
139
+ @response.env[:status] = 409
140
+ lambda {
141
+ @instance.send :handle_response, request, @response
142
+ }.should raise_error(ApiClient::Errors::Conflict, "Status code: 409")
143
+ end
144
+
145
+ it "raises an ApiClient::Errors::Gone if status is 410" do
146
+ @response.env[:status] = 410
147
+ lambda {
148
+ @instance.send :handle_response, request, @response
149
+ }.should raise_error(ApiClient::Errors::Gone, "Status code: 410")
150
+ end
151
+
152
+ it "raises an ApiClient::Errors::PreconditionFailed if status is 412" do
153
+ @response.env[:status] = 412
154
+ lambda {
155
+ @instance.send :handle_response, request, @response
156
+ }.should raise_error(ApiClient::Errors::PreconditionFailed, "Status code: 412")
157
+ end
158
+
159
+ it "raises an ApiClient::Errors::Unsupported if status is 422" do
160
+ @response.env[:status] = 422
161
+ lambda {
162
+ @instance.send :handle_response, request, @response
163
+ }.should raise_error(ApiClient::Errors::UnprocessableEntity, @response.body)
164
+ end
165
+
166
+ it "raises an ApiClient::Errors::Locked if status is 423" do
167
+ @response.env[:status] = 423
168
+ lambda {
169
+ @instance.send :handle_response, request, @response
170
+ }.should raise_error(ApiClient::Errors::Locked, @response.body)
171
+ end
172
+
173
+ it "raises an ApiClient::Errors::TooManyRequests if status is 429" do
174
+ @response.env[:status] = 429
175
+ lambda {
176
+ @instance.send :handle_response, request, @response
177
+ }.should raise_error(ApiClient::Errors::TooManyRequests, @response.body)
178
+ end
179
+
180
+ it "raises an ApiClient::Errors::Unsupported if status is 300..399" do
181
+ location = "https://google.com"
182
+ @response.env[:status] = 302
183
+ @response.env[:response_headers] = { 'Location' => location }
184
+ lambda {
185
+ @instance.send :handle_response, request, @response
186
+ }.should raise_error(ApiClient::Errors::Redirect, location)
187
+ end
188
+
189
+ it "raises an ApiClient::Errors::ServerError if status is 500..599" do
190
+ @response.env[:status] = 502
191
+ lambda {
192
+ @instance.send :handle_response, request, @response
193
+ }.should raise_error(ApiClient::Errors::ServerError, "Status code: 502")
194
+ end
195
+
196
+ end
197
+
198
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Connection::Oauth do
4
+
5
+ it "uses correct adapter" do
6
+ instance = ApiClient::Connection::Oauth.new("http://google.com")
7
+ expect(instance.handler.builder.adapter.name).to eq("Faraday::Adapter::NetHttp")
8
+ end
9
+
10
+ it "adds basic middlewares to faraday" do
11
+ instance = ApiClient::Connection::Oauth.new("http://google.com")
12
+ expect(instance.handler.builder.handlers.collect(&:name))
13
+ .to include("ApiClient::Connection::Middlewares::Request::OAuth", "Faraday::Request::UrlEncoded")
14
+ end
15
+
16
+ it "adds the logger middlewares to faraday if ApiClient.logger is available" do
17
+ logger = double
18
+ ApiClient.stub(:logger).and_return(logger)
19
+ instance = ApiClient::Connection::Oauth.new("http://google.com")
20
+ expect(instance.handler.builder.handlers.collect(&:name))
21
+ .to include("ApiClient::Connection::Middlewares::Request::Logger", "ApiClient::Connection::Middlewares::Request::OAuth", "Faraday::Request::UrlEncoded")
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Connection::Middlewares::Request::Json do
4
+ let(:app) { double }
5
+ let(:body) { {:some => :data} }
6
+ let(:env) do
7
+ {
8
+ :url => "http://api.twitter.com",
9
+ :request_headers => {},
10
+ :method => "post",
11
+ :body => body
12
+ }
13
+ end
14
+
15
+ subject { ApiClient::Connection::Middlewares::Request::Json.new(app) }
16
+
17
+ it "sets content type to json" do
18
+ app.should_receive(:call).
19
+ with(hash_including(:request_headers => {"Content-Type" => "application/json"}))
20
+
21
+ subject.call(env)
22
+ end
23
+
24
+ it "JSON encodes body" do
25
+ app.should_receive(:call).
26
+ with(hash_including(:body => MultiJson.dump(body)))
27
+
28
+ subject.call(env)
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Connection::Middlewares::Request::Logger do
4
+ it "adds a oauth header to the request" do
5
+ app = double
6
+ io = StringIO.new
7
+ logger = Logger.new(io)
8
+ instance = ApiClient::Connection::Middlewares::Request::Logger.new(app, logger)
9
+ env = {
10
+ :url => "http://api.twitter.com",
11
+ :request_headers => {},
12
+ :method => 'get'
13
+ }
14
+ app.should_receive(:call).with(env)
15
+ instance.call(env)
16
+ io.string.should match("GET http://api.twitter.com")
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Connection::Middlewares::Request::OAuth do
4
+
5
+ it "adds a oauth header to the request" do
6
+ app = double
7
+ options = {
8
+ :token => 'TOKEN',
9
+ :token_secret => 'SECRET',
10
+ :consumer_key => 'CONSUMER_KEY',
11
+ :consumer_secret => 'CONSUMER_SECRET'
12
+ }
13
+ instance = ApiClient::Connection::Middlewares::Request::OAuth.new(app, options)
14
+ env = {
15
+ :url => "http://api.twitter.com",
16
+ :request_headers => {}
17
+ }
18
+ app.should_receive(:call).with(env)
19
+
20
+ instance.call(env)
21
+ env[:request_headers]['Authorization'].should match("OAuth")
22
+ env[:request_headers]['User-Agent'].should match("ApiClient gem")
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,97 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Resource::Base do
4
+
5
+ describe '.scope' do
6
+
7
+ it "is an instance of ApiClient::Resource::Scope" do
8
+ ApiClient::Resource::Base.scope.should be_an_instance_of(ApiClient::Resource::Scope)
9
+ end
10
+
11
+ end
12
+
13
+
14
+ describe "persistence" do
15
+
16
+ before do
17
+ @instance = ApiClient::Resource::Base.new
18
+ @instance.id = 42
19
+ @instance.name = "Mike"
20
+ end
21
+
22
+ describe '#persisted?' do
23
+
24
+ it "returns true if id is present, false otherwise" do
25
+ @instance.id = 42
26
+ @instance.persisted?.should == true
27
+ @instance.id = nil
28
+ @instance.persisted?.should == false
29
+ end
30
+
31
+ end
32
+
33
+ describe '#save' do
34
+
35
+ it "creates a record if not persisted" do
36
+ @instance.id = nil
37
+ @instance.should_receive(:remote_create)
38
+ @instance.save
39
+ end
40
+
41
+ it "updates a record if not persisted" do
42
+ @instance.id = 42
43
+ @instance.should_receive(:remote_update)
44
+ @instance.save
45
+ end
46
+
47
+ end
48
+
49
+ describe "#destroy" do
50
+
51
+ it "delegates the destroy to the class" do
52
+ ApiClient::Resource::Base.should_receive(:destroy).with(42)
53
+ @instance.destroy
54
+ end
55
+
56
+ it "retains the original scope" do
57
+ @instance.original_scope = double
58
+ @instance.original_scope.should_receive(:destroy).with(42)
59
+ @instance.destroy
60
+ end
61
+
62
+ end
63
+
64
+ describe "#remote_update" do
65
+
66
+ it "delegates the update to the class" do
67
+ ApiClient::Resource::Base.should_receive(:update).with(42, "name" => "Mike")
68
+ @instance.remote_update
69
+ end
70
+
71
+ it "retains the original scope" do
72
+ ApiClient::Resource::Base.stub(:update)
73
+ @instance.original_scope = double
74
+ @instance.original_scope.should_receive(:update).with(42, "name" => "Mike")
75
+ @instance.remote_update
76
+ end
77
+
78
+ end
79
+
80
+ describe "#remote_create" do
81
+
82
+ it "delegates the create to the class" do
83
+ ApiClient::Resource::Base.should_receive(:create).with("name" => "Mike")
84
+ @instance.remote_create
85
+ end
86
+
87
+ it "retains the original scope" do
88
+ @instance.original_scope = double
89
+ @instance.original_scope.should_receive(:create).with("name" => "Mike")
90
+ @instance.remote_create
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApiClient::Resource::NameResolver do
4
+ describe '.resolve' do
5
+ subject { described_class }
6
+
7
+ it 'changes My::Namespace::MyResouce to my_resource' do
8
+ subject.resolve('My::Namespace::MyResource').should == 'my_resource'
9
+ end
10
+
11
+ it 'changes Resource to resource' do
12
+ subject.resolve('Resource').should == 'resource'
13
+ end
14
+
15
+ it 'changes My::Resource to resoure' do
16
+ subject.resolve('My::Resource').should == 'resource'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,122 @@
1
+ require "spec_helper"
2
+
3
+ describe ApiClient::Resource::Scope do
4
+
5
+ describe "restful requests" do
6
+
7
+ class Restful < ApiClient::Resource::Base
8
+ end
9
+
10
+ class Restful2 < ApiClient::Resource::Base
11
+ namespace false
12
+ end
13
+
14
+ class Restful3 < ApiClient::Resource::Base
15
+ prefix "v1"
16
+ end
17
+
18
+ before do
19
+ @instance = ApiClient::Resource::Scope.new(Restful)
20
+ end
21
+
22
+ it "performs a find to fetch one record" do
23
+ response = { "restful" => { "id" => 42 }}
24
+ @instance.should_receive(:get).with('/restfuls/1.json').and_return(response)
25
+ result = @instance.find(1)
26
+ result.should be_an_instance_of(Restful)
27
+ result.id.should == 42
28
+ end
29
+
30
+ it "performs a find to fetch one record in raw mode" do
31
+ response = { "restful" => { "id" => 42 }}
32
+ @instance.should_receive(:get).with('/restfuls/1.json').and_return(response)
33
+ result = @instance.raw.find(1)
34
+ result.should == response
35
+ end
36
+
37
+ it "performs a find to fetch one record with a prefix if provided" do
38
+ @instance = ApiClient::Resource::Scope.new(Restful3)
39
+ response = { "restful3" => { "id" => 42 }}
40
+ @instance.should_receive(:get).with('/v1/restful3s/1.json').and_return(response)
41
+ result = @instance.find(1)
42
+ result.should be_an_instance_of(Restful3)
43
+ result.id.should == 42
44
+ end
45
+
46
+ it "performs a find_all to fetch many records" do
47
+ response = [{ "restful" => { "id" => 42 } }, { "restful" => { "id" => 112 } }]
48
+ @instance.should_receive(:get).with('/restfuls.json', {}).and_return(response)
49
+ result = @instance.find_all
50
+
51
+ result.should be_an_instance_of(Array)
52
+ result.first.should be_an_instance_of(Restful)
53
+ result.first.id.should == 42
54
+ result.last.should be_an_instance_of(Restful)
55
+ result.last.id.should == 112
56
+ end
57
+
58
+ it "performs a find_all to fetch many records in raw mode" do
59
+ response = [{ "restful" => { "id" => 42 } }, { "restful" => { "id" => 112 } }]
60
+ @instance.should_receive(:get).with('/restfuls.json', {}).and_return(response)
61
+ result = @instance.raw.find_all
62
+ result.should == response
63
+ end
64
+
65
+ it "performs a create to create a new record" do
66
+ response = { "restful" => { "id" => 42, "name" => "Foo" }}
67
+ @instance.should_receive(:post).with('/restfuls.json', {"restful" => {:name => "Foo"} }).and_return(response)
68
+ result = @instance.create(:name => "Foo")
69
+ result.should be_an_instance_of(Restful)
70
+ result.id.should == 42
71
+ end
72
+
73
+ it "performs a create to create a new record in raw mode" do
74
+ response = { "restful" => { "id" => 42, "name" => "Foo" }}
75
+ @instance.should_receive(:post).with('/restfuls.json', {"restful" => {:name => "Foo"} }).and_return(response)
76
+ result = @instance.raw.create(:name => "Foo")
77
+ result.should == response
78
+ end
79
+
80
+ it "performs a create to create a new record skipping the namespace if it is not present" do
81
+ @instance = ApiClient::Resource::Scope.new(Restful2)
82
+ response = { "id" => 42, "name" => "Foo" }
83
+ @instance.should_receive(:post).with('/restful2s.json', {:name => "Foo"} ).and_return(response)
84
+ result = @instance.create(:name => "Foo")
85
+ result.should be_an_instance_of(Restful2)
86
+ result.id.should == 42
87
+ end
88
+
89
+ it "performs a update to update an existing record" do
90
+ response = { "restful" => { "id" => 42, "name" => "Foo" }}
91
+ @instance.should_receive(:put).with('/restfuls/42.json', {"restful" => {:name => "Foo"} }).and_return(response)
92
+ result = @instance.update(42, :name => "Foo")
93
+ result.should be_an_instance_of(Restful)
94
+ result.id.should == 42
95
+ end
96
+
97
+ it "performs a update to update an existing record in raw mode" do
98
+ response = { "restful" => { "id" => 42, "name" => "Foo" }}
99
+ @instance.should_receive(:put).with('/restfuls/42.json', {"restful" => {:name => "Foo"} }).and_return(response)
100
+ result = @instance.raw.update(42, :name => "Foo")
101
+ result.should == response
102
+ end
103
+
104
+ it "performs a update to update an existing record skipping the namespace if it is not present" do
105
+ @instance = ApiClient::Resource::Scope.new(Restful2)
106
+ response = { "id" => 42, "name" => "Foo" }
107
+ @instance.should_receive(:put).with('/restful2s/42.json', {:name => "Foo"} ).and_return(response)
108
+ result = @instance.update(42, :name => "Foo")
109
+ result.should be_an_instance_of(Restful2)
110
+ result.id.should == 42
111
+ end
112
+
113
+ it "performs a destroy to remove a record" do
114
+ response = { "restful" => { "id" => 42, "name" => "Foo" }}
115
+ @instance.should_receive(:delete).with('/restfuls/42.json').and_return(response)
116
+ result = @instance.destroy(42)
117
+ result.should == true
118
+ end
119
+
120
+ end
121
+
122
+ end