tddium_client 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/tddium_client.rb CHANGED
@@ -10,73 +10,82 @@ module TddiumClient
10
10
  API_KEY_HEADER = "X-tddium-api-key"
11
11
  API_ERROR_TEXT = "An error occured: "
12
12
 
13
- class Error < RuntimeError; end
14
- class TimeoutError < TddiumClient::Error; end
13
+ module Error
14
+ class Base < RuntimeError; end
15
+ end
15
16
 
16
- class APIError < TddiumClient::Error
17
- attr_accessor :tddium_result
17
+ module Result
18
+ class Base < Error::Base
19
+ attr_accessor :http_response
18
20
 
19
- def initialize(result)
20
- self.tddium_result = result
21
- end
21
+ def initialize(http_response)
22
+ self.http_response = http_response
23
+ end
22
24
 
23
- def http_code
24
- self.tddium_result.http_code if self.tddium_result
25
- end
25
+ def http_code
26
+ http_response.code
27
+ end
26
28
 
27
- def http_result
28
- self.tddium_result.http_result if self.tddium_result
29
+ def http_message
30
+ http_response.response.header.msg.to_s
31
+ end
29
32
  end
30
33
 
31
- def to_s
32
- "#{http_code} #{http_result} (#{self.tddium_result.status}) #{self.tddium_result.explanation}"
34
+ class Abstract < Base
35
+ attr_accessor :tddium_response
36
+
37
+ def initialize(http_response)
38
+ super
39
+ self.tddium_response = JSON.parse(http_response.body) rescue {}
40
+ end
41
+
42
+ def [](value)
43
+ tddium_response[value]
44
+ end
33
45
  end
34
46
 
35
- def message
36
- "API Error: #{to_s}"
47
+ class API < Abstract
48
+ def initialize(http_response)
49
+ super
50
+ raise TddiumClient::Error::Server.new(http_response) unless tddium_response.include?("status")
51
+ raise TddiumClient::Error::API.new(http_response) unless tddium_response["status"] == 0
52
+ end
37
53
  end
38
54
  end
39
55
 
40
- class ServerError < TddiumClient::Error
41
- attr_accessor :http_code, :http_result
56
+ module Error
57
+ class Timeout < Base; end
42
58
 
43
- def initialize(http_code, http_result)
44
- self.http_code = http_code
45
- self.http_result = http_result
46
- end
47
-
48
- def to_s
49
- "#{http_code} #{http_result}"
50
- end
59
+ class Server < TddiumClient::Result::Base
60
+ def to_s
61
+ "#{http_code} #{http_message}"
62
+ end
51
63
 
52
- def message
53
- "Server Error: #{to_s}"
64
+ def message
65
+ "Server Error: #{to_s}"
66
+ end
54
67
  end
55
- end
56
68
 
57
- class Result
58
- attr_accessor :http_code, :http_result, :response
69
+ class API < TddiumClient::Result::Abstract
70
+ def initialize(http_response)
71
+ super
72
+ end
59
73
 
60
- def initialize(http_code, http_result, response)
61
- self.http_code = http_code
62
- self.http_result = http_result
63
- self.response = response
64
- end
74
+ def to_s
75
+ "#{http_code} #{http_message} (#{status}) #{explanation}"
76
+ end
65
77
 
66
- def success?
67
- has_response? && response["status"] == 0
68
- end
78
+ def message
79
+ "API Error: #{to_s}"
80
+ end
69
81
 
70
- def has_response?
71
- !response.nil? && response.is_a?(Hash)
72
- end
82
+ def explanation
83
+ tddium_response["explanation"]
84
+ end
73
85
 
74
- def status
75
- has_response? ? response["status"] : nil
76
- end
77
-
78
- def explanation
79
- has_response? ? response["explanation"] : nil
86
+ def status
87
+ tddium_response["status"]
88
+ end
80
89
  end
81
90
  end
82
91
 
@@ -110,19 +119,9 @@ module TddiumClient
110
119
  end
111
120
  end
112
121
 
113
- raise TimeoutError if tries > retries
114
-
115
- response = JSON.parse(http.body) rescue {}
116
-
117
- http_message = http.response.header.msg.to_s
118
-
119
- raise ServerError.new(http.code, http_message) unless response.is_a?(Hash) && response.include?("status")
120
-
121
- result = Result.new(http.code, http.response.header.msg.to_s, response)
122
-
123
- raise APIError.new(result) if !result.success?
122
+ raise Error::Timeout if tries > retries && retries >= 0
124
123
 
125
- result
124
+ Result::API.new(http)
126
125
  end
127
126
 
128
127
  private
@@ -3,5 +3,5 @@ Copyright (c) 2011 Solano Labs All Rights Reserved
3
3
  =end
