freemium-ajb 0.0.4
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/.coveralls.yml +1 -0
- data/.gitignore +27 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.md +20 -0
- data/README.md +1 -0
- data/app/mailers/freemium_mailer.rb +36 -0
- data/app/views/subscription_mailer/admin_report.text.erb +4 -0
- data/app/views/subscription_mailer/expiration_notice.text.erb +1 -0
- data/app/views/subscription_mailer/expiration_warning.text.erb +1 -0
- data/app/views/subscription_mailer/invoice.text.erb +5 -0
- data/freemium.gemspec +29 -0
- data/lib/freemium.rb +25 -0
- data/lib/freemium/configuration.rb +27 -0
- data/lib/freemium/coupon.rb +37 -0
- data/lib/freemium/coupon_redemption.rb +59 -0
- data/lib/freemium/credit_card.rb +222 -0
- data/lib/freemium/engine.rb +7 -0
- data/lib/freemium/gateways/base.rb +65 -0
- data/lib/freemium/gateways/brain_tree.rb +175 -0
- data/lib/freemium/gateways/test.rb +36 -0
- data/lib/freemium/rates.rb +33 -0
- data/lib/freemium/response.rb +24 -0
- data/lib/freemium/subscription.rb +384 -0
- data/lib/freemium/subscription_change.rb +20 -0
- data/lib/freemium/subscription_plan.rb +26 -0
- data/lib/freemium/testing/app/controllers/application_controller.rb +7 -0
- data/lib/freemium/testing/application.rb +46 -0
- data/lib/freemium/testing/config/database.yml +11 -0
- data/lib/freemium/testing/config/routes.rb +3 -0
- data/lib/freemium/transaction.rb +15 -0
- data/lib/freemium/version.rb +3 -0
- data/lib/generators/freemium/install/install_generator.rb +58 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_coupon_redemptions.rb +18 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_coupons.rb +28 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_credit_cards.rb +14 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_subscription_changes.rb +21 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_subscription_plans.rb +14 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_subscriptions.rb +31 -0
- data/lib/generators/freemium/install/templates/db/migrate/create_transactions.rb +17 -0
- data/lib/generators/freemium/install/templates/freemium.rb +16 -0
- data/lib/generators/freemium/install/templates/models/coupon.rb +3 -0
- data/lib/generators/freemium/install/templates/models/coupon_redemption.rb +3 -0
- data/lib/generators/freemium/install/templates/models/credit_card.rb +3 -0
- data/lib/generators/freemium/install/templates/models/subscription.rb +3 -0
- data/lib/generators/freemium/install/templates/models/subscription_change.rb +3 -0
- data/lib/generators/freemium/install/templates/models/subscription_plan.rb +3 -0
- data/lib/generators/freemium/install/templates/models/transaction.rb +3 -0
- data/lib/generators/views/USAGE +3 -0
- data/lib/generators/views/views_generator.rb +39 -0
- data/lib/tasks/freemium.rake +17 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/mailers.rb +1 -0
- data/spec/dummy/app/models/models.rb +31 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +45 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +21 -0
- data/spec/dummy/config/environment.rb +6 -0
- data/spec/dummy/config/environments/development.rb +26 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/freemium.rb +16 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mem_db.rb +12 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/db/schema.rb +90 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/fixtures/credit_cards.yml +11 -0
- data/spec/fixtures/subscription_plans.yml +15 -0
- data/spec/fixtures/subscriptions.yml +28 -0
- data/spec/fixtures/users.yml +16 -0
- data/spec/lib/tasks/run_billing_rake_spec.rb +14 -0
- data/spec/models/coupon_redemption_spec.rb +287 -0
- data/spec/models/credit_card_spec.rb +124 -0
- data/spec/models/manual_billing_spec.rb +165 -0
- data/spec/models/subscription_plan_spec.rb +46 -0
- data/spec/models/subscription_spec.rb +386 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/helpers.rb +18 -0
- data/spec/support/shared_contexts/rake.rb +19 -0
- metadata +270 -0
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
bobs_credit_card:
|
2
|
+
id: 1
|
3
|
+
expiration_date: <%= (Time.now + 3.years).to_s :db %>
|
4
|
+
display_number: xxxx-xxxx-xxxx-2222
|
5
|
+
card_type: master
|
6
|
+
steves_credit_card:
|
7
|
+
id: 2
|
8
|
+
expiration_date: <%= (Time.now + 3.years).to_s :db %>
|
9
|
+
display_number: xxxx-xxxx-xxxx-1111
|
10
|
+
card_type: visa
|
11
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
bobs_subscription:
|
2
|
+
id: 1
|
3
|
+
subscribable_id: 1
|
4
|
+
subscribable_type: User
|
5
|
+
subscription_plan_id: 2
|
6
|
+
credit_card_id: 1
|
7
|
+
paid_through: <%= (Date.today + 20).to_s :db %>
|
8
|
+
billing_key: tc00001
|
9
|
+
started_on: <%= (Date.today - 60).to_s :db %>
|
10
|
+
last_transaction_at: 2007-09-15 12:34:56
|
11
|
+
sues_subscription:
|
12
|
+
id: 2
|
13
|
+
subscribable_id: 2
|
14
|
+
subscribable_type: User
|
15
|
+
subscription_plan_id: 1
|
16
|
+
paid_through:
|
17
|
+
last_transaction_at:
|
18
|
+
started_on: <%= (Date.today - 60).to_s :db %>
|
19
|
+
steves_subscription:
|
20
|
+
id: 3
|
21
|
+
subscribable_id: 4
|
22
|
+
subscribable_type: User
|
23
|
+
subscription_plan_id: 3
|
24
|
+
credit_card_id: 1
|
25
|
+
paid_through: <%= (Date.today + 20).to_s :db %>
|
26
|
+
billing_key: tc00002
|
27
|
+
started_on: <%= (Date.today - 60).to_s :db %>
|
28
|
+
last_transaction_at: 2007-09-15 12:34:56
|
@@ -0,0 +1,287 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CouponRedemption do
|
4
|
+
fixtures :users, :subscriptions, :subscription_plans, :credit_cards
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@subscription = subscriptions(:bobs_subscription)
|
8
|
+
@original_price = @subscription.rate
|
9
|
+
@coupon = Coupon.create(:description => "30% off", :discount_percentage => 30, :redemption_key => "30OFF")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be applied" do
|
13
|
+
@subscription.paid_through = Date.today + 30
|
14
|
+
@original_remaining_value = @subscription.remaining_value
|
15
|
+
@original_daily_rate = @subscription.daily_rate
|
16
|
+
@subscription.coupon_key = nil
|
17
|
+
|
18
|
+
@subscription.coupon_redemptions.create(:coupon => @coupon).should be_true
|
19
|
+
@subscription.rate.cents.should eql(@coupon.discount(@original_price).cents)
|
20
|
+
@subscription.daily_rate.cents.should eql(@coupon.discount(@original_daily_rate).cents)
|
21
|
+
@subscription.remaining_value.cents.should eql((@coupon.discount(@original_daily_rate) * @subscription.remaining_days).cents)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be applied using coupon accessor" do
|
25
|
+
@subscription = build_subscription(:coupon => @coupon, :credit_card => CreditCard.sample)
|
26
|
+
@subscription.save!
|
27
|
+
|
28
|
+
@subscription.coupon.should_not be_nil
|
29
|
+
@subscription.coupon_redemptions.first.coupon.should_not be_nil
|
30
|
+
@subscription.coupon_redemptions.first.subscription.should_not be_nil
|
31
|
+
@subscription.coupon_redemptions.empty?.should be_false
|
32
|
+
@subscription.rate.cents.should eql(@coupon.discount(@subscription.subscription_plan.rate).cents)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be applied using coupon key accessor" do
|
36
|
+
@subscription = build_subscription(:coupon_key => @coupon.redemption_key, :credit_card => CreditCard.sample)
|
37
|
+
@subscription.save!
|
38
|
+
|
39
|
+
@subscription.coupon.should_not be_nil
|
40
|
+
@subscription.coupon_redemptions.first.coupon.should_not be_nil
|
41
|
+
@subscription.coupon_redemptions.first.subscription.should_not be_nil
|
42
|
+
@subscription.coupon_redemptions.empty?.should be_false
|
43
|
+
@subscription.rate.cents.should eql(@coupon.discount(@subscription.subscription_plan.rate).cents)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should be applied multiple" do
|
47
|
+
@coupon_1 = Coupon.new(:description => "10% off", :discount_percentage => 10)
|
48
|
+
@subscription.coupon_redemptions.create(:coupon => @coupon_1).should be_true
|
49
|
+
|
50
|
+
@coupon_2 = Coupon.new(:description => "30% off", :discount_percentage => 30)
|
51
|
+
@subscription.coupon_redemptions.create(:coupon => @coupon_2).should be_true
|
52
|
+
|
53
|
+
@coupon_3 = Coupon.new(:description => "20% off", :discount_percentage => 20)
|
54
|
+
@subscription.coupon_redemptions.create(:coupon => @coupon_3).should be_true
|
55
|
+
|
56
|
+
# Should use the highest discounted coupon
|
57
|
+
@subscription.rate.cents.should eql(@coupon_2.discount(@original_price).cents)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be destroyed" do
|
61
|
+
@subscription.coupon_redemptions.create(:coupon => @coupon).should be_true
|
62
|
+
@subscription.rate.cents.should eql(@coupon.discount(@original_price).cents)
|
63
|
+
|
64
|
+
@coupon.destroy
|
65
|
+
@subscription.reload
|
66
|
+
|
67
|
+
@subscription.coupon_redemptions.empty?.should be_true
|
68
|
+
@subscription.rate.cents.should eql(@original_price.cents)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should test coupon duration" do
|
72
|
+
@subscription.coupon_redemptions.create(:coupon => @coupon).should be_true
|
73
|
+
@subscription.rate.cents.should eql(@coupon.discount(@original_price).cents)
|
74
|
+
|
75
|
+
@coupon.duration_in_months = 3
|
76
|
+
@coupon.save!
|
77
|
+
|
78
|
+
@subscription.rate({:date => (Date.today + 3.months - 1)}).cents.should eql(@coupon.discount(@original_price).cents)
|
79
|
+
@subscription.rate({:date => (Date.today + 3.months + 1)}).cents.should eql(@original_price.cents)
|
80
|
+
|
81
|
+
safe_date = Date.today + 3.months - 1
|
82
|
+
Date.stub!(:today => safe_date)
|
83
|
+
@subscription.rate.cents.should eql(@coupon.discount(@original_price).cents)
|
84
|
+
|
85
|
+
safe_date = Date.today + 1
|
86
|
+
Date.stub!(:today => safe_date)
|
87
|
+
@subscription.rate.cents.should eql(@coupon.discount(@original_price).cents)
|
88
|
+
|
89
|
+
safe_date = Date.today + 1
|
90
|
+
Date.stub!(:today => safe_date)
|
91
|
+
@subscription.rate.cents.should eql(@original_price.cents)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should be applied complimentary" do
|
95
|
+
@coupon.discount_percentage = 100
|
96
|
+
|
97
|
+
@subscription = build_subscription(:coupon => @coupon, :credit_card => CreditCard.sample, :subscription_plan => subscription_plans(:premium))
|
98
|
+
|
99
|
+
@subscription.save.should be_true
|
100
|
+
@subscription.coupon.should_not be_nil
|
101
|
+
@subscription.rate.cents.should eql(0)
|
102
|
+
@subscription.paid?.should be_false
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
## Plan-specific coupons
|
107
|
+
##
|
108
|
+
|
109
|
+
it "should be applied only on new premium plan" do
|
110
|
+
set_coupon_to_premium_only
|
111
|
+
|
112
|
+
@subscription = build_subscription(:coupon => @coupon, :credit_card => CreditCard.sample,
|
113
|
+
:subscription_plan => subscription_plans(:premium))
|
114
|
+
|
115
|
+
@subscription.save.should be_true
|
116
|
+
@subscription.coupon.should_not be_nil
|
117
|
+
|
118
|
+
@subscription = build_subscription(:coupon => @coupon, :credit_card => CreditCard.sample,
|
119
|
+
:subscription_plan => subscription_plans(:basic))
|
120
|
+
|
121
|
+
@subscription.save.should be_false
|
122
|
+
@subscription.should have(1).errors_on(:coupon_redemptions)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should be applied only on existent premium plan" do
|
126
|
+
set_coupon_to_premium_only
|
127
|
+
|
128
|
+
@subscription.coupon = @coupon
|
129
|
+
|
130
|
+
@subscription.subscription_plan.should eql(subscription_plans(:basic))
|
131
|
+
@subscription.save.should be_false
|
132
|
+
@subscription.should have(1).errors_on(:coupon_redemptions)
|
133
|
+
|
134
|
+
@subscription.subscription_plan = subscription_plans(:premium)
|
135
|
+
|
136
|
+
@subscription.subscription_plan.should eql(subscription_plans(:premium))
|
137
|
+
@subscription.save.should be_true
|
138
|
+
@subscription.coupon.should_not be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should automatically upgrade the plan, as long as discount percentage is 100%" do
|
142
|
+
hundred_coupon = Coupon.create(:description => "100% off", :discount_percentage => 100, :redemption_key => "100OFF")
|
143
|
+
hundred_coupon.subscription_plans << subscription_plans(:premium)
|
144
|
+
|
145
|
+
@subscription.coupon = hundred_coupon
|
146
|
+
|
147
|
+
@subscription.subscription_plan.should eql(subscription_plans(:premium))
|
148
|
+
@subscription.save.should be_true
|
149
|
+
@subscription.rate.cents.should eql(0)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should not automatically downgrade the plan, no matter what" do
|
153
|
+
@subscription.subscription_plan = subscription_plans(:premium)
|
154
|
+
|
155
|
+
hundred_coupon = Coupon.create(:description => "100% off", :discount_percentage => 100, :redemption_key => "100OFF")
|
156
|
+
hundred_coupon.subscription_plans << subscription_plans(:basic)
|
157
|
+
|
158
|
+
@subscription.coupon = hundred_coupon
|
159
|
+
|
160
|
+
@subscription.subscription_plan.should eql(subscription_plans(:premium))
|
161
|
+
@subscription.save.should be_false
|
162
|
+
@subscription.should have(1).errors_on(:coupon_redemptions)
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should remove the coupon when upgrading the subscription plan' do
|
166
|
+
@subscription.subscription_plan = subscription_plans(:free)
|
167
|
+
|
168
|
+
hundred_coupon = Coupon.create(:description => "100% off", :discount_percentage => 100, :redemption_key => "100OFF")
|
169
|
+
hundred_coupon.subscription_plans << subscription_plans(:basic)
|
170
|
+
|
171
|
+
@subscription.coupon = hundred_coupon
|
172
|
+
|
173
|
+
@subscription.subscription_plan.should eql(subscription_plans(:basic))
|
174
|
+
@subscription.save.should be_true
|
175
|
+
@subscription.rate.cents.should eql(0)
|
176
|
+
|
177
|
+
cc = CreditCard.sample
|
178
|
+
cc.save
|
179
|
+
|
180
|
+
@subscription.update_attributes(
|
181
|
+
subscription_plan_id: subscription_plans(:premium).id,
|
182
|
+
credit_card: cc
|
183
|
+
)
|
184
|
+
|
185
|
+
@subscription.reload
|
186
|
+
|
187
|
+
@subscription.credit_card.should eql(cc)
|
188
|
+
@subscription.rate.cents.should_not eql(0)
|
189
|
+
@subscription.paid_through.should_not eql(nil)
|
190
|
+
@subscription.coupon.should eql(nil)
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
## applying coupons
|
195
|
+
##
|
196
|
+
|
197
|
+
it "should be applied to subscription" do
|
198
|
+
@subscription.coupon = @coupon
|
199
|
+
@subscription.should be_valid
|
200
|
+
@subscription.coupon.should_not be_nil
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should validate coupon key" do
|
204
|
+
@subscription.coupon_key = @coupon.redemption_key + "xxxxx"
|
205
|
+
|
206
|
+
@subscription.should_not be_valid
|
207
|
+
@subscription.coupon.should be_nil
|
208
|
+
@subscription.should have(1).errors_on(:coupon)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should validate coupon by coupon plan" do
|
212
|
+
set_coupon_to_premium_only
|
213
|
+
|
214
|
+
@subscription.subscription_plan.should_not eql(subscription_plans(:premium))
|
215
|
+
|
216
|
+
@subscription.coupon = @coupon
|
217
|
+
@subscription.should_not be_valid
|
218
|
+
@subscription.should have(1).errors_on(:coupon_redemptions)
|
219
|
+
end
|
220
|
+
|
221
|
+
protected
|
222
|
+
|
223
|
+
def set_coupon_to_premium_only
|
224
|
+
@coupon.subscription_plans << subscription_plans(:premium)
|
225
|
+
@coupon.save!
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
public
|
230
|
+
|
231
|
+
##
|
232
|
+
## Validation Tests
|
233
|
+
##
|
234
|
+
|
235
|
+
it "should validate coupon" do
|
236
|
+
s = CouponRedemption.new(:subscription => subscriptions(:bobs_subscription))
|
237
|
+
s.save.should be_false
|
238
|
+
s.should have(1).errors_on(:coupon)
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should not be applied to unpaid subscription" do
|
242
|
+
subscriptions(:sues_subscription).paid?.should be_false
|
243
|
+
s = CouponRedemption.new(:subscription => subscriptions(:sues_subscription), :coupon => @coupon)
|
244
|
+
s.save.should be_false
|
245
|
+
s.should have(1).errors_on(:subscription)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should not be applied twice" do
|
249
|
+
s = CouponRedemption.new(:subscription => subscriptions(:bobs_subscription), :coupon => @coupon)
|
250
|
+
s.save.should be_true
|
251
|
+
|
252
|
+
s = CouponRedemption.new(:subscription => subscriptions(:bobs_subscription), :coupon => @coupon)
|
253
|
+
s.save.should be_false
|
254
|
+
s.should have(1).errors_on(:coupon_id)
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should not be applied with redemption expired coupon" do
|
258
|
+
@coupon.redemption_expiration = Date.today-1
|
259
|
+
@coupon.save!
|
260
|
+
|
261
|
+
s = CouponRedemption.new(:subscription => subscriptions(:bobs_subscription), :coupon => @coupon)
|
262
|
+
s.save.should be_false
|
263
|
+
s.should have(1).errors_on(:coupon)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should not be applied with too many redemptions" do
|
267
|
+
@coupon.redemption_limit = 1
|
268
|
+
@coupon.save!
|
269
|
+
|
270
|
+
s = CouponRedemption.new(:subscription => subscriptions(:bobs_subscription), :coupon => @coupon)
|
271
|
+
s.save!
|
272
|
+
|
273
|
+
s = CouponRedemption.new(:subscription => subscriptions(:steves_subscription), :coupon => @coupon)
|
274
|
+
s.save.should be_false
|
275
|
+
s.should have(1).errors_on(:coupon)
|
276
|
+
end
|
277
|
+
|
278
|
+
protected
|
279
|
+
|
280
|
+
def build_subscription(options = {})
|
281
|
+
Subscription.new({
|
282
|
+
:subscription_plan => subscription_plans(:basic),
|
283
|
+
:subscribable => users(:sue)
|
284
|
+
}.merge(options))
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CreditCard do
|
4
|
+
fixtures :users, :subscriptions, :subscription_plans, :credit_cards
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@subscription = Subscription.new(:subscription_plan => subscription_plans(:premium), :subscribable => users(:sally))
|
8
|
+
@credit_card = CreditCard.create(CreditCard.sample_params.merge(:subscription => @subscription))
|
9
|
+
Freemium.configuration.gateway = Freemium::Gateways::Test.new
|
10
|
+
Freemium.configuration.gateway.username = 'demo'
|
11
|
+
Freemium.configuration.gateway.password = 'password'
|
12
|
+
|
13
|
+
Freemium.configuration.gateway.stub!(:validate => Freemium::Response.new(true))
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create" do
|
17
|
+
@subscription.credit_card = @credit_card
|
18
|
+
|
19
|
+
@subscription.save.should be_true
|
20
|
+
@subscription = Subscription.find(@subscription.id)
|
21
|
+
@subscription.billing_key.should_not be_nil
|
22
|
+
@subscription.credit_card.display_number.should_not be_nil
|
23
|
+
@subscription.credit_card.card_type.should_not be_nil
|
24
|
+
@subscription.credit_card.expiration_date.should_not be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be created with billing validation failure" do
|
28
|
+
response = Freemium::Response.new(false, 'responsetext' => 'FAILED')
|
29
|
+
response.message = 'FAILED'
|
30
|
+
Freemium.configuration.gateway.stub!(:validate => response)
|
31
|
+
|
32
|
+
@subscription.credit_card = @credit_card
|
33
|
+
|
34
|
+
@subscription.save.should be_false
|
35
|
+
@subscription.should have(1).errors_on(:base)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should be updated" do
|
39
|
+
@subscription.credit_card = @credit_card
|
40
|
+
|
41
|
+
@subscription.save.should be_true
|
42
|
+
@subscription = Subscription.find(@subscription.id)
|
43
|
+
@subscription.billing_key.should_not be_nil
|
44
|
+
|
45
|
+
original_key = @subscription.billing_key
|
46
|
+
original_expiration = @subscription.credit_card.expiration_date
|
47
|
+
|
48
|
+
@subscription.credit_card = CreditCard.new(CreditCard.sample_params.merge(:zip_code => 95060, :number => "5431111111111111", :card_type => "master", :year => 2020))
|
49
|
+
@subscription.save.should be_true
|
50
|
+
@subscription = Subscription.find(@subscription.id)
|
51
|
+
@subscription.billing_key.should eql(original_key)
|
52
|
+
original_expiration.should < @subscription.credit_card.expiration_date
|
53
|
+
@subscription.credit_card.reload.zip_code.should eql("95060")
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
## Test Validations
|
58
|
+
##
|
59
|
+
|
60
|
+
it "should validate card number" do
|
61
|
+
@credit_card.number = "foo"
|
62
|
+
@credit_card.should_not be_valid
|
63
|
+
@credit_card.save.should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should validate expiration date of card" do
|
67
|
+
@credit_card.year = 2001
|
68
|
+
@credit_card.should_not be_valid
|
69
|
+
@credit_card.save.should be_false
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should be changed" do
|
73
|
+
# We're overriding AR#changed? to include instance vars that aren't persisted to see if a new card is being set
|
74
|
+
@credit_card.changed?.should be_true #New card is changed
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should be changed after reload" do
|
78
|
+
@credit_card.save!
|
79
|
+
@credit_card = CreditCard.find(@credit_card.id)
|
80
|
+
@credit_card.reload.changed?.should be_false #Saved card is NOT changed
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should not be chanegd for existent card" do
|
84
|
+
credit_cards(:bobs_credit_card).changed?.should be_false
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should be chnaged after update" do
|
88
|
+
credit_cards(:bobs_credit_card).number = "foo"
|
89
|
+
credit_cards(:bobs_credit_card).changed?.should be_true
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be valid" do
|
93
|
+
@credit_card.should be_valid #New card is valid
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should be valid and unchanged for existent cards" do
|
97
|
+
# existing cards on file are valid ...
|
98
|
+
credit_cards(:bobs_credit_card).changed?.should be_false #Existing card has not changed
|
99
|
+
credit_cards(:bobs_credit_card).should be_valid #Existing card is valid
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should validate number of existent card" do
|
103
|
+
# ... unless theres an attempt to update them
|
104
|
+
credit_cards(:bobs_credit_card).number = "foo"
|
105
|
+
credit_cards(:bobs_credit_card).should_not be_valid #Partially changed existing card is not valid
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should validate card type of existent card" do
|
109
|
+
# ... unless theres an attempt to update them
|
110
|
+
credit_cards(:bobs_credit_card).card_type = "visa"
|
111
|
+
credit_cards(:bobs_credit_card).should_not be_valid #Partially changed existing card is not valid
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should automatically determine card type" do
|
115
|
+
c = CreditCard.create(number: '4111111111111111', month: '2', year: '2013')
|
116
|
+
c.valid?
|
117
|
+
c.card_type.should eql(:visa)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should not choke when there is no expiration date provided' do
|
121
|
+
c = CreditCard.new(number: '4111111111111111')
|
122
|
+
c.valid?.should eql(false)
|
123
|
+
end
|
124
|
+
end
|