spreedly 1.3.1 → 1.3.2

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