4
4
 
5
5
  module TddiumClient
6
- VERSION = "0.0.5"
6
+ VERSION = "0.0.6"
7
7
  end
@@ -4,69 +4,199 @@ Copyright (c) 2011 Solano Labs All Rights Reserved
4
4
 
5
5
  require "spec_helper"
6
6
 
7
- module TddiumClient
8
- describe Result do
9
- describe "#has_response?" do
10
- it "should be true with a reponse" do
11
- result = TddiumClient::Result.new 200, "OK", {"status" => 0}
12
- result.should be_has_response
7
+ describe "TddiumClient" do
8
+ let(:http_response) { mock(Net::HTTP).as_null_object }
9
+
10
+ def stub_sample_api_response(options = {})
11
+ options[:status]
12
+ return_value = ""
13
+ unless options[:status] == false
14
+ options[:success] = true unless options[:success] == false
15
+ return_value = {"status" => options[:success] ? 0 : 1}
16
+ return_value.merge!(:explanation => options[:explanation] || "User not found") unless options[:success]
17
+ return_value = return_value.to_json
18
+ end
19
+ http_response.stub(:body).and_return(return_value)
20
+ end
21
+
22
+ def stub_http_code(code = "401")
23
+ http_response.stub(:code).and_return(code)
24
+ end
25
+
26
+ def stub_http_message(message = "Unauthorized")
27
+ http_response.stub_chain(:response, :header, :msg).and_return(message)
28
+ end
29
+
30
+ describe "Response" do
31
+
32
+ shared_examples_for "base" do
33
+ describe "#http_code" do
34
+ before {stub_http_code("200")}
35
+ it "should return the http status code from the response" do
36
+ base.http_code.should == "200"
37
+ end
38
+ end
39
+
40
+ describe "#http_message" do
41
+ before {stub_http_message("OK")}
42
+ it "should return the http message from the response" do
43
+ base.http_message.should == "OK"
44
+ end
45
+ end
46
+
47
+ describe "#http_response" do
48
+ it "should return the http response" do
49
+ base.http_response.should == http_response
50
+ end
51
+ end
52
+ end
53
+
54
+ shared_examples_for "abstract" do
55
+ it_should_behave_like "base" do
56
+ let(:base) { TddiumClient::Result::API.new(http_response) }
57
+ end
58
+
59
+ before { stub_sample_api_response }
60
+
61
+ describe "#tddium_response" do
62
+ it "should return the parsed tddium_response" do
63
+ abstract.tddium_response.should == {"status" => 0}
64
+ end
65
+ end
66
+
67
+ describe "#[]" do
68
+ it "should return the result from the tddium_response" do
69
+ abstract["status"].should == 0
70
+ end
13
71
  end
72
+ end
14
73
 
15
- it "should be false without a response" do
16
- result = TddiumClient::Result.new 200, "OK", nil
17
- result.should_not be_has_response
74
+ describe "Base" do
75
+ it_should_behave_like "base" do
76
+ let(:base) {TddiumClient::Result::Base.new(http_response)}
18
77
  end
78
+ end
19
79
 
20
- it "should be false with a nonhash response" do
21
- result = TddiumClient::Result.new 200, "OK", "a"
22
- result.should_not be_has_response
80
+ describe "Abstract" do
81
+ it_should_behave_like "abstract" do
82
+ let(:abstract) { TddiumClient::Result::Abstract.new(http_response) }
23
83
  end
24
84
  end
25
85
 
26
- describe "#success?" do
27
- context "with successful params" do
28
- it "should be true" do
29
- result = TddiumClient::Result.new 200, "OK", {"status" => 0}
30
- result.should be_success
86
+ describe "API" do
87
+ let(:api) { TddiumClient::Result::API.new(http_response) }
88
+ it_should_behave_like "abstract" do
89
+ let(:abstract) { api }
90
+ end
91
+
92
+ context "no status is included in the response" do
93
+ before {stub_sample_api_response(:status => false) }
94
+
95
+ it "should raise a ServerError" do
96
+ expect {
97
+ TddiumClient::Result::API.new(http_response)
98
+ }.to raise_error(TddiumClient::Error::Server)
31
99
  end
32
100
  end
33
101
 
34
- context "with unsuccessful params" do
35
- it "should handle no response" do
36
- result = TddiumClient::Result.new 200, "OK", nil
37
- result.should_not be_success
102
+ context "a status is included in the response but it does not == 0" do
103
+ before {stub_sample_api_response(:success => false) }
104
+
105
+ it "should raise an APIError" do
106
+ expect {
107
+ TddiumClient::Result::API.new(http_response)
108
+ }.to raise_error(TddiumClient::Error::API)
38
109
  end
