reward_station 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +2 -2
  3. data/README.md +121 -0
  4. data/{spec/fixtures/savon/reward_station → lib/responses}/award_points/award_points.xml +0 -0
  5. data/{spec/fixtures/savon/reward_station → lib/responses}/award_points/award_points_invalid_token.xml +0 -0
  6. data/{spec/fixtures/savon/reward_station → lib/responses}/return_point_summary/return_point_summary.xml +0 -0
  7. data/{spec/fixtures/savon/reward_station → lib/responses}/return_point_summary/return_point_summary_invalid_token.xml +0 -0
  8. data/{spec/fixtures/savon/reward_station → lib/responses}/return_popular_products/return_popular_products.xml +0 -0
  9. data/{spec/fixtures/savon/reward_station → lib/responses}/return_popular_products/return_popular_products_invalid_token.xml +0 -0
  10. data/{spec/fixtures/savon/reward_station → lib/responses}/return_token/return_token.xml +0 -0
  11. data/{spec/fixtures/savon/reward_station → lib/responses}/return_token/return_token_invalid.xml +0 -0
  12. data/{spec/fixtures/savon/reward_station → lib/responses}/return_user/return_user.xml +0 -0
  13. data/{spec/fixtures/savon/reward_station → lib/responses}/return_user/return_user_invalid_token.xml +0 -0
  14. data/{spec/fixtures/savon/reward_station → lib/responses}/return_user/return_user_invalid_user.xml +0 -0
  15. data/{spec/fixtures/savon/reward_station → lib/responses}/update_user/create_user.xml +0 -0
  16. data/{spec/fixtures/savon/reward_station → lib/responses}/update_user/create_user_exists.xml +0 -0
  17. data/lib/reward_station.rb +10 -1
  18. data/lib/reward_station/errors.rb +31 -0
  19. data/lib/reward_station/service.rb +167 -0
  20. data/lib/reward_station/version.rb +1 -1
  21. data/lib/saml/auth_response.rb +174 -0
  22. data/lib/savon/macros.rb +12 -0
  23. data/lib/savon/mock.rb +70 -0
  24. data/lib/savon/mock_response.rb +45 -0
  25. data/reward_station.gemspec +5 -3
  26. data/spec/reward_station/service_spec.rb +326 -0
  27. data/spec/spec_helper.rb +1 -8
  28. metadata +44 -24
  29. data/lib/xceleration/reward_station.rb +0 -122
  30. data/spec/savon_helper.rb +0 -129
  31. data/spec/xceleration/reward_station_spec.rb +0 -348
