spreedly 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 1.3.2
2
+
3
+ * Added methods on subscriber: update, allow_free_trial,
4
+ add_fee [mateuszzawisza]
5
+ * Fixing tests: generate spreedly url and edit url working with all
6
+ site names [mateuszzawisza]
7
+ * Add support for pre-population of the subscribe page via the subscribe
8
+ url. [davemcp]
9
+
1
10
  === 1.3.1
2
11
 
3
12
  * Handle new error reporting when creating a subscriber.
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ hoe = Hoe.spec('spreedly') do
8
8
  self.rubyforge_name = 'terralien'
9
9
  self.test_globs = ["test/**/*_test.rb"]
10
10
  self.extra_deps << ["mechanize"]
11
- self.extra_dev_deps << ["thoughtbot-shoulda"]
11
+ self.extra_dev_deps << ["shoulda"]
12
12
  end
13
13
 
14
14
  def remove_task(*task_names)
@@ -37,7 +37,7 @@ end
37
37
 
38
38
  desc "Publish documentation."
39
39
  replace_task :publish_docs => [:clean, :docs] do
40
- host = "terralien@terralien.biz"
40
+ host = "terralien@terralien.com"
41
41
 
42
42
  remote_dir = "/var/www/terralien/www/shared/static/projects/spreedly-gem"
43
43
  local_dir = 'doc'
@@ -69,4 +69,4 @@ replace_task :multi do
69
69
  ruby hoe.make_test_cmd(:multi)
70
70
  ENV["SPREEDLY_TEST"] = "REAL"
71
71
  ruby hoe.make_test_cmd(:multi)
72
- end
72
+ end
data/lib/spreedly.rb CHANGED
@@ -107,7 +107,7 @@ module Spreedly
107
107
  # Spreedly.Subscriber.create!(id, email, screen_name)
108
108
  # Spreedly.Subscriber.create!(id, :email => email, :screen_name => screen_name)
109
109
  # Spreedly.Subscriber.create!(id, email, screen_name, :billing_first_name => first_name)
110
- def self.create!(id, *args)
110
+ def self.create!(id, *args)
111
111
  optional_attrs = args.last.is_a?(::Hash) ? args.pop : {}
112
112
  email, screen_name = args
113
113
  subscriber = {:customer_id => id, :email => email, :screen_name => screen_name}.merge(optional_attrs)
@@ -152,6 +152,7 @@ module Spreedly
152
152
  def comp(quantity, units, feature_level=nil)
153
153
  params = {:duration_quantity => quantity, :duration_units => units}
154
154
  params[:feature_level] = feature_level if feature_level
155
+ raise "Feature level is required to comp an inactive subscriber" if !active? and !feature_level
155
156
  endpoint = (active? ? "complimentary_time_extensions" : "complimentary_subscriptions")
156
157
  result = Spreedly.post("/subscribers/#{id}/#{endpoint}.xml", :body => Spreedly.to_xml_params(endpoint[0..-2] => params))
157
158
  case result.code.to_s
@@ -198,8 +199,58 @@ module Spreedly
198
199
  end
199
200
  end
200
201
 
201
- end
202
+
203
+
204
+ # Update a Subscriber
205
+ # usage: @subscriber.update(:email => email, :screen_name => screen_name)
206
+ def update(args)
207
+ result = Spreedly.put("/subscribers/#{id}.xml", :body => Spreedly.to_xml_params(:subscriber => args))
208
+
209
+ case result.code.to_s
210
+ when /2../
211
+ when '403'
212
+ raise "Could not update subscriber: new-customer-id is already in use."
213
+ when '404'
214
+ raise "Could not update subscriber: subscriber not found"
215
+ else
216
+ raise "Could not update subscriber: result code #{result.code}."
217
+ end
218
+ end
219
+
220
+
221
+ # Allow Another Free Trial
222
+ # usage: @subscriber.allow_free_trial
223
+ def allow_free_trial
224
+ result = Spreedly.post("/subscribers/#{id}/allow_free_trial.xml")
225
+
226
+ case result.code.to_s
227
+ when /2../
228
+ else
229
+ raise "Could not allow subscriber to another trial: result code #{result.code}."
230
+ end
231
+ end
232
+
233
+
234
+ # Add a Fee to a Subscriber
235
+ # usage: @subscriber.add_fee(:amount => amount, :group => group_name, :description => description, :name => name)
236
+ def add_fee(args)
237
+ result = Spreedly.post("/subscribers/#{id}/fees.xml", :body => Spreedly.to_xml_params(:fee => args))
238
+
239
+ case result.code.to_s
240
+ when /2../
241
+ when '404'
242
+ raise "Not Found"
243
+ when '422'
244
+ raise "Unprocessable Entity - #{result.body}"
245
+ else
246
+ raise "Could not add fee to subscriber: result code #{result.code}."
247
+ end
248
+ end
202
249
 