110
+ end
39
111
 
40
- it "should handle 5xx" do
41
- result = TddiumClient::Result.new 501, "Internal Server Error", {"status" => 1}
42
- result.should_not be_success
112
+ context "a status is included in the response and it == 0" do
113
+ before {stub_sample_api_response }
114
+ it "should return a new instance of Response::Client" do
115
+ TddiumClient::Result::API.new(http_response).should be_a(TddiumClient::Result::API)
43
116
  end
44
117
  end
45
118
  end
46
119
  end
47
120
 
48
- describe ServerError do
49
- it "should stringify with code and result" do
50
- code = 404
51
- message = 'Not Found'
52
- e = TddiumClient::ServerError.new(code, message)
53
- e.message.should =~ /#{code}/
54
- e.message.should =~ /#{message}/
121
+ describe "Error" do
122
+ shared_examples_for "#to_s" do
123
+ before do
124
+ stub_http_code("401")
125
+ stub_http_message("Unauthorized")
126
+ end
127
+
128
+ it "should contain the http code" do
129
+ result.should include("401")
130
+ end
131
+
132
+ it "should contain the http message" do
133
+ result.should include("Unauthorized")
134
+ end
55
135
  end
56
- end
57
136
 
58
- describe APIError do
59
- it "should stringify with explanation" do
60
- obj = {"status" => 1, "explanation"=>"oops"}
61
- result = TddiumClient::Result.new(200, "OK", obj)
62
- result.should_not be_success
63
- e = TddiumClient::APIError.new(result)
64
- e.message.should =~ /#{obj["status"]}/
65
- e.message.should =~ /#{obj["explanation"]}/
137
+ describe "Server" do
138
+ let(:server_error) { TddiumClient::Error::Server.new(http_response) }
139
+
140
+ it_should_behave_like("base") do
141
+ let(:base) { server_error }
142
+ end
143
+
144
+ describe "#to_s" do
145
+ it_should_behave_like("#to_s") do
146
+ let(:result) {server_error.to_s}
147
+ end
148
+ end
149
+
150
+ describe "#message" do
151
+ it_should_behave_like("#to_s") do
152
+ let(:result) {server_error.message}
153
+ end
154
+
155
+ it "should start with 'Server Error:'" do
156
+ server_error.message.should =~ /^Server Error:/
157
+ end
158
+ end
159
+ end
160
+
161
+ describe "API" do
162
+ let(:api_error) { TddiumClient::Error::API.new(http_response) }
163
+
164
+ it_should_behave_like("abstract") do
165
+ let(:abstract) { api_error }
166
+ end
167
+
168
+ describe "#to_s" do
169
+ it_should_behave_like("#to_s") do
170
+ let(:result) {api_error.to_s}
171
+ end
172
+ end
173
+
174
+ describe "#message" do
175
+ before do
176
+ stub_sample_api_response(:success => false, :explanation => "User is invalid")
177
+ end
178
+
179
+ it_should_behave_like("#to_s") do
180
+ let(:result) {api_error.message}
181
+ end
182
+
183
+ it "should start with 'API Error:'" do
184
+ api_error.message.should =~ /^API Error:/
185
+ end
186
+
187
+ it "should include the api status in brackets ()" do
188
+ api_error.message.should include("(1)")
189
+ end
190
+
191
+ it "should include the api explanation" do
192
+ api_error.message.should include("User is invalid")
193
+ end
194
+
195
+ end
66
196
  end
67
197
  end
68
198
 
69
- describe Client do
199
+ describe "Client" do
70
200
  include FakeFS::SpecHelpers
71
201
  include TddiumSpecHelpers
72
202
 
@@ -105,7 +235,7 @@ module TddiumClient
105
235
  end
106
236
 
107
237
  describe "#call_api" do
108
- before(:each) do
238
+ before do
109
239
  FakeWeb.clean_registry
110
240
  stub_tddium_client_config
111
241
  stub_http_response(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, :response => fixture_path("post_suites_201.json"))
@@ -130,12 +260,12 @@ module TddiumClient
130
260
 
131
261
  it "should retry 5 times by default to contact the API" do
132
262
  HTTParty.should_receive(EXAMPLE_HTTP_METHOD).exactly(6).times
133
- expect { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE) }.to raise_error(TddiumClient::TimeoutError)
263
+ expect { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE) }.to raise_error(TddiumClient::Error::Timeout)
134
264
  end
135
265
 
136
266
  it "should retry as many times as we want to contact the API" do
137
267
  HTTParty.should_receive(EXAMPLE_HTTP_METHOD).exactly(3).times