@@ -0,0 +1,12 @@
1
+ module Savon
2
+ # = Savon::Spec::Macros
3
+ #
4
+ # Include this module into your RSpec tests to mock/stub Savon SOAP requests.
5
+ module Macros
6
+ def savon
7
+ Savon::SOAP::Response.any_instance.stub(:soap_fault?).and_return(false)
8
+ Savon::SOAP::Response.any_instance.stub(:http_error?).and_return(false)
9
+ Savon::Mock.new
10
+ end
11
+ end
12
+ end
data/lib/savon/mock.rb ADDED
@@ -0,0 +1,70 @@
1
+ module Savon
2
+ # = Savon::Spec::Mock
3
+ #
4
+ # Mocks/stubs SOAP requests executed by Savon.
5
+ class Mock
6
+
7
+ def expects(soap_action)
8
+ setup :expects, soap_action
9
+ self
10
+ end
11
+
12
+ def stub(soap_action)
13
+ setup :stub, soap_action
14
+ self
15
+ end
16
+
17
+ # Expects a given SOAP body Hash to be used.
18
+ def with(soap_body)
19
+ Savon::SOAP::XML.any_instance.expects(:body=).with(soap_body) if mock_method == :expects
20
+ self
21
+ end
22
+
23
+ def never
24
+ httpi_mock.never
25
+ self
26
+ end
27
+
28
+ # Sets up HTTPI to return a given +response+.
29
+ def and_return(response = nil)
30
+ http = { :code => 200, :headers => {}, :body => "" }
31
+
32
+ case response
33
+ when Symbol then http[:body] = MockResponse[soap_action, response]
34
+ when Hash then http.merge! response
35
+ when String then http[:body] = response
36
+ end
37
+
38
+ httpi_mock.and_return HTTPI::Response.new(http[:code], http[:headers], http[:body])
39
+ self
40
+ end
41
+
42
+ # Sets up Savon to respond like there was a SOAP fault.
43
+ def raises_soap_fault
44
+ Savon::SOAP::Response.any_instance.stub(:soap_fault?).and_return(true)
45
+ self
46
+ end
47
+
48
+ def raises_http_error
49
+ Savon::SOAP::Response.any_instance.stub(:soap_fault?).and_return(false)
50
+ Savon::SOAP::Response.any_instance.stub(:http_error?).and_return(true)
51
+ self
52
+ end
53
+
54
+ private
55
+
56
+ def setup(mock_method, soap_action)
57
+ self.mock_method = mock_method
58
+ self.soap_action = soap_action
59
+ self.httpi_mock = HTTPI.send(mock_method, :post)
60
+ end
61
+
62
+ attr_accessor :mock_method
63
+ attr_accessor :httpi_mock
64
+
65
+ attr_reader :soap_action
66
+ def soap_action=(soap_action)
67
+ @soap_action = soap_action.kind_of?(Symbol) ? soap_action.to_s.lower_camelcase : soap_action
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,45 @@
1
+ module Savon
2
+ class MockResponse
3
+ class << self
4
+
5
+ def gem_responses_path
6
+ File.join(File.dirname(__FILE__), "..", "responses")
7
+ end
8
+
9
+ def local_responses_path
10
+ File.expand_path('config/responses') rescue nil
11
+ end
12
+
13
+ def load(*args)
14
+ file = args.map { |arg| arg.to_s.snakecase }.join("/")
15
+ responses[file] ||= load_response_file file
16
+ end
17
+
18
+ alias_method :[], :load
19
+
20
+ private
21
+
22
+ def responses
23
+ @responses ||= {}
24
+ end
25
+
26
+ def load_response_file(file)
27
+ file_path = nil
28
+
29
+ if local_responses_path
30
+ local_path = File.join(local_responses_path, "#{file}.xml")
31
+ file_path = local_path if File.exist?(local_path)
32
+ end
33
+
34
+ unless file_path
35
+ gem_path = File.join(gem_responses_path, "#{file}.xml")
36
+ file_path = gem_path if File.exist?(gem_path)
37
+ end
38
+
39
+ raise ArgumentError, "Unable to load: #{file}" unless file_path
40
+
41
+ File.read file_path
42
+ end
43
+ end
44
+ end
45
+ end
@@ -6,11 +6,11 @@ Gem::Specification.new do |s|
6
6
  s.name = "reward_station"
7
7
  s.version = RewardStation::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Stepan Filatov"]
9
+ s.authors = ["Stepan Filatov", 'Cloud Castle Inc.']
10
10
  s.email = ["filatov.st@gmail.com"]
11
11
  s.homepage = "https://github.com/sfilatov/reward_station"
12
- s.summary = %q{Reward Station is a client implementation of the Xceleration Reward Station service API}
13
- s.description = %q{Reward Station is a client implementation of the Xceleration Reward Station service API}
12
+ s.summary = %q{Reward Station is a client library for rewardstation.com}
13
+ s.description = %q{}
14
14
 
15
15
  s.rubyforge_project = "reward_station"
16
16
 
@@ -18,4 +18,6 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {spec}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'savon', ">= 0.9.6"
21
23
  end
