tddium_client 0.0.5 → 0.0.6

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.
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