138
- expect { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, {}, nil, 2) }.to raise_error(TddiumClient::TimeoutError)
268
+ expect { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, {}, nil, 2) }.to raise_error(TddiumClient::Error::Timeout)
139
269
  end
140
270
  end
141
271
 
@@ -177,102 +307,32 @@ module TddiumClient
177
307
  tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, {}, nil) rescue {}
178
308
  end
179
309
 
180
- it "should return a TddiumClient::Result" do
310
+ it "should return a TddiumClient::Result::Client" do
181
311
  result = tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, {}, nil)
182
- result.should be_a(TddiumClient::Result)
312
+ result.should be_a(TddiumClient::Result::API)
183
313
  end
184
314
 
185
315
  it "should parse the JSON response" do
186
316
  result = tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, {}, nil)
187
- result.http_code.should == 201
188
- result.response.should be_a(Hash)
189
- result.response["status"].should == 0
190
- result.should be_success
191
- result.response["suite"]["id"].should == 19
317
+ result.tddium_response["status"].should == 0
318
+ result.tddium_response["suite"]["id"].should == 19
192
319
  end
193
320
  end
194
321
 
195
- context "exceptions for an unprocessable response" do
322
+ context "the response has no 'status' in the body" do
196
323
  before { stub_http_response(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, :status => ["501", "Internal Server Error"]) }
197
- it "should raise a TddiumClient::ServerError" do
198
- expect do
324
+ it "should raise a TddiumClient::Error::Server" do
325
+ expect {
199
326
  tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE)
200
- end.to raise_error do |error|
201
- puts error.inspect
202
- error.should be_a(TddiumClient::ServerError)
203
- error.should respond_to(:http_code)
204
- error.http_code.should == 500
205
- error.http_message.should =~ /Internal Server Error/
206
- end
207
- end
208
-
209
- context "when no response is present" do
210
- before { stub_http_response(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, :status => ["200", "OK"]) }
211
- it "should raise a TddiumClient::ServerError" do
212
- expect do
213
- tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE)
214
- end.to raise_error do |error|
215
- error.should be_a(TddiumClient::ServerError)
216
- error.should respond_to(:http_code)
217
- error.http_code.should == 200
218
- error.http_message.should =~ /OK/
219
- end
220
- end
221
- end
222
- end
223
-
224
- shared_examples_for "raising an APIError" do
225
- # users can set:
226
- #
227
- # aproc
228
- # http_code
229
- # http_message
230
- it "should raise the right exception" do
231
- expect { aproc.call }.to raise_error do |error|
232
- error.should be_a(TddiumClient::APIError)
233
- error.should respond_to(:tddium_result)
234
- error.tddium_result.should be_a(TddiumClient::Result)
235
- end
236
- end
237
-
238
- it "should capture the http response line" do
239
- expect { aproc.call }.to raise_error do |error|
240
- error.tddium_result.http_code.should == http_code if http_code
241
- error.tddium_result.http_message.should == http_message if http_message
242
- end
327
+ }.to raise_error(TddiumClient::Error::Server)
243
328
  end
244
329
  end
245
330
 
246
331
  context "where the http request was successful but API status is not 0" do
247
332
  before { stub_http_response(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, :response => fixture_path("post_suites_269_json_status_1.json")) }
248
333
 
249
- it_should_behave_like "raising an APIError" do
250
- let(:aproc) { Proc.new { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE) } }
251
- let(:http_code) {269}
252
- end
253
- end
254
-
255
- context "exceptions for an error response" do
256
- before { stub_http_response(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, :status => ["404", "Not Found"]) }
257
- it_should_behave_like "raising an APIError" do
258
- let(:aproc) { Proc.new { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE) } }
259
- let(:http_code) {404}
260
- end
261
-
262
- context "and an API error is returned" do
263
- before { stub_http_response(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE, :response => fixture_path("post_suites_409.json")) }
264
- it_should_behave_like "raising an APIError" do
265
- let(:aproc) { Proc.new { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE) } }
266
- let(:http_code) {409}
267
- end
268
-
269
- it "should have an api status" do
270
- expect do
271
- tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE)
272
- end.to raise_error do |error|
273
- error.tddium_result.response[:status].should == 1
274
- end
275
- end
334
+ it "should raise a TddiumClient::Error::API Error" do
335
+ expect { tddium_client.call_api(EXAMPLE_HTTP_METHOD, EXAMPLE_TDDIUM_RESOURCE) }.to raise_error(TddiumClient::Error::API)
276
336
  end
277
337
  end
278
338
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tddium_client
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.5
5
+ version: 0.0.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jay Moorthi
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-28 00:00:00 -07:00
13
+ date: 2011-04-04 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency