effective_orders 1.0.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +856 -0
- data/Rakefile +24 -0
- data/app/assets/images/effective_orders/stripe_connect.png +0 -0
- data/app/assets/javascripts/effective_orders/shipping_address_toggle.js.coffee +30 -0
- data/app/assets/javascripts/effective_orders/stripe_charges.js.coffee +26 -0
- data/app/assets/javascripts/effective_orders/stripe_subscriptions.js.coffee +28 -0
- data/app/assets/javascripts/effective_orders.js +2 -0
- data/app/assets/stylesheets/effective_orders/_order.scss +30 -0
- data/app/assets/stylesheets/effective_orders.css.scss +1 -0
- data/app/controllers/admin/customers_controller.rb +15 -0
- data/app/controllers/admin/orders_controller.rb +22 -0
- data/app/controllers/effective/carts_controller.rb +70 -0
- data/app/controllers/effective/orders_controller.rb +191 -0
- data/app/controllers/effective/providers/moneris.rb +94 -0
- data/app/controllers/effective/providers/paypal.rb +29 -0
- data/app/controllers/effective/providers/stripe.rb +125 -0
- data/app/controllers/effective/providers/stripe_connect.rb +47 -0
- data/app/controllers/effective/subscriptions_controller.rb +123 -0
- data/app/controllers/effective/webhooks_controller.rb +86 -0
- data/app/helpers/effective_carts_helper.rb +90 -0
- data/app/helpers/effective_orders_helper.rb +108 -0
- data/app/helpers/effective_paypal_helper.rb +37 -0
- data/app/helpers/effective_stripe_helper.rb +63 -0
- data/app/mailers/effective/orders_mailer.rb +64 -0
- data/app/models/concerns/acts_as_purchasable.rb +134 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/cart.rb +65 -0
- data/app/models/effective/cart_item.rb +40 -0
- data/app/models/effective/customer.rb +61 -0
- data/app/models/effective/datatables/customers.rb +45 -0
- data/app/models/effective/datatables/orders.rb +53 -0
- data/app/models/effective/order.rb +247 -0
- data/app/models/effective/order_item.rb +69 -0
- data/app/models/effective/stripe_charge.rb +35 -0
- data/app/models/effective/subscription.rb +95 -0
- data/app/models/inputs/price_field.rb +63 -0
- data/app/models/inputs/price_form_input.rb +7 -0
- data/app/models/inputs/price_formtastic_input.rb +9 -0
- data/app/models/inputs/price_input.rb +19 -0
- data/app/models/inputs/price_simple_form_input.rb +8 -0
- data/app/models/validators/effective/sold_out_validator.rb +7 -0
- data/app/views/active_admin/effective_orders/orders/_show.html.haml +70 -0
- data/app/views/admin/customers/_actions.html.haml +2 -0
- data/app/views/admin/customers/index.html.haml +10 -0
- data/app/views/admin/orders/index.html.haml +7 -0
- data/app/views/admin/orders/show.html.haml +11 -0
- data/app/views/effective/carts/_cart.html.haml +33 -0
- data/app/views/effective/carts/show.html.haml +18 -0
- data/app/views/effective/orders/_checkout_step_1.html.haml +39 -0
- data/app/views/effective/orders/_checkout_step_2.html.haml +18 -0
- data/app/views/effective/orders/_my_purchases.html.haml +15 -0
- data/app/views/effective/orders/_order.html.haml +4 -0
- data/app/views/effective/orders/_order_header.html.haml +21 -0
- data/app/views/effective/orders/_order_items.html.haml +39 -0
- data/app/views/effective/orders/_order_payment_details.html.haml +11 -0
- data/app/views/effective/orders/_order_shipping.html.haml +19 -0
- data/app/views/effective/orders/_order_user_fields.html.haml +10 -0
- data/app/views/effective/orders/checkout.html.haml +3 -0
- data/app/views/effective/orders/declined.html.haml +10 -0
- data/app/views/effective/orders/moneris/_form.html.haml +34 -0
- data/app/views/effective/orders/my_purchases.html.haml +6 -0
- data/app/views/effective/orders/my_sales.html.haml +28 -0
- data/app/views/effective/orders/new.html.haml +4 -0
- data/app/views/effective/orders/paypal/_form.html.haml +5 -0
- data/app/views/effective/orders/purchased.html.haml +10 -0
- data/app/views/effective/orders/show.html.haml +17 -0
- data/app/views/effective/orders/stripe/_form.html.haml +8 -0
- data/app/views/effective/orders/stripe/_subscription_fields.html.haml +7 -0
- data/app/views/effective/orders_mailer/order_receipt_to_admin.html.haml +8 -0
- data/app/views/effective/orders_mailer/order_receipt_to_buyer.html.haml +8 -0
- data/app/views/effective/orders_mailer/order_receipt_to_seller.html.haml +30 -0
- data/app/views/effective/subscriptions/index.html.haml +16 -0
- data/app/views/effective/subscriptions/new.html.haml +10 -0
- data/app/views/effective/subscriptions/show.html.haml +49 -0
- data/config/routes.rb +57 -0
- data/db/migrate/01_create_effective_orders.rb.erb +91 -0
- data/db/upgrade/02_upgrade_effective_orders_from03x.rb.erb +29 -0
- data/db/upgrade/upgrade_price_column_on_table.rb.erb +17 -0
- data/lib/effective_orders/engine.rb +52 -0
- data/lib/effective_orders/version.rb +3 -0
- data/lib/effective_orders.rb +76 -0
- data/lib/generators/effective_orders/install_generator.rb +38 -0
- data/lib/generators/effective_orders/upgrade_from03x_generator.rb +34 -0
- data/lib/generators/effective_orders/upgrade_price_column_generator.rb +34 -0
- data/lib/generators/templates/README +1 -0
- data/lib/generators/templates/effective_orders.rb +210 -0
- data/spec/controllers/carts_controller_spec.rb +143 -0
- data/spec/controllers/moneris_orders_controller_spec.rb +245 -0
- data/spec/controllers/orders_controller_spec.rb +418 -0
- data/spec/controllers/stripe_orders_controller_spec.rb +127 -0
- data/spec/controllers/webhooks_controller_spec.rb +79 -0
- data/spec/dummy/README.rdoc +8 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/product.rb +17 -0
- data/spec/dummy/app/models/product_with_float_price.rb +17 -0
- data/spec/dummy/app/models/user.rb +28 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +31 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +83 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/devise.rb +254 -0
- data/spec/dummy/config/initializers/effective_addresses.rb +15 -0
- data/spec/dummy/config/initializers/effective_orders.rb +22 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +142 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +487 -0
- data/spec/dummy/log/test.log +347 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/helpers/effective_orders_helper_spec.rb +21 -0
- data/spec/models/acts_as_purchasable_spec.rb +107 -0
- data/spec/models/customer_spec.rb +71 -0
- data/spec/models/factories_spec.rb +13 -0
- data/spec/models/order_item_spec.rb +35 -0
- data/spec/models/order_spec.rb +323 -0
- data/spec/models/stripe_charge_spec.rb +39 -0
- data/spec/models/subscription_spec.rb +103 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/support/factories.rb +118 -0
- metadata +387 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Effective::OrdersController do
|
|
4
|
+
routes { EffectiveOrders::Engine.routes }
|
|
5
|
+
|
|
6
|
+
let(:purchased_order) { FactoryGirl.create(:purchased_order) }
|
|
7
|
+
let(:order) { FactoryGirl.create(:order) }
|
|
8
|
+
|
|
9
|
+
let(:cart) { FactoryGirl.create(:cart) }
|
|
10
|
+
let(:address) { FactoryGirl.create(:address) }
|
|
11
|
+
|
|
12
|
+
let(:billing_address) { FactoryGirl.create(:address) }
|
|
13
|
+
let(:billing_atts) { billing_address.attributes.reject { |k, v| ['id', 'addressable_type', 'addressable_id', 'category', 'updated_at', 'created_at'].include?(k) } }
|
|
14
|
+
|
|
15
|
+
let(:shipping_address) { FactoryGirl.create(:address) }
|
|
16
|
+
let(:shipping_atts) { shipping_address.attributes.reject { |k, v| ['id', 'addressable_type', 'addressable_id', 'category', 'updated_at', 'created_at'].include?(k) } }
|
|
17
|
+
|
|
18
|
+
let(:valid_order_attributes) do
|
|
19
|
+
{
|
|
20
|
+
:effective_order => {
|
|
21
|
+
:billing_address => billing_atts, :save_billing_address => false,
|
|
22
|
+
:shipping_address => shipping_atts, :save_shipping_address => false,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'uses authenticate_user! to redirect to sign in if not signed in' do
|
|
28
|
+
get :new
|
|
29
|
+
response.should redirect_to '/users/sign_in'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#new' do
|
|
33
|
+
it 'should assign an @order based off the user cart' do
|
|
34
|
+
sign_in cart.user
|
|
35
|
+
get :new
|
|
36
|
+
|
|
37
|
+
assigns(:order).user.should eq cart.user
|
|
38
|
+
|
|
39
|
+
assigns(:order).order_items.size.should eq cart.cart_items.size
|
|
40
|
+
assigns(:order).total.should eq cart.total
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'redirects if there is an empty order' do
|
|
44
|
+
sign_in cart.user
|
|
45
|
+
cart.cart_items.destroy_all
|
|
46
|
+
|
|
47
|
+
get :new
|
|
48
|
+
|
|
49
|
+
flash[:danger].downcase.include?('add one or more item to your cart').should eq true
|
|
50
|
+
response.should redirect_to '/cart' # cart_path
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'redirects if order total is less than minimum charge' do
|
|
54
|
+
sign_in cart.user
|
|
55
|
+
Effective::CartItem.any_instance.stub(:price).and_return(10)
|
|
56
|
+
|
|
57
|
+
get :new
|
|
58
|
+
|
|
59
|
+
flash[:danger].downcase.include?('a minimum order of $0.50 is required').should eq true
|
|
60
|
+
response.should redirect_to '/cart' # cart_path
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# "effective_order"=> {
|
|
65
|
+
# "order_items_attributes"=> {
|
|
66
|
+
# "0"=> {
|
|
67
|
+
# "class"=>"Effective::Subscription", "stripe_coupon_id"=>"50OFF", "id"=>"2"}},
|
|
68
|
+
# "billing_address"=>{"address1"=>"1234 Fake street", "address2"=>"", "city"=>"Edmonton", "country_code"=>"KH", "state_code"=>"1", "postal_code"=>"T5T2T1"},
|
|
69
|
+
# "save_billing_address"=>"1",
|
|
70
|
+
# "shipping_address"=>{"address1"=>"123 Shipping street", "address2"=>"", "city"=>"Edmonton", "country_code"=>"KH", "state_code"=>"10", "postal_code"=>"t5t2t1"},
|
|
71
|
+
# "save_shipping_address"=>"1"},
|
|
72
|
+
# "commit"=>"Continue Checkout"
|
|
73
|
+
# }
|
|
74
|
+
|
|
75
|
+
describe '#create' do
|
|
76
|
+
before(:each) do
|
|
77
|
+
sign_in cart.user
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should assign an @order based off the user cart' do
|
|
81
|
+
post :create
|
|
82
|
+
|
|
83
|
+
assigns(:order).user.should eq cart.user
|
|
84
|
+
assigns(:order).order_items.size.should eq cart.cart_items.size
|
|
85
|
+
assigns(:order).total.should eq cart.total
|
|
86
|
+
assigns(:order).purchased?.should eq false
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'assign appropriate User fields' do
|
|
90
|
+
post :create, :effective_order => {
|
|
91
|
+
:billing_address => billing_atts, :save_billing_address => false,
|
|
92
|
+
:shipping_address => shipping_atts, :save_shipping_address => false,
|
|
93
|
+
:shipping_address_same_as_billing => false,
|
|
94
|
+
:user_attributes => {:first_name => 'First', :last_name => 'Last', :email => 'email@somwhere.com'}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
98
|
+
|
|
99
|
+
assigns(:order).user.first_name.should eq 'First'
|
|
100
|
+
assigns(:order).user.last_name.should eq 'Last'
|
|
101
|
+
assigns(:order).user.email.should_not eq 'email@somwhere.com'
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'assign addresses to the order and not the user' do
|
|
105
|
+
post :create, :effective_order => {
|
|
106
|
+
:billing_address => billing_atts, :save_billing_address => false,
|
|
107
|
+
:shipping_address => shipping_atts, :save_shipping_address => false,
|
|
108
|
+
:shipping_address_same_as_billing => false
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
112
|
+
|
|
113
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
114
|
+
assigns(:order).shipping_address.address1.should eq shipping_atts['address1']
|
|
115
|
+
|
|
116
|
+
assigns(:order).user.billing_address.present?.should eq false
|
|
117
|
+
assigns(:order).user.shipping_address.present?.should eq false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'assign addresses to the order and the user' do
|
|
121
|
+
post :create, :effective_order => {
|
|
122
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
123
|
+
:shipping_address => shipping_atts, :save_shipping_address => true,
|
|
124
|
+
:shipping_address_same_as_billing => false
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
128
|
+
|
|
129
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
130
|
+
assigns(:order).shipping_address.address1.should eq shipping_atts['address1']
|
|
131
|
+
|
|
132
|
+
assigns(:order).user.billing_address.address1.should eq billing_atts['address1']
|
|
133
|
+
assigns(:order).user.shipping_address.address1.should eq shipping_atts['address1']
|
|
134
|
+
|
|
135
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'does not assign the billing_address to user if save_billing_address is false' do
|
|
139
|
+
post :create, :effective_order => {
|
|
140
|
+
:billing_address => billing_atts, :save_billing_address => false,
|
|
141
|
+
:shipping_address => shipping_atts, :save_shipping_address => true,
|
|
142
|
+
:shipping_address_same_as_billing => false
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
146
|
+
|
|
147
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
148
|
+
assigns(:order).shipping_address.address1.should eq shipping_atts['address1']
|
|
149
|
+
|
|
150
|
+
assigns(:order).user.billing_address.present?.should eq false
|
|
151
|
+
assigns(:order).user.shipping_address.address1.should eq shipping_atts['address1']
|
|
152
|
+
|
|
153
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'does not assign the shipping_address to user if save_shipping_address is false' do
|
|
157
|
+
post :create, :effective_order => {
|
|
158
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
159
|
+
:shipping_address => shipping_atts, :save_shipping_address => false,
|
|
160
|
+
:shipping_address_same_as_billing => false
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
164
|
+
|
|
165
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
166
|
+
assigns(:order).shipping_address.address1.should eq shipping_atts['address1']
|
|
167
|
+
|
|
168
|
+
assigns(:order).user.billing_address.address1.should eq billing_atts['address1']
|
|
169
|
+
assigns(:order).user.shipping_address.present?.should eq false
|
|
170
|
+
|
|
171
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'assign billing address to the order shipping_address when shipping_address_same_as_billing' do
|
|
175
|
+
post :create, :effective_order => {
|
|
176
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
177
|
+
:shipping_address => shipping_atts, :save_shipping_address => true,
|
|
178
|
+
:shipping_address_same_as_billing => true
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
182
|
+
|
|
183
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
184
|
+
assigns(:order).shipping_address.address1.should eq billing_atts['address1']
|
|
185
|
+
|
|
186
|
+
assigns(:order).user.billing_address.address1.should eq billing_atts['address1']
|
|
187
|
+
assigns(:order).user.shipping_address.address1.should eq billing_atts['address1']
|
|
188
|
+
|
|
189
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'assign billing address to the order shipping_address when shipping_address_same_as_billing and no shipping provided' do
|
|
193
|
+
post :create, :effective_order => {
|
|
194
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
195
|
+
:shipping_address_same_as_billing => true
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
199
|
+
|
|
200
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
201
|
+
assigns(:order).shipping_address.address1.should eq billing_atts['address1']
|
|
202
|
+
|
|
203
|
+
assigns(:order).user.billing_address.address1.should eq billing_atts['address1']
|
|
204
|
+
assigns(:order).user.shipping_address.address1.should eq billing_atts['address1']
|
|
205
|
+
|
|
206
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'assign billing address to the order shipping_address but not the user when shipping_address_same_as_billing provided' do
|
|
210
|
+
post :create, :effective_order => {
|
|
211
|
+
:billing_address => billing_atts, :save_billing_address => false,
|
|
212
|
+
:save_shipping_address => false,
|
|
213
|
+
:shipping_address_same_as_billing => true
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq true
|
|
217
|
+
|
|
218
|
+
assigns(:order).billing_address.address1.should eq billing_atts['address1']
|
|
219
|
+
assigns(:order).shipping_address.address1.should eq billing_atts['address1']
|
|
220
|
+
|
|
221
|
+
assigns(:order).user.billing_address.present?.should eq false
|
|
222
|
+
assigns(:order).user.shipping_address.present?.should eq false
|
|
223
|
+
|
|
224
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'is invalid when passed an invalid address' do
|
|
228
|
+
post :create, :effective_order => {
|
|
229
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
230
|
+
:shipping_address => shipping_atts.tap { |x| x[:address1] = nil }, :save_shipping_address => true,
|
|
231
|
+
:shipping_address_same_as_billing => false
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq false
|
|
235
|
+
assigns(:order).errors[:addresses].present?.should eq true
|
|
236
|
+
assigns(:order).errors[:shipping_address].present?.should eq true
|
|
237
|
+
|
|
238
|
+
response.should render_template(:new)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it 'is invalid when passed an invalid order_item' do
|
|
242
|
+
Effective::OrderItem.any_instance.stub(:valid?).and_return(false)
|
|
243
|
+
|
|
244
|
+
post :create, :effective_order => {
|
|
245
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
246
|
+
:shipping_address => shipping_atts, :save_shipping_address => true,
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq false
|
|
250
|
+
response.should render_template(:new)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it 'is invalid when passed an invalid user' do
|
|
254
|
+
User.any_instance.stub(:valid?).and_return(false)
|
|
255
|
+
|
|
256
|
+
post :create, :effective_order => {
|
|
257
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
258
|
+
:shipping_address => shipping_atts, :save_shipping_address => true,
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq false
|
|
262
|
+
response.should render_template(:new)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it 'is invalid when passed an invalid purchasable' do
|
|
266
|
+
Product.any_instance.stub(:valid?).and_return(false)
|
|
267
|
+
|
|
268
|
+
post :create, :effective_order => {
|
|
269
|
+
:billing_address => billing_atts, :save_billing_address => true,
|
|
270
|
+
:shipping_address => shipping_atts, :save_shipping_address => true,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq false
|
|
274
|
+
response.should render_template(:new)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it 'prevents the order from proceeding when missing a required address' do
|
|
278
|
+
post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address_same_as_billing => false }
|
|
279
|
+
|
|
280
|
+
(assigns(:order).valid? && assigns(:order).persisted?).should eq false
|
|
281
|
+
assigns(:order).errors[:shipping_address].present?.should eq true
|
|
282
|
+
|
|
283
|
+
response.should render_template(:new)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
describe '#create with a Stripe Subscription object' do
|
|
288
|
+
let(:cart_with_subscription) { FactoryGirl.create(:cart_with_subscription) }
|
|
289
|
+
let(:subscription) { cart_with_subscription.cart_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription)}.purchasable }
|
|
290
|
+
|
|
291
|
+
let(:valid_order_with_new_subscription_coupon_attributes) do
|
|
292
|
+
valid_order_attributes.tap { |x| x[:effective_order]['order_items_attributes'] = {'0' => {"class"=>"Effective::Subscription", "stripe_coupon_id"=>"#{::Stripe::Coupon.create().id}", 'id' => "#{subscription.id}"}} }
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
before do
|
|
296
|
+
StripeMock.start
|
|
297
|
+
sign_in cart_with_subscription.user
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
after { StripeMock.stop }
|
|
301
|
+
|
|
302
|
+
it 'has an OrderItem that is a Subscription' do
|
|
303
|
+
post :create, valid_order_attributes
|
|
304
|
+
assigns(:order).persisted?.should eq true
|
|
305
|
+
|
|
306
|
+
subscription = assigns(:order).order_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription) }
|
|
307
|
+
subscription.present?.should eq true
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it 'does not alter the subscription.stripe_coupon_id' do
|
|
311
|
+
post :create, valid_order_attributes
|
|
312
|
+
assigns(:order).persisted?.should eq true
|
|
313
|
+
|
|
314
|
+
order_subscription = assigns(:order).order_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription) }.purchasable
|
|
315
|
+
order_subscription.stripe_coupon_id.should eq subscription.stripe_coupon_id
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it 'updates the subscription.stripe_coupon_id when passed' do
|
|
319
|
+
post :create, valid_order_with_new_subscription_coupon_attributes
|
|
320
|
+
assigns(:order).persisted?.should eq true
|
|
321
|
+
|
|
322
|
+
order_subscription = assigns(:order).order_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription) }.purchasable
|
|
323
|
+
order_subscription.stripe_coupon_id.should_not eq subscription.stripe_coupon_id
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it 'is invalid when passed an invalid coupon code' do
|
|
327
|
+
invalid_coupon_atts = valid_order_with_new_subscription_coupon_attributes.tap { |x| x[:effective_order]['order_items_attributes']['0']['stripe_coupon_id'] = 'SOMETHING INVALID' }
|
|
328
|
+
|
|
329
|
+
post :create, invalid_coupon_atts
|
|
330
|
+
|
|
331
|
+
assigns(:order).errors['order_items.purchasable'].present?.should eq true
|
|
332
|
+
assigns(:order).errors['order_items.purchasable.stripe_coupon_id'].present?.should eq true
|
|
333
|
+
assigns(:order).persisted?.should eq false
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
describe '#order_purchased (with a free order)' do
|
|
338
|
+
before(:each) do
|
|
339
|
+
sign_in cart.user
|
|
340
|
+
cart.cart_items.each { |cart_item| cart_item.purchasable.update_attributes(:price => 0.0) }
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it 'creates a purchased order' do
|
|
344
|
+
post :create, valid_order_attributes
|
|
345
|
+
assigns(:order).purchased?.should eq true
|
|
346
|
+
assigns(:order).payment[:details].should eq 'zero-dollar order'
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it 'destroys the current user cart' do
|
|
350
|
+
post :create, valid_order_attributes
|
|
351
|
+
|
|
352
|
+
expect { Effective::Cart.find(cart.id) }.to raise_error(ActiveRecord::RecordNotFound)
|
|
353
|
+
assigns(:cart).cart_items.size.should eq 0
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it 'redirects to the purchased page' do
|
|
357
|
+
post :create, valid_order_attributes
|
|
358
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}/purchased"
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
describe '#show' do
|
|
363
|
+
|
|
364
|
+
it 'finds the order by obfuscated ID' do
|
|
365
|
+
sign_in purchased_order.user
|
|
366
|
+
get :show, :id => purchased_order.to_param
|
|
367
|
+
assigns(:order).id.should eq purchased_order.id
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it 'does not find an order by regular ID' do
|
|
371
|
+
sign_in purchased_order.user
|
|
372
|
+
expect { get :show, :id => purchased_order.id }.to raise_error(ActiveRecord::RecordNotFound)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it 'renders the show template for a purchased order' do
|
|
376
|
+
sign_in purchased_order.user
|
|
377
|
+
get :show, :id => purchased_order.to_param
|
|
378
|
+
response.should render_template(:show)
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
it 'renders the checkout template for a non-purchased order' do
|
|
382
|
+
sign_in order.user
|
|
383
|
+
get :show, :id => order.to_param
|
|
384
|
+
response.should render_template(:checkout)
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
describe '#purchased' do
|
|
389
|
+
before(:each) do
|
|
390
|
+
sign_in purchased_order.user
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it 'finds the order by obfuscated ID' do
|
|
394
|
+
get :purchased, :id => purchased_order.to_param
|
|
395
|
+
assigns(:order).id.should eq purchased_order.id
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it 'does not find an order by regular ID' do
|
|
399
|
+
expect { get :purchased, :id => purchased_order.id }.to raise_error(ActiveRecord::RecordNotFound)
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
describe '#declined' do
|
|
404
|
+
before(:each) do
|
|
405
|
+
sign_in purchased_order.user
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
it 'finds the order by obfuscated ID' do
|
|
409
|
+
get :declined, :id => purchased_order.to_param
|
|
410
|
+
assigns(:order).id.should eq purchased_order.id
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
it 'does not find an order by regular ID' do
|
|
414
|
+
expect { get :declined, :id => purchased_order.id }.to raise_error(ActiveRecord::RecordNotFound)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# We're testing the effective/providers/stripe.rb file, which is included into the OrdersController at runtime
|
|
4
|
+
|
|
5
|
+
describe Effective::OrdersController do
|
|
6
|
+
routes { EffectiveOrders::Engine.routes }
|
|
7
|
+
|
|
8
|
+
before { StripeMock.start }
|
|
9
|
+
after { StripeMock.stop }
|
|
10
|
+
|
|
11
|
+
let(:order) { FactoryGirl.create(:order) }
|
|
12
|
+
let(:buyer) { Effective::Customer.for_user(order.user) }
|
|
13
|
+
let(:token) { 'tok_123456789' }
|
|
14
|
+
let(:stripe_charge_params) do
|
|
15
|
+
{:effective_stripe_charge => {'effective_order_id' => order.to_param, 'token' => token}}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#stripe_charge' do
|
|
19
|
+
before do
|
|
20
|
+
sign_in order.user
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'invalid parameters' do
|
|
24
|
+
it 'raises RecordNotFound when passed an unknown order id' do
|
|
25
|
+
expect {
|
|
26
|
+
post :stripe_charge, stripe_charge_params.tap { |x| x[:effective_stripe_charge]['effective_order_id'] = 999 }
|
|
27
|
+
}.to raise_error(ActiveRecord::RecordNotFound)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'renders the :create action on validation failure' do
|
|
31
|
+
subject.should_not_receive(:process_stripe_charge)
|
|
32
|
+
|
|
33
|
+
post :stripe_charge, stripe_charge_params.tap { |x| x[:effective_stripe_charge]['token'] = nil }
|
|
34
|
+
|
|
35
|
+
flash[:danger].downcase.include?('token').should eq true
|
|
36
|
+
assigns(:stripe_charge).errors[:token].present?.should eq true
|
|
37
|
+
|
|
38
|
+
assigns(:order).purchased?.should eq false
|
|
39
|
+
response.should render_template(:checkout)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe 'valid parameters' do
|
|
44
|
+
it 'redirects to order_purchase_path on success' do
|
|
45
|
+
post :stripe_charge, stripe_charge_params
|
|
46
|
+
assigns(:order).purchased?.should eq true
|
|
47
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}/purchased"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'assigns the @stripe_charge, @order and @buyer properly' do
|
|
51
|
+
post :stripe_charge, stripe_charge_params
|
|
52
|
+
|
|
53
|
+
assigns(:stripe_charge).valid?.should eq true
|
|
54
|
+
assigns(:stripe_charge).order.should eq order
|
|
55
|
+
assigns(:order).should eq order
|
|
56
|
+
assigns(:buyer).should eq buyer
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'calls process_stripe_charge when the stripe_charge form object is valid' do
|
|
60
|
+
subject.should_receive(:process_stripe_charge)
|
|
61
|
+
post :stripe_charge, stripe_charge_params
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'assigns the buyer a new card based on the passed token' do
|
|
65
|
+
Effective::Customer.any_instance.should_receive(:update_card!).with(token)
|
|
66
|
+
post :stripe_charge, stripe_charge_params
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'stores the Stripe::Charge info in the order.payment' do
|
|
70
|
+
post :stripe_charge, stripe_charge_params
|
|
71
|
+
assigns(:order).payment[:charge]['object'].should eq 'charge'
|
|
72
|
+
assigns(:order).payment[:charge]['amount'].should eq order.total
|
|
73
|
+
assigns(:order).payment[:charge]['customer'].should eq buyer.stripe_customer_id
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe 'stripe charge errors' do
|
|
78
|
+
it 'rollsback the entire transaction when Stripe::Charge fails' do
|
|
79
|
+
StripeMock.prepare_card_error(:card_declined)
|
|
80
|
+
|
|
81
|
+
post :stripe_charge, stripe_charge_params
|
|
82
|
+
|
|
83
|
+
assigns(:order).purchased?.should eq false
|
|
84
|
+
assigns(:stripe_charge).errors[:base].first.downcase.include?('unable to process order with stripe').should eq true
|
|
85
|
+
assigns(:stripe_charge).errors[:base].first.downcase.include?('the card was declined').should eq true
|
|
86
|
+
response.should render_template(:checkout)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe '#stripe_charge with a subscription' do
|
|
92
|
+
let(:order) { FactoryGirl.create(:order_with_subscription) }
|
|
93
|
+
let(:buyer) { Effective::Customer.for_user(order.user) }
|
|
94
|
+
let(:subscription) { order.order_items[1].purchasable }
|
|
95
|
+
let(:token) { 'tok_123456789' }
|
|
96
|
+
let(:stripe_charge_params) do
|
|
97
|
+
{:effective_stripe_charge => {'effective_order_id' => order.to_param, 'token' => token}}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
before do
|
|
101
|
+
sign_in order.user
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'redirects to order_purchase_path on success' do
|
|
105
|
+
post :stripe_charge, stripe_charge_params
|
|
106
|
+
assigns(:order).purchased?.should eq true
|
|
107
|
+
response.should redirect_to "/orders/#{assigns(:order).to_param}/purchased"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'makes a Stripe::Charge for only the non-Subscription OrderItems' do
|
|
111
|
+
post :stripe_charge, stripe_charge_params
|
|
112
|
+
assigns(:order).payment[:charge]['object'].should eq 'charge'
|
|
113
|
+
assigns(:order).payment[:charge]['amount'].should eq order.order_items.first.total
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'makes a Stripe::Subscription for the Subscriptions' do
|
|
117
|
+
post :stripe_charge, stripe_charge_params
|
|
118
|
+
|
|
119
|
+
assigns(:order).payment[:subscriptions]["#{subscription.stripe_plan_id}"]['object'].should eq 'subscription'
|
|
120
|
+
assigns(:order).payment[:subscriptions]["#{subscription.stripe_plan_id}"]['plan'].should eq subscription.stripe_plan_id
|
|
121
|
+
subscription.reload.stripe_subscription_id.present?.should eq true
|
|
122
|
+
subscription.reload.stripe_coupon_id.present?.should eq true
|
|
123
|
+
|
|
124
|
+
Effective::Subscription.find(subscription.id).purchased?.should eq true
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Effective::WebhooksController do
|
|
4
|
+
routes { EffectiveOrders::Engine.routes }
|
|
5
|
+
|
|
6
|
+
before { StripeMock.start }
|
|
7
|
+
after { StripeMock.stop }
|
|
8
|
+
|
|
9
|
+
let(:order) { FactoryGirl.create(:order) }
|
|
10
|
+
let(:buyer) { Effective::Customer.for_user(order.user) }
|
|
11
|
+
|
|
12
|
+
let(:event) { StripeMock.mock_webhook_event('customer.subscription.created') }
|
|
13
|
+
let(:event_hash) { event.to_hash }
|
|
14
|
+
|
|
15
|
+
describe '#stripe' do
|
|
16
|
+
it 'retrieves the real event from Stripe based on passed ID' do
|
|
17
|
+
Stripe::Event.should_receive(:retrieve).with(event_hash[:id])
|
|
18
|
+
post :stripe, event_hash
|
|
19
|
+
response.code.should eq '200'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'assigns the @event based on the passed ID' do
|
|
23
|
+
post :stripe, event_hash
|
|
24
|
+
assigns(:event).id.should eq event_hash[:id]
|
|
25
|
+
response.code.should eq '200'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'exits immediately when passed a livemode=false event in Production' do
|
|
29
|
+
event_hash[:livemode] = false
|
|
30
|
+
Rails.env.stub(:production?).and_return(true)
|
|
31
|
+
|
|
32
|
+
post :stripe, event_hash
|
|
33
|
+
assigns(:event).should eq nil
|
|
34
|
+
response.code.should eq '200'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'exits immediately when passed a non-object event' do
|
|
38
|
+
event_hash[:object] = 'not-object'
|
|
39
|
+
|
|
40
|
+
post :stripe, event_hash
|
|
41
|
+
assigns(:event).should eq nil
|
|
42
|
+
response.code.should eq '200'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '#stripe.subscription_created' do
|
|
48
|
+
before(:each) do
|
|
49
|
+
buyer.update_attributes(:stripe_customer_id => event.data.object.customer)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'assigns the existing customer, if exists' do
|
|
53
|
+
post :stripe, event_hash
|
|
54
|
+
assigns(:customer).should eq buyer
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'creates a new purchased Order for the Subscription' do
|
|
58
|
+
Effective::Subscription.any_instance.stub(:valid?).and_return(true)
|
|
59
|
+
Effective::Subscription.any_instance.stub(:purchased?).and_return(false)
|
|
60
|
+
|
|
61
|
+
post :stripe, event_hash
|
|
62
|
+
|
|
63
|
+
assigns(:order).purchased?.should eq true
|
|
64
|
+
assigns(:order).user.should eq buyer.user
|
|
65
|
+
assigns(:order).payment.to_s.include?(event_hash[:id]).should eq true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'does not create an Order for an existing purchased Subscription' do
|
|
69
|
+
Effective::Subscription.any_instance.stub(:valid?).and_return(true)
|
|
70
|
+
Effective::Subscription.any_instance.stub(:purchased?).and_return(true)
|
|
71
|
+
|
|
72
|
+
post :stripe, event_hash
|
|
73
|
+
|
|
74
|
+
assigns(:order).present?.should eq false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
data/spec/dummy/Rakefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// compiled file.
|
|
9
|
+
//
|
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
|
11
|
+
// about supported directives.
|
|
12
|
+
//
|
|
13
|
+
//= require_tree .
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
11
|
+
* file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|