@@ -0,0 +1,326 @@
1
+ require 'spec_helper'
2
+
3
+ describe RewardStation::Service do
4
+
5
+ let(:service) { RewardStation::Service.new :client_id => '100080', :client_password => 'fM6Rv4moz#', :token => "e285e1ed-2356-4676-a554-99d79e6284b0" }
6
+
7
+ describe "required options" do
8
+ it "should raise ArgumentError on missing client_id" do
9
+ lambda{ RewardStation::Service.new :client_password => "" }.should raise_error(ArgumentError)
10
+ end
11
+
12
+ it "should raise ArgumentError on missing client_password" do
13
+ lambda{ RewardStation::Service.new :client_id => "" }.should raise_error(ArgumentError)
14
+ end
15
+
16
+ it "should not rause ArgumentError if all required parameters present" do
17
+ lambda{ RewardStation::Service.new :client_id => "", :client_password => "" }.should_not raise_error(ArgumentError)
18
+ end
19
+ end
20
+
21
+ describe "new_token_callback" do
22
+ it "should raise ArgumentError if options is not lambda or proc" do
23
+ lambda{ RewardStation::Service.new :client_id => "", :client_password => "", :new_token_callback => "" }.should raise_error(ArgumentError)
24
+ end
25
+
26
+ it "should not raise ArgumentError if option is lambda or proc" do
27
+ lambda{ RewardStation::Service.new :client_id => "", :client_password => "", :new_token_callback => Proc.new { } }.should_not raise_error(ArgumentError)
28
+ end
29
+ end
30
+
31
+ describe "return_token" do
32
+
33
+ describe "on valid response" do
34
+ before { savon.stub(:return_token).and_return(:return_token) }
35
+
36
+ it "should return valid token" do
37
+ service.return_token.should eq("e285e1ed-2356-4676-a554-99d79e6284b0")
38
+ end
39
+
40
+ it "should not raise InvalidAccount exception" do
41
+ lambda{ service.return_token }.should_not raise_error(RewardStation::InvalidAccount)
42
+ end
43
+ end
44
+
45
+ describe "on invalid account response" do
46
+ before { savon.stub(:return_token).and_return(:return_token_invalid) }
47
+
48
+ it "should raise InvalidAccount exception" do
49
+ lambda{ service.return_token }.should raise_error(RewardStation::InvalidAccount)
50
+ end
51
+ end
52
+
53
+ describe "on soap error" do
54
+ before { savon.stub(:return_token).and_return.raises_soap_fault }
55
+
56
+ it "should raise ConnectionError exception" do
57
+ lambda{ service.return_token }.should raise_error(RewardStation::ConnectionError)
58
+ end
59
+ end
60
+
61
+ describe "on http error" do
62
+ before { savon.stub(:return_token).and_return(:code => 404).raises_http_error }
63
+
64
+ it "should raise HttpError exception" do
65
+ lambda{ service.return_token }.should raise_error(RewardStation::ConnectionError)
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "award_points" do
71
+ let(:service) {
72
+ RewardStation::Service.new :client_id => '100080',
73
+ :client_password => 'fM6Rv4moz#',
74
+ :program_id => 90,
75
+ :point_reason_code_id => 129,
76
+ :token => "e285e1ed-2356-4676-a554-99d79e6284b0"
77
+ }
78
+
79
+ describe "on valid response" do
80
+ before { savon.stub(:award_points).and_return(:award_points) }
81
+
82
+ it "should return valid confirm code" do
83
+ service.award_points(130, 10, "Action 'Some' taken").should eq("9376")
84
+ end
85
+ end
86
+
87
+ describe "on invalid token response" do
88
+ before { savon.stub(:award_points).and_return(:award_points_invalid_token) }
89
+
90
+ it "should not raise InvalidToken exception" do
91
+ lambda{ service.award_points(130, 10, "Action 'Some' taken") }.should_not raise_error(RewardStation::InvalidToken)
92
+ end
93
+ end
94
+
95
+ describe "on soap error" do
96
+ before { savon.stub(:award_points).and_return.raises_soap_fault }
97
+
98
+ it "should raise ConnectionError exception" do
99
+ lambda{ service.award_points(130, 10, "Action 'Some' taken") }.should raise_error(RewardStation::ConnectionError)
100
+ end
101
+ end
102
+
103
+ describe "on http error" do
104
+ before { savon.stub(:award_points).and_return(:code => 404).raises_http_error }
105
+
106
+ it "should raise HttpError exception" do
107
+ lambda{ service.award_points(130, 10, "Action 'Some' taken") }.should raise_error(RewardStation::ConnectionError)
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ describe "return_user" do
114
+
115
+ describe "on valid response" do
116
+ before { savon.stub(:return_user).and_return(:return_user) }
117
+
118
+ it "should return valid user data" do
119
+ service.return_user(130).should eq(:user_id => '6725',
120
+ :client_id => '100080',
121
+ :user_name => 'john3@company.com',
122
+ :encrypted_password => nil,
123
+ :first_name => 'John',
124
+ :last_name => 'Smith',
125
+ :address_one => nil,
126
+ :address_two => nil,
127
+ :city => nil,
128
+ :state_code => nil,
129
+ :province => nil,
130
+ :postal_code => nil,
131
+ :country_code => 'USA',
132
+ :phone => nil,
133
+ :email => 'john@company.com',
134
+ :organization_id => '0',
135
+ :organization_name => nil,
136
+ :rep_type_id => '0',
137
+ :client_region_id => '0',
138
+ :is_active => true,
139
+ :point_balance => '10',
140
+ :manager_id => '0',
141
+ :error_message => nil)
142
+ end
143
+
144
+ it "should not raise InvalidToken exception" do
145
+ lambda{ service.return_user(130) }.should_not raise_error(RewardStation::InvalidToken)
146
+ end
147
+ end
148
+
149
+ describe "on invalid token response" do
150
+ before { savon.stub(:return_user).and_return(:return_user_invalid_token) }
151
+
152
+ it "should not raise InvalidToken exception" do
153
+ lambda{ service.return_user(130) }.should_not raise_error(RewardStation::InvalidToken)
154
+ end
155
+ end
156
+
157
+ describe "on invalid user response" do
158
+ before { savon.stub(:return_user).and_return(:return_user_invalid_user) }
159
+
160
+ it "should raise InvalidUser exception" do
161
+ lambda{ service.return_user(130) }.should raise_error(RewardStation::InvalidUser)
162
+ end
163
+ end
164
+
165
+ describe "on soap error" do
166
+ before { savon.stub(:return_user).and_return.raises_soap_fault }
167
+
168
+ it "should raise ConnectionError exception" do
169
+ lambda{ service.return_user(130) }.should raise_error(RewardStation::ConnectionError)
170
+ end
171
+ end
172
+
173
+ describe "on http error" do
174
+ before { savon.stub(:return_user).and_return(:code => 404).raises_http_error }
175
+
176
+ it "should raise HttpError exception" do
177
+ lambda{ service.return_user(130) }.should raise_error(RewardStation::ConnectionError)
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "return_point_summary" do
183
+ describe "on valid request" do
184
+ before { savon.stub(:return_point_summary).and_return(:return_point_summary) }
185
+
186
+ it "should return valid summary" do
187
+ service.return_point_summary(130).should eq(:user_id => '577',
188
+ :is_active => true,
189
+ :points_earned => '465',
190
+ :points_redeemed => '0',
191
+ :points_credited => '0',
192
+ :points_balance => '465')
193
+ end
194
+
195
+ it "should not raise InvalidToken exception" do
196
+ lambda{ service.return_point_summary(130) }.should_not raise_error(RewardStation::InvalidToken)
197
+ end
198
+ end
199
+
200
+ describe "on invalid token request" do
201
+ before { savon.stub(:return_point_summary).and_return(:return_point_summary_invalid_token) }
202
+
203
+ it "should not raise InvalidToken exception" do
204
+ lambda{ service.return_point_summary(130) }.should_not raise_error(RewardStation::InvalidToken)
205
+ end
206
+ end
207
+
208
+ describe "on soap error" do
209
+ before { savon.stub(:return_point_summary).and_return.raises_soap_fault }
210
+
211
+ it "should raise ConnectionError exception" do
212
+ lambda{ service.return_point_summary(130) }.should raise_error(RewardStation::ConnectionError)
213
+ end
214
+ end
215
+
216
+ describe "on http error" do
217
+ before { savon.stub(:return_point_summary).and_return(:code => 404).raises_http_error }
218
+
219
+ it "should raise HttpError exception" do
220
+ lambda{ service.return_point_summary(130) }.should raise_error(RewardStation::ConnectionError)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe "update_user" do
226
+ let(:service) { RewardStation::Service.new :client_id => '100080', :client_password => 'fM6Rv4moz#', :organization_id => '150', :token => "e285e1ed-2356-4676-a554-99d79e6284b0" }
227
+
228
+ describe "on create user valid request" do
229
+ before { savon.stub(:update_user).and_return(:create_user) }
230
+
231
+ it "should return valid response" do
232
+ service.create_user(
233
+ :email => 'john5@company.com',
234
+ :first_name => 'John',
235
+ :last_name => 'Smith',
236
+ :user_name => 'john5@company.com',
237
+ :balance => 0
238
+ ).should eq(:user_id => '6727',
239
+ :client_id => '100080',
240
+ :user_name => 'john5@company.com',
241
+ :email => 'john5@company.com',
242
+ :encrypted_password => nil,
243
+ :first_name => 'John',
244
+ :last_name => 'Smith',
245
+ :address_one => nil,
246
+ :address_two => nil,
247
+ :city => nil,
248
+ :state_code => nil,
249
+ :province => nil,
250
+ :postal_code => nil,
251
+ :country_code => 'USA',
252
+ :phone => nil,
253
+ :organization_id => '150',
254
+ :organization_name => nil,
255
+ :rep_type_id => '0',
256
+ :client_region_id => '0',
257
+
258
+ :is_active => true,
259
+ :point_balance => '0',
260
+ :manager_id => '0',
261
+ :error_message => nil)
262
+ end
263
+
264
+ it "should not raise InvalidToken exception" do
265
+ lambda{
266
+ service.create_user(:email => 'john5@company.com',
267
+ :first_name => 'John',
268
+ :last_name => 'Smith',
269
+ :user_name => 'john5@company.com',
270
+ :balance => 0)
271
+ }.should_not raise_error(RewardStation::InvalidToken)
272
+ end
273
+ end
274
+
275
+ describe "on create user invalid request" do
276
+ before { savon.stub(:update_user).and_return(:create_user_exists) }
277
+
278
+ it "should raise UserAlreadyExists exception" do
279
+ lambda{
280
+ service.update_user(130, {
281
+ :email => 'john5@company.com',
282
+ :first_name => 'John',
283
+ :last_name => 'Smith',
284
+ :user_name => 'john5@company.com',
285
+ :balance => 0
286
+ })
287
+ }.should raise_error(RewardStation::UserAlreadyExists)
288
+ end
289
+ end
290
+
291
+ end
292
+
293
+ describe "return_popular_products" do
294
+ describe "on valid request" do
295
+ before { savon.stub(:return_popular_products).and_return(:return_popular_products) }
296
+
297
+ it "should return valid response" do
298
+ products = service.return_popular_products(130)
299
+ products.should be_a(Array)
300
+ products.size.should eq(35)
301
+ products.first.should eq(:product_id => 'MC770LLA',
302
+ :name => 'iPad 2 with Wifi - 32GB',
303
+ :description => 'The NEW Apple iPad 2 - Thinner, lighter, and full of great ideas. Once you pick up iPad 2, it’ll be hard to put down. That’s the idea behind the all-new design. It’s 33 percent thinner and up to 15 percent lighter, so it feels even more comfortable in your hands. And, it makes surfing the web, checking email, watching movies, and reading books so natural, you might forget there’s incredible technology under your fingers.<br><br><b>Dual-core A5 chip</b>.<br> Two powerful cores in one A5 chip mean iPad can do twice the work at once. You’ll notice the difference when you’re surfing the web, watching movies, making FaceTime video calls, gaming, and going from app to app to app. Multitasking is smoother, apps load faster, and everything just works better.<br><br><b>Superfast graphics</b>. <br>With up to nine times the graphics performance, gameplay on iPad is even smoother and more realistic. And faster graphics help apps perform better — especially those with video. You’ll see it when you’re scrolling through your photo library, editing video with iMovie, and viewing animations in Keynote.<br><br><b>Battery life keeps on going. So you can, too.</b><br> Even with the new thinner and lighter design, iPad has the same amazing 10-hour battery life. That’s enough juice for one flight across the ocean, or one movie-watching all-nighter, or a week’s commute across town. The power-efficient A5 chip and iOS keep battery life from fading away, so you can get carried away.<br><br><b>Two cameras.</b><br> You’ll see two cameras on iPad — one on the front and one on the back. They may be tiny, but they’re a big deal. They’re designed for FaceTime video calling, and they work together so you can talk to your favorite people and see them smile and laugh back at you. The front camera puts you and your friend face-to-face. Switch to the back camera during your video call to share where you are, who you’re with, or what’s going on around you. When you’re not using FaceTime, let the back camera roll if you see something movie-worthy. It’s HD, so whatever you shoot is a mini-masterpiece. And you can take wacky snapshots in Photo Booth. It’s the most fun a face can have.<br><br><b>Due to the demand for this item, please allow up to 8-10 weeks for delivery</b>.',
304
+ :points => '10927',
305
+ :category => 'Office & Computer',
306
+ :manufacturer => 'Apple',
307
+ :small_image_url => 'https://www.rewardstation.com/catalogimages/MC769LLA.gif',
308
+ :large_image_url => 'https://www.rewardstation.com/catalogimages/MC769LLA.jpg')
309
+ end
310
+
311
+ it "should not raise InvalidToken exception" do
312
+ lambda{ service.return_popular_products(130) }.should_not raise_error(RewardStation::InvalidToken)
313
+ end
314
+ end
315
+
316
+ describe "on create user invalid token request" do
317
+ before { savon.stub(:return_popular_products).and_return(:return_popular_products_invalid_token) }
318
+
319
+ it "should not raise InvalidToken exception" do
320
+ lambda{ service.return_popular_products(130) }.should_not raise_error(RewardStation::InvalidToken)
321
+ end
322
+ end
323
+
324
+ end
325
+
326
+ end