250
+
251
+ end
252
+
253
+
203
254
  class SubscriptionPlan < Resource
204
255
  # Returns all of the subscription plans defined in your site.
205
256
  def self.all
@@ -10,9 +10,24 @@ require 'spreedly/version'
10
10
 
11
11
  module Spreedly
12
12
  # Generates a subscribe url for the given user id and plan.
13
- def self.subscribe_url(id, plan, screen_name=nil)
14
- screen_name = (screen_name ? URI.escape(screen_name) : "")
15
- "https://spreedly.com/#{site_name}/subscribers/#{id}/subscribe/#{plan}/#{screen_name}"
13
+ # Options:
14
+ # :screen_name => a screen name for the user (shows up in the admin UI)
15
+ # :email => pre-populate the email field
16
+ # :first_name => pre-populate the first name field
17
+ # :last_name => pre-populate the last name field
18
+ def self.subscribe_url(id, plan, options={})
19
+ %w(screen_name email first_name last_name).each do |option|
20
+ options[option.to_sym] &&= URI.escape(options[option.to_sym])
21
+ end
22
+
23
+ screen_name = options.delete(:screen_name)
24
+ params = %w(email first_name last_name).select{|e| options[e.to_sym]}.collect{|e| "#{e}=#{options[e.to_sym]}"}.join('&')
25
+
26
+ url = "https://spreedly.com/#{site_name}/subscribers/#{id}/subscribe/#{plan}"
27
+ url << "/#{screen_name}" if screen_name
28
+ url << '?' << params unless params == ''
29
+
30
+ url
16
31
  end
17
32
 
18
33
  # Generates an edit subscriber for the given subscriber token. The
data/lib/spreedly/mock.rb CHANGED
@@ -51,7 +51,8 @@ module Spreedly
51
51
  :active_until => proc{nil},
52
52
  :feature_level => proc{""},
53
53
  :on_trial => proc{false},
54
- :recurring => proc{false}
54
+ :recurring => proc{false},
55
+ :eligible_for_free_trial => proc{false}
55
56
  }
56
57
 
57
58
  def self.wipe! # :nodoc: all
@@ -98,6 +99,14 @@ module Spreedly
98
99
  @attributes[:customer_id]
99
100
  end
100
101
 
102
+ def update(args)
103
+ args.each_pair do |key, value|
104
+ if @attributes.has_key?(key)
105
+ @attributes[key] = value
106
+ end
107
+ end
108
+ end
109
+
101
110
  def comp(quantity, units, feature_level=nil)
102
111
  raise "Could not comp subscriber: no longer exists." unless self.class.find(id)
103
112
  raise "Could not comp subscriber: validation failed." unless units && quantity
@@ -115,11 +124,15 @@ module Spreedly
115
124
  def activate_free_trial(plan_id)
116
125
  raise "Could not activate free trial for subscriber: validation failed. missing subscription plan id" unless plan_id
117
126
  raise "Could not active free trial for subscriber: subscriber or subscription plan no longer exists." unless self.class.find(id) && SubscriptionPlan.find(plan_id)
118
- raise "Could not activate free trial for subscriber: subscription plan either 1) isn't a free trial, 2) the subscriber is not eligible for a free trial, or 3) the subscription plan is not enabled." if on_trial?
127
+ raise "Could not activate free trial for subscriber: subscription plan either 1) isn't a free trial, 2) the subscriber is not eligible for a free trial, or 3) the subscription plan is not enabled." if (on_trial? and !eligible_for_free_trial?)
119
128
  @attributes[:on_trial] = true
120
129
  plan = SubscriptionPlan.find(plan_id)
121
130
  comp(plan.duration_quantity, plan.duration_units, plan.feature_level)
122
131
  end
132
+
133
+ def allow_free_trial
134
+ @attributes[:eligible_for_free_trial] = true
135
+ end
123
136
 
124
137
  def stop_auto_renew
125
138
  raise "Could not stop auto renew for subscriber: subscriber does not exist." unless self.class.find(id)
@@ -131,6 +144,12 @@ module Spreedly
131
144
  plan = SubscriptionPlan.find(plan_id)
132
145
  comp(plan.duration_quantity, plan.duration_units, plan.feature_level)
133
146
  end
147
+
148
+ def add_fee(args)
149
+ raise "Unprocessable Entity" unless (args.keys & [:amount, :group, :name]).size == 3
150
+ raise "Unprocessable Entity" unless active?
151
+ nil
152
+ end
134
153
  end
135
154
 
136
155
  class SubscriptionPlan < Resource
@@ -5,7 +5,7 @@ module Spreedly
5
5
  # This method is *strictly* for use when testing, and will
6
6
  # probably only work against a test Spreedly site anyhow.
7
7
  def subscribe(plan_id)
8
- agent = WWW::Mechanize.new
8
+ agent = Mechanize.new
9
9
  page = agent.get(Spreedly.subscribe_url(id, plan_id))
10
10
  page = page.forms.first.submit
11
11
  form = page.forms.first
@@ -21,4 +21,4 @@ module Spreedly
21
21
  raise "Subscription didn't got through" unless page.title == "Thank you!"
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Spreedly
2
- VERSION = "1.3.1"
3
- end
2
+ VERSION = "1.3.2"
3
+ end
@@ -14,6 +14,7 @@ end
14
14
  test_site = YAML.load(File.read(File.dirname(__FILE__) + '/test_site.yml'))
15
15
  Spreedly.configure(test_site['name'], test_site['token'])
16
16
 
17
+
17
18
  class SpreedlyGemTest < Test::Unit::TestCase
18
19
  def self.only_real
19
20
  yield if ENV["SPREEDLY_TEST"] == "REAL"
@@ -58,6 +59,13 @@ class SpreedlyGemTest < Test::Unit::TestCase
58
59
  end
59
60
  end # adding a subscriber
60
61
 
62
+ should "update subscriber" do
63
+ subscriber = Spreedly::Subscriber.create!('joe', :screen_name => "big-joe")
64
+ assert_equal "big-joe", Spreedly::Subscriber.find(subscriber.id).screen_name
65
+ subscriber.update(:screen_name => "small-joe")
66
+ assert_equal "small-joe", Spreedly::Subscriber.find(subscriber.id).screen_name
67
+ end
68
+
61
69
  should "get a subscriber" do
62
70
  id = create_subscriber.id
63
71
  subscriber = Spreedly::Subscriber.find(id)
@@ -69,10 +77,10 @@ class SpreedlyGemTest < Test::Unit::TestCase
69
77
  end
70
78
 
71
79
  should "expose and parse attributes" do
72
- subscriber = create_subscriber
80
+ subscriber = create_subscriber('bob')
73
81
  assert_kind_of Time, subscriber.created_at
74
- assert_equal false, subscriber.active
75
- assert_equal false, subscriber.recurring
82
+ assert !subscriber.active
83
+ assert !subscriber.recurring
76
84
  assert_equal BigDecimal('0.0'), subscriber.store_credit
77
85
  end
78
86
 
@@ -107,14 +115,21 @@ class SpreedlyGemTest < Test::Unit::TestCase
107
115
  end
108
116
 
109
117
  should "generate a subscribe url" do
110
- assert_equal "https://spreedly.com/terralien-test/subscribers/joe/subscribe/1/Joe%20Bob",
111
- Spreedly.subscribe_url('joe', '1', "Joe Bob")
112
- assert_equal "https://spreedly.com/terralien-test/subscribers/joe/subscribe/1/",
118
+ assert_equal "https://spreedly.com/#{Spreedly.site_name}/subscribers/joe/subscribe/1/Joe%20Bob",
119
+ Spreedly.subscribe_url('joe', '1', :screen_name => "Joe Bob")
120
+ assert_equal "https://spreedly.com/#{Spreedly.site_name}/subscribers/joe/subscribe/1",
113
121
  Spreedly.subscribe_url('joe', '1')
114
122
  end
115
123
 
124
+ should "generate a pre-populated subscribe url" do
125
+ assert_equal "https://spreedly.com/#{Spreedly.site_name}/subscribers/joe/subscribe/1?email=joe.bob@test.com&first_name=Joe&last_name=Bob",
126
+ Spreedly.subscribe_url('joe', '1', :email => "joe.bob@test.com", :first_name => "Joe", :last_name => "Bob")
127
+ assert_equal "https://spreedly.com/#{Spreedly.site_name}/subscribers/joe/subscribe/1?first_name=Joe&last_name=Bob",
128
+ Spreedly.subscribe_url('joe', '1', :first_name => "Joe", :last_name => "Bob")
129
+ end
130
+
116
131
  should "generate an edit subscriber url" do
117
- assert_equal "https://spreedly.com/terralien-test/subscriber_accounts/zetoken",
132
+ assert_equal "https://spreedly.com/#{Spreedly.site_name}/subscriber_accounts/zetoken",
118
133
  Spreedly.edit_subscriber_url('zetoken')
119
134
  end
120
135
 
@@ -133,7 +148,7 @@ class SpreedlyGemTest < Test::Unit::TestCase
133
148
  should "comp an active subscriber" do
134
149
  sub = create_subscriber
135
150
  assert !sub.active?
136
- sub.comp(1, 'days')
151
+ sub.comp(1, 'days', 'Sweet!')
137
152
 
138
153
  sub = Spreedly::Subscriber.find(sub.id)
139
154
  assert sub.active?
@@ -149,7 +164,7 @@ class SpreedlyGemTest < Test::Unit::TestCase
149
164
  sub = create_subscriber
150
165
  Spreedly::Subscriber.wipe!
151
166
  ex = assert_raise(RuntimeError) do
152
- sub.comp(1, 'days')
167
+ sub.comp(1, 'days', 'bogus')
153
168
  end
154
169
  assert_match(/exists/i, ex.message)
155
170
  end
@@ -157,7 +172,7 @@ class SpreedlyGemTest < Test::Unit::TestCase
157
172
  should "throw an error if comp is invalid" do
158
173
  sub = create_subscriber
159
174
  ex = assert_raise(RuntimeError) do
160
- sub.comp(nil, nil)
175
+ sub.comp(nil, nil, 'bogus')
161
176
  end
162
177
  assert_match(/validation/i, ex.message)
163
178
  assert_raise(RuntimeError){sub.comp(1, nil)}
@@ -203,6 +218,16 @@ class SpreedlyGemTest < Test::Unit::TestCase
203
218
  assert_match %r{not eligible}, ex.message
204
219
  end
205
220
 
221
+ should "allow second trial if 'allow_free_trial' is excecuted" do
222
+ sub = create_subscriber
223
+ sub.activate_free_trial(@trial.id)
224
+ sub.allow_free_trial
225
+ sub.activate_free_trial(@trial.id)
226
+ sub = Spreedly::Subscriber.find(sub.id)
227
+ assert sub.active?
228
+ assert sub.on_trial?
229
+ end
230
+
206
231
  should "throw errors on invalid free trial activation" do
207
232
  sub = create_subscriber
208
233
 
@@ -217,7 +242,7 @@ class SpreedlyGemTest < Test::Unit::TestCase
217
242
  context "with a Regular plan" do
218
243
  setup do
219
244
  @regular_plan = Spreedly::SubscriptionPlan.all.detect{|e| e.name == "Test Regular Plan"}
220
- assert @regular_plan, "For this test to pass in REAL mode you must have a regular plan in your Spreedly test site with the name \"Test Regular Plan\"."
245
+ assert @regular_plan, "For this test to pass in REAL mode you must have a regular plan in your Spreedly test site with the name \"Test Regular Plan\". It must be an auto-recurring plan."
221
246
  end
222
247
 
223
248
  should "stop auto renew for subscriber" do
@@ -235,6 +260,37 @@ class SpreedlyGemTest < Test::Unit::TestCase
235
260
  end
236
261
  end
237
262
 
263
+ context "adding fees" do
264
+
265
+ setup do
266
+ @regular_plan = Spreedly::SubscriptionPlan.all.detect{|e| e.name == "Test Regular Plan"}
267
+ assert @regular_plan, "For this test to pass in REAL mode you must have a regular plan in your Spreedly test site with the name \"Test Regular Plan\". It must be an auto-recurring plan."
268
+ end
269
+
270
+ should "be able to add fee to user" do
271
+ sub = create_subscriber
272
+ sub.subscribe(@regular_plan.id)
273
+ sub.add_fee(:name => "Daily Bandwidth Charge", :amount => "2.34", :description => "313 MB used", :group => "Traffic Fees")
274
+ end
275
+
276
+ should "throw an error when add fee to not active user" do
277
+ sub = create_subscriber
278
+ ex = assert_raise(RuntimeError) do
279
+ sub.add_fee(:name => "Daily Bandwidth Charge", :amount => "2.34", :description => "313 MB used", :group => "Traffic Fees")
280
+ end
281
+ assert_match %r{Unprocessable Entity}, ex.message
282
+ end
283
+
284
+ should "throw an error when add fee with incomplete arguments" do
285
+ sub = create_subscriber
286
+ sub.subscribe(@regular_plan.id)
287
+ ex = assert_raise(RuntimeError) do
288
+ sub.add_fee(:name => "Daily Bandwidth Charge", :description => "313 MB used", :group => "Traffic Fees")
289
+ end
290
+ assert_match %r{Unprocessable Entity}, ex.message
291
+ end
292
+ end
293
+
238
294
  should "throw an error if stopping auto renew on a non-existent subscriber" do
