saucy 0.13.3 → 0.14.0
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/CHANGELOG.md +4 -0
- data/app/controllers/billings_controller.rb +7 -0
- data/app/models/signup.rb +9 -2
- data/app/views/billings/_form.html.erb +12 -2
- data/features/run_features.feature +1 -0
- data/lib/generators/saucy/features/templates/factories.rb +5 -0
- data/lib/generators/saucy/features/templates/features/manage_billing.feature +41 -26
- data/lib/generators/saucy/features/templates/features/manage_plan.feature +16 -5
- data/lib/generators/saucy/features/templates/features/sign_up_paid.feature +18 -0
- data/lib/generators/saucy/features/templates/features/trial_plans.feature +0 -9
- data/lib/generators/saucy/features/templates/step_definitions/country_steps.rb +8 -0
- data/lib/saucy/subscription.rb +38 -13
- data/spec/models/subscription_spec.rb +105 -91
- metadata +4 -53
data/CHANGELOG.md
CHANGED
@@ -12,6 +12,13 @@ class BillingsController < ApplicationController
|
|
12
12
|
@account.billing_email = @account.customer.email
|
13
13
|
@account.expiration_month = @account.credit_card.expiration_month
|
14
14
|
@account.expiration_year = @account.credit_card.expiration_year
|
15
|
+
|
16
|
+
@account.street_address = @account.billing_address.street_address
|
17
|
+
@account.extended_address = @account.billing_address.extended_address
|
18
|
+
@account.locality = @account.billing_address.locality
|
19
|
+
@account.region = @account.billing_address.region
|
20
|
+
@account.postal_code = @account.billing_address.postal_code
|
21
|
+
@account.country_name = @account.billing_address.country_name
|
15
22
|
end
|
16
23
|
|
17
24
|
def update
|
data/app/models/signup.rb
CHANGED
@@ -13,7 +13,13 @@ class Signup
|
|
13
13
|
:expiration_month => :expiration_month,
|
14
14
|
:expiration_year => :expiration_year,
|
15
15
|
:verification_code => :verification_code,
|
16
|
-
:plan => :plan
|
16
|
+
:plan => :plan,
|
17
|
+
:street_address => :street_address,
|
18
|
+
:extended_address => :extended_address,
|
19
|
+
:locality => :locality,
|
20
|
+
:region => :region,
|
21
|
+
:postal_code => :postal_code,
|
22
|
+
:country_name => :country_name
|
17
23
|
},
|
18
24
|
:user => {
|
19
25
|
:email => :email,
|
@@ -22,7 +28,8 @@ class Signup
|
|
22
28
|
}.freeze
|
23
29
|
|
24
30
|
attr_accessor :billing_email, :password, :cardholder_name, :email,
|
25
|
-
:card_number, :expiration_month, :expiration_year, :plan, :verification_code, :coupon
|
31
|
+
:card_number, :expiration_month, :expiration_year, :plan, :verification_code, :coupon,
|
32
|
+
:street_address, :extended_address, :locality, :region, :postal_code, :country_name
|
26
33
|
|
27
34
|
def initialize(attributes = {})
|
28
35
|
if attributes
|
@@ -1,8 +1,18 @@
|
|
1
1
|
<%= form.inputs do %>
|
2
|
-
<%= form.input :cardholder_name, :required => true %>
|
3
|
-
<%= form.input :billing_email, :required => true, :hint => "We'll send receipts and billing issues to this address." %>
|
4
2
|
<%= form.input :card_number, :required => true, :input_html => { :autocomplete => "off" } %>
|
5
3
|
<%= form.input :verification_code, :required => true, :input_html => { :autocomplete => "off" } %>
|
6
4
|
<%= form.input :expiration_month, :collection => [['January', '01'], ['February', '02'], ['March', '03'], ['April', '04'], ['May', '05'], ['June', '06'], ['July', '07'], ['August', '08'], ['September', '09'], ['October', '10'], ['November', '11'], ['December', '12']], :required => true %>
|
7
5
|
<%= form.input :expiration_year, :collection => (Date.today.year..(Date.today.year+10)).to_a, :required => true %>
|
6
|
+
<%= form.input :cardholder_name, :required => true %>
|
7
|
+
<%= form.input :billing_email, :required => true, :hint => "We'll send receipts and billing issues to this address." %>
|
8
|
+
|
9
|
+
<%= form.input :street_address, :label => "Address Line 1", :required => true %>
|
10
|
+
<%= form.input :extended_address, :label => "Address Line 2", :required => true %>
|
11
|
+
<%= form.input :locality, :label => "City", :required => true %>
|
12
|
+
<%= form.input :region, :label => "State or Province", :required => true %>
|
13
|
+
<%= form.input :postal_code, :label => "ZIP or Postal Code", :required => true %>
|
14
|
+
<%= form.input :country_name, :label => "Country",
|
15
|
+
:required => true,
|
16
|
+
:collection => ["United States of America", "Canada", "---",
|
17
|
+
*Braintree::Address::CountryNames.map(&:first)] %>
|
8
18
|
<% end -%>
|
@@ -20,6 +20,7 @@ Feature: generate a saucy application and run rake
|
|
20
20
|
gem "launchy"
|
21
21
|
gem "timecop"
|
22
22
|
gem "jquery-rails"
|
23
|
+
gem "minitest", "~> 2.6.1", :platforms => :ruby_19
|
23
24
|
"""
|
24
25
|
When I add the "saucy" gem from this project as a dependency
|
25
26
|
And I successfully run `bundle install`
|
@@ -25,6 +25,11 @@ Factory.define :paid_account, :parent => :account do |f|
|
|
25
25
|
f.verification_code { "123" }
|
26
26
|
f.expiration_month { 5 }
|
27
27
|
f.expiration_year { 2012 }
|
28
|
+
f.street_address { "1 Robo Lane" }
|
29
|
+
f.locality { "Boston" }
|
30
|
+
f.region { "MA" }
|
31
|
+
f.postal_code { "02108" }
|
32
|
+
f.country_name { "United States of America" }
|
28
33
|
f.association :plan, :factory => :paid_plan
|
29
34
|
end
|
30
35
|
|
@@ -3,12 +3,14 @@ Feature: Manage Billing
|
|
3
3
|
I want to be able to manage my billing information
|
4
4
|
So that my account can stay up to date and in good standing
|
5
5
|
|
6
|
-
|
6
|
+
Background:
|
7
7
|
Given a paid plan exists with a name of "Paid"
|
8
8
|
And the following account exists:
|
9
|
-
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
10
|
-
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
11
|
-
|
9
|
+
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year | street_address | extended_address | locality | region | postal_code | country_name |
|
10
|
+
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 | 1 Robo Lane | Suite 333 | Beverly Hills | CA | 90210 | United States of America |
|
11
|
+
|
12
|
+
Scenario: Update the billing information on an account with a paid plan
|
13
|
+
Given I have signed in with "joe@example.com"
|
12
14
|
And "joe@example.com" is an admin of the "Test" account
|
13
15
|
When I go to the billing page for the "Test" account
|
14
16
|
Then I should see "card ending in 5555"
|
@@ -21,23 +23,39 @@ Feature: Manage Billing
|
|
21
23
|
And the "Verification code" field should have nothing in it
|
22
24
|
And the "Expiration month" field should contain "01"
|
23
25
|
And the "Expiration year" field should contain "2015"
|
26
|
+
And the "Address Line 1" field should contain "1 Robo Lane"
|
27
|
+
And the "Address Line 2" field should contain "Suite 333"
|
28
|
+
And the "City" field should contain "Beverly Hills"
|
29
|
+
And the "State or Province" field should contain "CA"
|
30
|
+
And the "ZIP or Postal Code" field should contain "90210"
|
31
|
+
And the "Country" field should contain "United States of America"
|
24
32
|
|
25
|
-
|
33
|
+
When I fill in "Cardholder name" with "Ralph Robot"
|
26
34
|
And I fill in "Billing email" with "accounting@example.com"
|
27
35
|
And I fill in "Card number" with "4111111111111111"
|
28
36
|
And I fill in "Verification code" with "123"
|
29
37
|
And I select "March" from "Expiration month"
|
30
38
|
And I select "2020" from "Expiration year"
|
39
|
+
And I fill in "Address Line 1" with "41 Winter St"
|
40
|
+
And I fill in "Address Line 2" with "Floor 7"
|
41
|
+
And I fill in "City" with "Boston"
|
42
|
+
And I fill in "State or Province" with "MA"
|
43
|
+
And I fill in "ZIP or Postal Code" with "02108"
|
44
|
+
And I select "Uganda" from "Country"
|
31
45
|
And I press "Update"
|
32
46
|
Then I should see "updated successfully"
|
33
|
-
|
47
|
+
And I should see "card ending in 1111"
|
48
|
+
|
49
|
+
When I follow "Change"
|
50
|
+
Then the "Address Line 1" field should contain "41 Winter St"
|
51
|
+
And the "Address Line 2" field should contain "Floor 7"
|
52
|
+
And the "City" field should contain "Boston"
|
53
|
+
And the "State or Province" field should contain "MA"
|
54
|
+
And the "ZIP or Postal Code" field should contain "02108"
|
55
|
+
And the "Country" field should contain "Uganda"
|
34
56
|
|
35
57
|
Scenario: Be forced to update the billing information on an account with a paid plan that is past due
|
36
|
-
Given
|
37
|
-
And the following account exists:
|
38
|
-
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
39
|
-
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
40
|
-
And the "Test" account is past due
|
58
|
+
Given the "Test" account is past due
|
41
59
|
And I have signed in with "joe@example.com"
|
42
60
|
And "joe@example.com" is an admin of the "Test" account
|
43
61
|
When I go to the settings page for the "Test" account
|
@@ -45,11 +63,7 @@ Feature: Manage Billing
|
|
45
63
|
And I should see "There was an issue processing the credit card you have on file. Please update your credit card information."
|
46
64
|
|
47
65
|
Scenario: Be told to have an admin update the billing information on an account with a paid plan that is past due
|
48
|
-
Given
|
49
|
-
And the following account exists:
|
50
|
-
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
51
|
-
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
52
|
-
And the "Test" account is past due
|
66
|
+
Given the "Test" account is past due
|
53
67
|
And the following projects exist:
|
54
68
|
| name | account |
|
55
69
|
| Project | name: Test |
|
@@ -64,11 +78,7 @@ Feature: Manage Billing
|
|
64
78
|
Then I should be on the billing page for the "Test" account
|
65
79
|
|
66
80
|
Scenario: View past credit card charges
|
67
|
-
Given
|
68
|
-
And the following account exists:
|
69
|
-
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
70
|
-
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
71
|
-
And the following transaction exist for the "Test" account:
|
81
|
+
Given the following transaction exist for the "Test" account:
|
72
82
|
| status | amount | created_at |
|
73
83
|
| Settled | 20.00 | July 1, 2010 |
|
74
84
|
| Settled | 5.00 | August 1, 2010 |
|
@@ -80,14 +90,19 @@ Feature: Manage Billing
|
|
80
90
|
And I should see "08/01/10 $5"
|
81
91
|
|
82
92
|
Scenario: Navigate back to the main settings page
|
83
|
-
Given
|
84
|
-
And the following account exists:
|
85
|
-
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
86
|
-
| Test | test | name: Paid | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
87
|
-
And I have signed in with "joe@example.com"
|
93
|
+
Given I have signed in with "joe@example.com"
|
88
94
|
And "joe@example.com" is an admin of the "Test" account
|
89
95
|
When I go to the billing page for the "Test" account
|
90
96
|
And I follow "Change"
|
91
97
|
And I follow "Billing"
|
92
98
|
And I follow "Account Info"
|
93
99
|
Then I should be on the settings page for the "Test" account
|
100
|
+
|
101
|
+
Scenario: Billing countries
|
102
|
+
Given I have signed in with "joe@example.com"
|
103
|
+
And "joe@example.com" is an admin of the "Test" account
|
104
|
+
When I go to the billing page for the "Test" account
|
105
|
+
And I follow "Change"
|
106
|
+
Then I should see all the Braintree countries in the country select with the following at the top:
|
107
|
+
| United States of America |
|
108
|
+
| Canada |
|
@@ -6,7 +6,7 @@ Feature: Manage Plan
|
|
6
6
|
Scenario: Change the plan to another paid plan on an account with a paid plan
|
7
7
|
Given a paid plan exists with a name of "Basic"
|
8
8
|
And a paid plan exists with a name of "Premium"
|
9
|
-
And the following account exists:
|
9
|
+
And the following paid account exists:
|
10
10
|
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
11
11
|
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
12
12
|
And I have signed in with "joe@example.com"
|
@@ -37,13 +37,18 @@ Feature: Manage Plan
|
|
37
37
|
Then I should see "Upgrade Your Plan"
|
38
38
|
When I choose the "Basic" plan
|
39
39
|
Then I should see "Billing Information"
|
40
|
-
And I should not see "No thanks, just delete my account"
|
41
40
|
And I fill in "Cardholder name" with "Ralph Robot"
|
42
41
|
And I fill in "Billing email" with "accounting@example.com"
|
43
42
|
And I fill in "Card number" with "4111111111111111"
|
44
43
|
And I fill in "Verification code" with "123"
|
45
44
|
And I select "March" from "Expiration month"
|
46
45
|
And I select "2020" from "Expiration year"
|
46
|
+
And I fill in "Address Line 1" with "41 Winter St"
|
47
|
+
And I fill in "Address Line 2" with "Floor 7"
|
48
|
+
And I fill in "City" with "Boston"
|
49
|
+
And I fill in "State or Province" with "MA"
|
50
|
+
And I fill in "ZIP or Postal Code" with "02108"
|
51
|
+
And I select "United States of America" from "Country"
|
47
52
|
When I press "Upgrade"
|
48
53
|
Then I should see "Plan changed successfully"
|
49
54
|
And I should see "Basic"
|
@@ -71,6 +76,12 @@ Feature: Manage Plan
|
|
71
76
|
And I fill in "Verification code" with "123"
|
72
77
|
And I select "March" from "Expiration month"
|
73
78
|
And I select "2020" from "Expiration year"
|
79
|
+
And I fill in "Address Line 1" with "41 Winter St"
|
80
|
+
And I fill in "Address Line 2" with "Floor 7"
|
81
|
+
And I fill in "City" with "Boston"
|
82
|
+
And I fill in "State or Province" with "MA"
|
83
|
+
And I fill in "ZIP or Postal Code" with "02108"
|
84
|
+
And I select "United States of America" from "Country"
|
74
85
|
When I press "Upgrade"
|
75
86
|
Then I should not see "Plan changed successfully"
|
76
87
|
And "Card number" should have the error "is invalid"
|
@@ -78,7 +89,7 @@ Feature: Manage Plan
|
|
78
89
|
Scenario: Change the plan to a free on an account with a paid plan
|
79
90
|
Given a paid plan exists with a name of "Basic"
|
80
91
|
And a plan exists with a name of "Free"
|
81
|
-
And the following account exists:
|
92
|
+
And the following paid account exists:
|
82
93
|
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
83
94
|
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
84
95
|
And I have signed in with "joe@example.com"
|
@@ -97,7 +108,7 @@ Feature: Manage Plan
|
|
97
108
|
Scenario: Attempting to downgrade when beyond the limits
|
98
109
|
Given a paid plan exists with a name of "Basic"
|
99
110
|
And a plan exists with a name of "Free"
|
100
|
-
And the following account exists:
|
111
|
+
And the following paid account exists:
|
101
112
|
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
102
113
|
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
103
114
|
And the following limits exist:
|
@@ -127,7 +138,7 @@ Feature: Manage Plan
|
|
127
138
|
|
128
139
|
Scenario: Viewing current usage
|
129
140
|
Given a paid plan exists with a name of "Basic"
|
130
|
-
And the following account exists:
|
141
|
+
And the following paid account exists:
|
131
142
|
| name | keyword | plan | cardholder_name | billing_email | card_number | verification_code | expiration_month | expiration_year |
|
132
143
|
| Test | test | name: Basic | Joe Smith | jsmith@example.com | 4111111111115555 | 122 | 01 | 2015 |
|
133
144
|
And the following limits exist:
|
@@ -31,6 +31,12 @@ Feature: Sign up
|
|
31
31
|
And I fill in "Verification code" with "123"
|
32
32
|
And I select "March" from "Expiration month"
|
33
33
|
And I select "2020" from "Expiration year"
|
34
|
+
And I fill in "Address Line 1" with "123 Robo Lane"
|
35
|
+
And I fill in "Address Line 2" with "Suite 5"
|
36
|
+
And I fill in "City" with "Boston"
|
37
|
+
And I fill in "State or Province" with "MA"
|
38
|
+
And I fill in "ZIP or Postal Code" with "02110"
|
39
|
+
And I select "United States of America" from "Country"
|
34
40
|
And I press "Sign up"
|
35
41
|
Then I should see "created"
|
36
42
|
|
@@ -46,6 +52,12 @@ Feature: Sign up
|
|
46
52
|
And I fill in "Verification code" with "123"
|
47
53
|
And I select "March" from "Expiration month"
|
48
54
|
And I select "2020" from "Expiration year"
|
55
|
+
And I fill in "Address Line 1" with "123 Robo Lane"
|
56
|
+
And I fill in "Address Line 2" with "Suite 5"
|
57
|
+
And I fill in "City" with "Boston"
|
58
|
+
And I fill in "State or Province" with "MA"
|
59
|
+
And I fill in "ZIP or Postal Code" with "02110"
|
60
|
+
And I select "United States of America" from "Country"
|
49
61
|
And I press "Sign up"
|
50
62
|
Then "Card number" should have the error "is invalid"
|
51
63
|
|
@@ -61,5 +73,11 @@ Feature: Sign up
|
|
61
73
|
And I fill in "Verification code" with "123"
|
62
74
|
And I select "March" from "Expiration month"
|
63
75
|
And I select "2020" from "Expiration year"
|
76
|
+
And I fill in "Address Line 1" with "123 Robo Lane"
|
77
|
+
And I fill in "Address Line 2" with "Suite 5"
|
78
|
+
And I fill in "City" with "Boston"
|
79
|
+
And I fill in "State or Province" with "MA"
|
80
|
+
And I fill in "ZIP or Postal Code" with "02110"
|
81
|
+
And I select "United States of America" from "Country"
|
64
82
|
And I press "Sign up"
|
65
83
|
Then "Card number" should have the error "Do Not Honor"
|
@@ -37,15 +37,6 @@ Feature: Trial plans
|
|
37
37
|
And I should see "expired"
|
38
38
|
And the "Temp" plan should be disabled
|
39
39
|
|
40
|
-
Scenario: Delete an account with an expired plan
|
41
|
-
Given a "Temp" account exists with a name of "Test" created 30 days ago
|
42
|
-
And I am signed in as an admin of the "Test" account
|
43
|
-
When I go to the projects page for the "Test" account
|
44
|
-
Then I should be on the upgrade plan page for the "Test" account
|
45
|
-
And I should see "expired"
|
46
|
-
When I follow "No thanks, just delete my account"
|
47
|
-
Then I should see "Your account has been deleted"
|
48
|
-
|
49
40
|
Scenario: Sign up for a non-trial plan
|
50
41
|
When I go to the list of plans page
|
51
42
|
And I follow "Eternal"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Then /^I should see all the Braintree countries in the country select with the following at the top:$/ do |table|
|
2
|
+
divider = "---"
|
3
|
+
top_country_names = table.raw.flatten
|
4
|
+
all_country_names = Braintree::Address::CountryNames.map(&:first)
|
5
|
+
|
6
|
+
expected_country_names = [top_country_names, divider, all_country_names].flatten
|
7
|
+
page.should have_select("Country", :options => expected_country_names)
|
8
|
+
end
|
data/lib/saucy/subscription.rb
CHANGED
@@ -10,16 +10,28 @@ module Saucy
|
|
10
10
|
|
11
11
|
extend ActiveSupport::Memoizable
|
12
12
|
|
13
|
-
CUSTOMER_ATTRIBUTES =
|
14
|
-
:billing_email
|
15
|
-
:card_number
|
16
|
-
:expiration_month
|
17
|
-
:expiration_year
|
18
|
-
:verification_code
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
CUSTOMER_ATTRIBUTES = [ :cardholder_name,
|
14
|
+
:billing_email,
|
15
|
+
:card_number,
|
16
|
+
:expiration_month,
|
17
|
+
:expiration_year,
|
18
|
+
:verification_code,
|
19
|
+
:street_address,
|
20
|
+
:extended_address,
|
21
|
+
:locality,
|
22
|
+
:region,
|
23
|
+
:postal_code,
|
24
|
+
:country_name
|
25
|
+
]
|
26
|
+
|
27
|
+
OPTIONAL_CUSTOMER_ATTRIBUTES = [:extended_address]
|
28
|
+
|
29
|
+
REQUIRED_CUSTOMER_ATTRIBUTES =
|
30
|
+
CUSTOMER_ATTRIBUTES - OPTIONAL_CUSTOMER_ATTRIBUTES
|
31
|
+
|
32
|
+
attr_accessor *CUSTOMER_ATTRIBUTES
|
33
|
+
|
34
|
+
REQUIRED_CUSTOMER_ATTRIBUTES.each do |attribute|
|
23
35
|
validates_presence_of attribute, :if => :switching_to_billed?
|
24
36
|
end
|
25
37
|
before_create :create_customer
|
@@ -39,6 +51,10 @@ module Saucy
|
|
39
51
|
customer.credit_cards[0] if customer && customer.credit_cards.any?
|
40
52
|
end
|
41
53
|
|
54
|
+
def billing_address
|
55
|
+
credit_card.billing_address if credit_card
|
56
|
+
end
|
57
|
+
|
42
58
|
def subscription
|
43
59
|
Braintree::Subscription.find(subscription_token) if subscription_token
|
44
60
|
end
|
@@ -103,11 +119,11 @@ module Saucy
|
|
103
119
|
end
|
104
120
|
|
105
121
|
def changing_customer_attributes?(attributes)
|
106
|
-
CUSTOMER_ATTRIBUTES.
|
122
|
+
CUSTOMER_ATTRIBUTES.any? { |attribute| attributes[attribute].present? }
|
107
123
|
end
|
108
124
|
|
109
125
|
def set_customer_attributes(attributes)
|
110
|
-
CUSTOMER_ATTRIBUTES.
|
126
|
+
CUSTOMER_ATTRIBUTES.each do |attribute|
|
111
127
|
send("#{attribute}=", attributes[attribute]) if attributes[attribute].present?
|
112
128
|
end
|
113
129
|
end
|
@@ -144,7 +160,16 @@ module Saucy
|
|
144
160
|
:number => card_number,
|
145
161
|
:expiration_month => expiration_month,
|
146
162
|
:expiration_year => expiration_year,
|
147
|
-
:cvv => verification_code
|
163
|
+
:cvv => verification_code,
|
164
|
+
:billing_address => {
|
165
|
+
:street_address => street_address,
|
166
|
+
:extended_address => extended_address,
|
167
|
+
:locality => locality,
|
168
|
+
:region => region,
|
169
|
+
:postal_code => postal_code,
|
170
|
+
:country_name => country_name
|
171
|
+
}
|
172
|
+
}
|
148
173
|
if credit_card
|
149
174
|
card_attributes.merge!(:options => credit_card_options)
|
150
175
|
end
|
@@ -1,17 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
describe Account, "factories" do
|
4
|
+
it "has a valid factory" do
|
5
|
+
Factory(:account).should be_valid
|
6
|
+
end
|
7
|
+
|
8
|
+
it "has a valid paid factory" do
|
9
|
+
Factory(:paid_account).should be_valid
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
3
13
|
describe Account do
|
4
14
|
subject { Factory(:account) }
|
5
15
|
|
6
16
|
it "manifests braintree processor_declined errors as errors on number and doesn't save" do
|
7
17
|
FakeBraintree.failures["4111111111111112"] = { "message" => "Do Not Honor", "code" => "2000", "status" => "processor_declined" }
|
8
|
-
account = Factory.build(:
|
9
|
-
:cardholder_name => "Ralph Robot",
|
10
|
-
:billing_email => "ralph@example.com",
|
18
|
+
account = Factory.build(:paid_account,
|
11
19
|
:card_number => "4111111111111112",
|
12
|
-
:verification_code => "100",
|
13
|
-
:expiration_month => 5,
|
14
|
-
:expiration_year => 2012,
|
15
20
|
:plan => Factory(:paid_plan))
|
16
21
|
account.save.should_not be
|
17
22
|
FakeBraintree.customers.should be_empty
|
@@ -21,13 +26,8 @@ describe Account do
|
|
21
26
|
|
22
27
|
it "manifests braintree gateway_rejected errors as errors on number and doesn't save" do
|
23
28
|
FakeBraintree.failures["4111111111111112"] = { "message" => "Gateway Rejected: cvv", "code" => "N", "status" => "gateway_rejected" }
|
24
|
-
account = Factory.build(:
|
25
|
-
:cardholder_name => "Ralph Robot",
|
26
|
-
:billing_email => "ralph@example.com",
|
29
|
+
account = Factory.build(:paid_account,
|
27
30
|
:card_number => "4111111111111112",
|
28
|
-
:expiration_month => 5,
|
29
|
-
:expiration_year => 2012,
|
30
|
-
:verification_code => 200,
|
31
31
|
:plan => Factory(:paid_plan))
|
32
32
|
account.save.should_not be
|
33
33
|
FakeBraintree.customers.should be_empty
|
@@ -36,14 +36,9 @@ describe Account do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "manifests braintree gateway_rejected errors as errors on number and doesn't save" do
|
39
|
-
FakeBraintree.failures["
|
40
|
-
account = Factory.build(:
|
41
|
-
:
|
42
|
-
:billing_email => "ralph@example.com",
|
43
|
-
:card_number => "4111111111111111",
|
44
|
-
:expiration_month => 5,
|
45
|
-
:expiration_year => 2012,
|
46
|
-
:verification_code => 123,
|
39
|
+
FakeBraintree.failures["4111111111111112"] = { "message" => "Credit card number is invalid.", "errors" => { "customer" => { "errors" => [], "credit-card" => { "errors" => [{ "message" => "Credit card number is invalid.", "code" => 81715, "attribute" => :number }] }}}}
|
40
|
+
account = Factory.build(:paid_account,
|
41
|
+
:card_number => "4111111111111112",
|
47
42
|
:plan => Factory(:paid_plan))
|
48
43
|
account.save.should_not be
|
49
44
|
FakeBraintree.customers.should be_empty
|
@@ -64,7 +59,7 @@ describe Account, "given free and paid plans" do
|
|
64
59
|
|
65
60
|
result.should be_false
|
66
61
|
account.reload.plan.should == free
|
67
|
-
Saucy::Subscription::
|
62
|
+
Saucy::Subscription::REQUIRED_CUSTOMER_ATTRIBUTES.each do |attribute|
|
68
63
|
account.errors[attribute].should_not be_blank
|
69
64
|
end
|
70
65
|
FakeBraintree.customers[account.customer_token].should_not be_nil
|
@@ -92,14 +87,7 @@ end
|
|
92
87
|
|
93
88
|
describe Account, "with a paid plan" do
|
94
89
|
subject do
|
95
|
-
Factory(:
|
96
|
-
:cardholder_name => "Ralph Robot",
|
97
|
-
:billing_email => "ralph@example.com",
|
98
|
-
:card_number => "4111111111111111",
|
99
|
-
:verification_code => "123",
|
100
|
-
:expiration_month => 5,
|
101
|
-
:expiration_year => 2012,
|
102
|
-
:plan => Factory(:paid_plan))
|
90
|
+
Factory(:paid_account, :plan => Factory(:paid_plan))
|
103
91
|
end
|
104
92
|
|
105
93
|
it "has a customer_token" do
|
@@ -148,15 +136,76 @@ describe Account, "with a paid plan" do
|
|
148
136
|
FakeBraintree.subscriptions[subject.subscription_token]["price"].should == "5"
|
149
137
|
end
|
150
138
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
139
|
+
context "updating customer credit card information when changed" do
|
140
|
+
before do
|
141
|
+
subject.save_customer_and_subscription!(:billing_email => "jrobot@example.com",
|
142
|
+
:cardholder_name => "Jim Robot",
|
143
|
+
:card_number => "4111111111111115",
|
144
|
+
:verification_code => "123",
|
145
|
+
:expiration_month => 5,
|
146
|
+
:expiration_year => 2013)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "updates the billing email" do
|
150
|
+
subject.customer.email.should == "jrobot@example.com"
|
151
|
+
end
|
152
|
+
|
153
|
+
it "updates the cardholder name" do
|
154
|
+
subject.credit_card.cardholder_name.should == "Jim Robot"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "updates the card number" do
|
158
|
+
subject.credit_card.last_4.should == "1115"
|
159
|
+
end
|
160
|
+
|
161
|
+
it "updates the expiration year" do
|
162
|
+
subject.credit_card.expiration_year.should == 2013
|
163
|
+
end
|
164
|
+
|
165
|
+
it "updates the expiration month" do
|
166
|
+
subject.credit_card.expiration_month.should == 5
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "updating customer credit card billing address information when changed" do
|
171
|
+
before do
|
172
|
+
subject.save_customer_and_subscription!(:billing_email => "jrobot@example.com",
|
173
|
+
:cardholder_name => "Jim Robot",
|
174
|
+
:card_number => "4111111111111115",
|
175
|
+
:verification_code => "123",
|
176
|
+
:expiration_month => 5,
|
177
|
+
:expiration_year => 2013,
|
178
|
+
:street_address => "1 E Main St",
|
179
|
+
:extended_address => "Suite 3",
|
180
|
+
:locality => "Chicago",
|
181
|
+
:region => "Illinois",
|
182
|
+
:postal_code => "60622",
|
183
|
+
:country_name => "United States of America")
|
184
|
+
end
|
185
|
+
|
186
|
+
it "updates the street address" do
|
187
|
+
subject.billing_address.street_address.should == "1 E Main St"
|
188
|
+
end
|
189
|
+
|
190
|
+
it "updates the extended address" do
|
191
|
+
subject.billing_address.extended_address.should == "Suite 3"
|
192
|
+
end
|
193
|
+
|
194
|
+
it "updates the locality" do
|
195
|
+
subject.billing_address.locality.should == "Chicago"
|
196
|
+
end
|
197
|
+
|
198
|
+
it "updates the region" do
|
199
|
+
subject.billing_address.region.should == "Illinois"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "updates the postal code" do
|
203
|
+
subject.billing_address.postal_code.should == "60622"
|
204
|
+
end
|
205
|
+
|
206
|
+
it "updates the country name" do
|
207
|
+
subject.billing_address.country_name.should == "United States of America"
|
208
|
+
end
|
160
209
|
end
|
161
210
|
|
162
211
|
it "deletes the customer when deleted" do
|
@@ -190,6 +239,10 @@ describe Account, "with a free plan" do
|
|
190
239
|
subject.subscription.should be_nil
|
191
240
|
end
|
192
241
|
|
242
|
+
it "doesn't have a billing address" do
|
243
|
+
subject.billing_address.should be_nil
|
244
|
+
end
|
245
|
+
|
193
246
|
it "creates a braintree customer" do
|
194
247
|
FakeBraintree.customers[subject.customer_token].should_not be_nil
|
195
248
|
end
|
@@ -199,34 +252,23 @@ describe Account, "with a free plan" do
|
|
199
252
|
FakeBraintree.subscriptions[subject.subscription_token].should be_nil
|
200
253
|
end
|
201
254
|
|
202
|
-
it "creates a credit card, and
|
255
|
+
it "creates a credit card, subscription, and billing address when the plan is changed to a paid plan and the billing info is supplied" do
|
203
256
|
new_plan = Factory(:paid_plan, :name => "New Plan")
|
204
|
-
subject.save_customer_and_subscription!(:plan_id => new_plan.id
|
205
|
-
:cardholder_name => "Ralph Robot",
|
206
|
-
:billing_email => "ralph@example.com",
|
207
|
-
:card_number => "4111111111111111",
|
208
|
-
:verification_code => "123",
|
209
|
-
:expiration_month => 5,
|
210
|
-
:expiration_year => 2012)
|
257
|
+
subject.save_customer_and_subscription!(Factory.attributes_for(:paid_account, :plan_id => new_plan.id))
|
211
258
|
|
212
259
|
FakeBraintree.customers[subject.customer_token]["credit_cards"].first.should_not be_nil
|
213
260
|
FakeBraintree.subscriptions[subject.subscription_token].should_not be_nil
|
214
261
|
FakeBraintree.subscriptions[subject.subscription_token]["plan_id"].should == new_plan.id
|
215
262
|
subject.credit_card.should_not be_nil
|
216
263
|
subject.subscription.should_not be_nil
|
264
|
+
subject.billing_address.should_not be_nil
|
217
265
|
end
|
218
266
|
|
219
267
|
it "passes up the merchant_account_id on the subscription when it's configured" do
|
220
268
|
begin
|
221
269
|
Saucy::Configuration.merchant_account_id = 'test'
|
222
270
|
new_plan = Factory(:paid_plan, :name => "New Plan")
|
223
|
-
subject.save_customer_and_subscription!(:plan_id => new_plan.id
|
224
|
-
:cardholder_name => "Ralph Robot",
|
225
|
-
:billing_email => "ralph@example.com",
|
226
|
-
:card_number => "4111111111111111",
|
227
|
-
:verification_code => "123",
|
228
|
-
:expiration_month => 5,
|
229
|
-
:expiration_year => 2012)
|
271
|
+
subject.save_customer_and_subscription!(Factory.attributes_for(:paid_account, :plan_id => new_plan.id))
|
230
272
|
|
231
273
|
FakeBraintree.subscriptions[subject.subscription_token]["merchant_account_id"].should == 'test'
|
232
274
|
ensure
|
@@ -237,23 +279,18 @@ describe Account, "with a free plan" do
|
|
237
279
|
it "doesn't pass up the merchant_account_id on the subscription when it's not configured" do
|
238
280
|
Saucy::Configuration.merchant_account_id = nil
|
239
281
|
new_plan = Factory(:paid_plan, :name => "New Plan")
|
240
|
-
subject.save_customer_and_subscription!(:plan_id => new_plan.id
|
241
|
-
:cardholder_name => "Ralph Robot",
|
242
|
-
:billing_email => "ralph@example.com",
|
243
|
-
:card_number => "4111111111111111",
|
244
|
-
:verification_code => "123",
|
245
|
-
:expiration_month => 5,
|
246
|
-
:expiration_year => 2012)
|
282
|
+
subject.save_customer_and_subscription!(Factory.attributes_for(:paid_account, :plan_id => new_plan.id))
|
247
283
|
|
248
284
|
FakeBraintree.subscriptions[subject.subscription_token].keys.should_not include("merchant_account_id")
|
249
285
|
end
|
250
286
|
|
251
|
-
it "doesn't create a credit card, and
|
287
|
+
it "doesn't create a credit card, subscription, and billing address when the plan is changed to a different free plan" do
|
252
288
|
new_plan = Factory(:plan, :name => "New Plan")
|
253
289
|
subject.save_customer_and_subscription!(:plan_id => new_plan.id)
|
254
290
|
|
255
291
|
subject.credit_card.should be_nil
|
256
292
|
subject.subscription.should be_nil
|
293
|
+
subject.billing_address.should be_nil
|
257
294
|
end
|
258
295
|
end
|
259
296
|
|
@@ -285,16 +322,12 @@ end
|
|
285
322
|
|
286
323
|
describe Account, "with a paid subscription" do
|
287
324
|
subject do
|
288
|
-
Factory(:
|
289
|
-
:cardholder_name => "Ralph Robot",
|
290
|
-
:billing_email => "ralph@example.com",
|
291
|
-
:card_number => "4111111111111111",
|
292
|
-
:verification_code => "123",
|
293
|
-
:expiration_month => 5,
|
294
|
-
:expiration_year => 2012,
|
325
|
+
Factory(:paid_account,
|
295
326
|
:plan => Factory(:paid_plan))
|
296
327
|
end
|
297
328
|
|
329
|
+
let(:merchant_time_zone) { ActiveSupport::TimeZone[Saucy::Configuration.merchant_account_time_zone] }
|
330
|
+
|
298
331
|
it "gets marked as past due and updates its next_billing_date when subscriptions are updated and it has been rejected by the gateway" do
|
299
332
|
next_billing_date_string = 2.months.from_now.to_s(:braintree_date)
|
300
333
|
subscription = FakeBraintree.subscriptions[subject.subscription_token]
|
@@ -304,8 +337,7 @@ describe Account, "with a paid subscription" do
|
|
304
337
|
Timecop.travel(subject.next_billing_date + 1.day) do
|
305
338
|
Account.update_subscriptions!
|
306
339
|
subject.reload.subscription_status.should == Braintree::Subscription::Status::PastDue
|
307
|
-
subject.next_billing_date.should ==
|
308
|
-
Saucy::Configuration.merchant_account_time_zone)
|
340
|
+
subject.next_billing_date.should == merchant_time_zone.parse(next_billing_date_string)
|
309
341
|
subject.past_due?.should be
|
310
342
|
end
|
311
343
|
end
|
@@ -326,13 +358,7 @@ describe Account, "with a paid subscription" do
|
|
326
358
|
end
|
327
359
|
|
328
360
|
it "delivers the rest of the emails even if one fails" do
|
329
|
-
Factory(:
|
330
|
-
:cardholder_name => "Ralph Robot",
|
331
|
-
:billing_email => "ralph@example.com",
|
332
|
-
:card_number => "4111111111111111",
|
333
|
-
:verification_code => "123",
|
334
|
-
:expiration_month => 5,
|
335
|
-
:expiration_year => 2012,
|
361
|
+
Factory(:paid_account,
|
336
362
|
:plan => Factory(:paid_plan))
|
337
363
|
Timecop.travel(subject.next_billing_date + 1.day) do
|
338
364
|
Account.update_subscriptions!
|
@@ -519,13 +545,7 @@ end
|
|
519
545
|
|
520
546
|
describe Account, "with a paid subscription that is past due" do
|
521
547
|
subject do
|
522
|
-
Factory(:
|
523
|
-
:cardholder_name => "Ralph Robot",
|
524
|
-
:billing_email => "ralph@example.com",
|
525
|
-
:card_number => "4111111111111111",
|
526
|
-
:verification_code => "123",
|
527
|
-
:expiration_month => 5,
|
528
|
-
:expiration_year => 2012,
|
548
|
+
Factory(:paid_account,
|
529
549
|
:plan => Factory(:paid_plan))
|
530
550
|
end
|
531
551
|
|
@@ -622,13 +642,7 @@ end
|
|
622
642
|
|
623
643
|
describe Account, "that is activated" do
|
624
644
|
subject do
|
625
|
-
Factory(:
|
626
|
-
:cardholder_name => "Ralph Robot",
|
627
|
-
:billing_email => "ralph@example.com",
|
628
|
-
:card_number => "4111111111111111",
|
629
|
-
:verification_code => "123",
|
630
|
-
:expiration_month => 5,
|
631
|
-
:expiration_year => 2012,
|
645
|
+
Factory(:paid_account,
|
632
646
|
:plan => Factory(:paid_plan))
|
633
647
|
end
|
634
648
|
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saucy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 45
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 13
|
9
|
-
- 3
|
10
|
-
version: 0.13.3
|
5
|
+
version: 0.14.0
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- thoughtbot, inc.
|
@@ -20,7 +15,7 @@ autorequire:
|
|
20
15
|
bindir: bin
|
21
16
|
cert_chain: []
|
22
17
|
|
23
|
-
date: 2011-10-
|
18
|
+
date: 2011-10-24 00:00:00 Z
|
24
19
|
dependencies:
|
25
20
|
- !ruby/object:Gem::Dependency
|
26
21
|
name: clearance
|
@@ -30,11 +25,6 @@ dependencies:
|
|
30
25
|
requirements:
|
31
26
|
- - ~>
|
32
27
|
- !ruby/object:Gem::Version
|
33
|
-
hash: 55
|
34
|
-
segments:
|
35
|
-
- 0
|
36
|
-
- 11
|
37
|
-
- 2
|
38
28
|
version: 0.11.2
|
39
29
|
type: :runtime
|
40
30
|
version_requirements: *id001
|
@@ -46,10 +36,6 @@ dependencies:
|
|
46
36
|
requirements:
|
47
37
|
- - ">="
|
48
38
|
- !ruby/object:Gem::Version
|
49
|
-
hash: 11
|
50
|
-
segments:
|
51
|
-
- 1
|
52
|
-
- 2
|
53
39
|
version: "1.2"
|
54
40
|
type: :runtime
|
55
41
|
version_requirements: *id002
|
@@ -61,11 +47,6 @@ dependencies:
|
|
61
47
|
requirements:
|
62
48
|
- - ">="
|
63
49
|
- !ruby/object:Gem::Version
|
64
|
-
hash: 1
|
65
|
-
segments:
|
66
|
-
- 3
|
67
|
-
- 0
|
68
|
-
- 3
|
69
50
|
version: 3.0.3
|
70
51
|
type: :runtime
|
71
52
|
version_requirements: *id003
|
@@ -77,11 +58,6 @@ dependencies:
|
|
77
58
|
requirements:
|
78
59
|
- - ">="
|
79
60
|
- !ruby/object:Gem::Version
|
80
|
-
hash: 19
|
81
|
-
segments:
|
82
|
-
- 2
|
83
|
-
- 6
|
84
|
-
- 2
|
85
61
|
version: 2.6.2
|
86
62
|
type: :runtime
|
87
63
|
version_requirements: *id004
|
@@ -93,11 +69,6 @@ dependencies:
|
|
93
69
|
requirements:
|
94
70
|
- - "="
|
95
71
|
- !ruby/object:Gem::Version
|
96
|
-
hash: 29
|
97
|
-
segments:
|
98
|
-
- 1
|
99
|
-
- 3
|
100
|
-
- 3
|
101
72
|
version: 1.3.3
|
102
73
|
type: :runtime
|
103
74
|
version_requirements: *id005
|
@@ -109,11 +80,6 @@ dependencies:
|
|
109
80
|
requirements:
|
110
81
|
- - ">="
|
111
82
|
- !ruby/object:Gem::Version
|
112
|
-
hash: 23
|
113
|
-
segments:
|
114
|
-
- 1
|
115
|
-
- 1
|
116
|
-
- 2
|
117
83
|
version: 1.1.2
|
118
84
|
type: :runtime
|
119
85
|
version_requirements: *id006
|
@@ -125,11 +91,6 @@ dependencies:
|
|
125
91
|
requirements:
|
126
92
|
- - ~>
|
127
93
|
- !ruby/object:Gem::Version
|
128
|
-
hash: 15
|
129
|
-
segments:
|
130
|
-
- 3
|
131
|
-
- 0
|
132
|
-
- 4
|
133
94
|
version: 3.0.4
|
134
95
|
type: :runtime
|
135
96
|
version_requirements: *id007
|
@@ -141,11 +102,6 @@ dependencies:
|
|
141
102
|
requirements:
|
142
103
|
- - "="
|
143
104
|
- !ruby/object:Gem::Version
|
144
|
-
hash: 27
|
145
|
-
segments:
|
146
|
-
- 0
|
147
|
-
- 2
|
148
|
-
- 6
|
149
105
|
version: 0.2.6
|
150
106
|
type: :development
|
151
107
|
version_requirements: *id008
|
@@ -238,6 +194,7 @@ files:
|
|
238
194
|
- lib/generators/saucy/features/templates/factories.rb
|
239
195
|
- lib/generators/saucy/features/templates/step_definitions/account_steps.rb
|
240
196
|
- lib/generators/saucy/features/templates/step_definitions/braintree_steps.rb
|
197
|
+
- lib/generators/saucy/features/templates/step_definitions/country_steps.rb
|
241
198
|
- lib/generators/saucy/features/templates/step_definitions/cron_steps.rb
|
242
199
|
- lib/generators/saucy/features/templates/step_definitions/email_steps.rb
|
243
200
|
- lib/generators/saucy/features/templates/step_definitions/factory_girl_steps.rb
|
@@ -345,23 +302,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
345
302
|
requirements:
|
346
303
|
- - ">="
|
347
304
|
- !ruby/object:Gem::Version
|
348
|
-
hash: 3
|
349
|
-
segments:
|
350
|
-
- 0
|
351
305
|
version: "0"
|
352
306
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
353
307
|
none: false
|
354
308
|
requirements:
|
355
309
|
- - ">="
|
356
310
|
- !ruby/object:Gem::Version
|
357
|
-
hash: 3
|
358
|
-
segments:
|
359
|
-
- 0
|
360
311
|
version: "0"
|
361
312
|
requirements: []
|
362
313
|
|
363
314
|
rubyforge_project:
|
364
|
-
rubygems_version: 1.8.
|
315
|
+
rubygems_version: 1.8.10
|
365
316
|
signing_key:
|
366
317
|
specification_version: 3
|
367
318
|
summary: Clearance-based Rails engine for SaaS
|