239
295
  sub = Spreedly::Subscriber.new('customer_id' => 'bogus')
240
296
  ex = assert_raise(RuntimeError){sub.stop_auto_renew}
@@ -244,9 +300,9 @@ class SpreedlyGemTest < Test::Unit::TestCase
244
300
  only_real do
245
301
  should "throw an error if comp is wrong type" do
246
302
  sub = create_subscriber
247
- sub.comp(1, 'days')
303
+ sub.comp(1, 'days', 'something')
248
304
  ex = assert_raise(RuntimeError) do
249
- sub.comp(1, 'days')
305
+ sub.comp(1, 'days', 'something')
250
306
  end
251
307
  assert_match(/invalid/i, ex.message)
252
308
  end
@@ -256,4 +312,4 @@ class SpreedlyGemTest < Test::Unit::TestCase
256
312
  def create_subscriber(id=(rand*100000000).to_i, email=nil, screen_name=nil)
257
313
  Spreedly::Subscriber.create!(id, email, screen_name)
258
314
  end
259
- end
315
+ end
data/test/test_site.yml CHANGED
@@ -1,2 +1,2 @@
1
- name: terralien-test
2
- token: 781651cf01c65b7f0c8f6565723ea60436e87a56
1
+ name: spreedlygem
2
+ token: 44c633ef5522564f40a117c009ecb6852c0ce3f3
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spreedly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 3
9
+ - 2
10
+ version: 1.3.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Nathaniel Talbott
@@ -9,39 +15,69 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-09-11 00:00:00 -04:00
18
+ date: 2010-06-04 00:00:00 -04:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: mechanize
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
- version:
33
+ type: :runtime
34
+ version_requirements: *id001
25
35
  - !ruby/object:Gem::Dependency
26
- name: thoughtbot-shoulda
36
+ name: rubyforge
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 7
44
+ segments:
45
+ - 2
46
+ - 0
47
+ - 4
48
+ version: 2.0.4
27
49
  type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: shoulda
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
30
56
  requirements:
31
57
  - - ">="
32
58
  - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
33
62
  version: "0"
34
- version:
63
+ type: :development
64
+ version_requirements: *id003
35
65
  - !ruby/object:Gem::Dependency
36
66
  name: hoe
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
40
70
  requirements:
41
71
  - - ">="
42
72
  - !ruby/object:Gem::Version
43
- version: 2.3.3
44
- version:
73
+ hash: 23
74
+ segments:
75
+ - 2
76
+ - 6
77
+ - 0
78
+ version: 2.6.0
79
+ type: :development
80
+ version_requirements: *id004
45
81
  description: |-
46
82
  The Spreedly gem provides a convenient Ruby wrapper for the goodness that is
47
83
  the http://spreedly.com API. Created by Terralien[http://terralien.com].
@@ -135,21 +171,27 @@ rdoc_options:
135
171
  require_paths:
136
172
  - lib
137
173
  required_ruby_version: !ruby/object:Gem::Requirement
174
+ none: false
138
175
  requirements:
139
176
  - - ">="
140
177
  - !ruby/object:Gem::Version
178
+ hash: 3
179
+ segments:
180
+ - 0
141
181
  version: "0"
142
- version:
143
182
  required_rubygems_version: !ruby/object:Gem::Requirement
183
+ none: false
144
184
  requirements:
145
185
  - - ">="
146
186
  - !ruby/object:Gem::Version
187
+ hash: 3
188
+ segments:
189
+ - 0
147
190
  version: "0"
148
- version:
149
191
  requirements: []
150
192
 
151
193
  rubyforge_project: terralien
152
- rubygems_version: 1.3.5
194
+ rubygems_version: 1.3.7
153
195
  signing_key:
154
196
  specification_version: 3
155
197
  summary: The Spreedly gem provides a convenient Ruby wrapper for the goodness that is the http://spreedly.com API