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.
Files changed (146) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +856 -0
  4. data/Rakefile +24 -0
  5. data/app/assets/images/effective_orders/stripe_connect.png +0 -0
  6. data/app/assets/javascripts/effective_orders/shipping_address_toggle.js.coffee +30 -0
  7. data/app/assets/javascripts/effective_orders/stripe_charges.js.coffee +26 -0
  8. data/app/assets/javascripts/effective_orders/stripe_subscriptions.js.coffee +28 -0
  9. data/app/assets/javascripts/effective_orders.js +2 -0
  10. data/app/assets/stylesheets/effective_orders/_order.scss +30 -0
  11. data/app/assets/stylesheets/effective_orders.css.scss +1 -0
  12. data/app/controllers/admin/customers_controller.rb +15 -0
  13. data/app/controllers/admin/orders_controller.rb +22 -0
  14. data/app/controllers/effective/carts_controller.rb +70 -0
  15. data/app/controllers/effective/orders_controller.rb +191 -0
  16. data/app/controllers/effective/providers/moneris.rb +94 -0
  17. data/app/controllers/effective/providers/paypal.rb +29 -0
  18. data/app/controllers/effective/providers/stripe.rb +125 -0
  19. data/app/controllers/effective/providers/stripe_connect.rb +47 -0
  20. data/app/controllers/effective/subscriptions_controller.rb +123 -0
  21. data/app/controllers/effective/webhooks_controller.rb +86 -0
  22. data/app/helpers/effective_carts_helper.rb +90 -0
  23. data/app/helpers/effective_orders_helper.rb +108 -0
  24. data/app/helpers/effective_paypal_helper.rb +37 -0
  25. data/app/helpers/effective_stripe_helper.rb +63 -0
  26. data/app/mailers/effective/orders_mailer.rb +64 -0
  27. data/app/models/concerns/acts_as_purchasable.rb +134 -0
  28. data/app/models/effective/access_denied.rb +17 -0
  29. data/app/models/effective/cart.rb +65 -0
  30. data/app/models/effective/cart_item.rb +40 -0
  31. data/app/models/effective/customer.rb +61 -0
  32. data/app/models/effective/datatables/customers.rb +45 -0
  33. data/app/models/effective/datatables/orders.rb +53 -0
  34. data/app/models/effective/order.rb +247 -0
  35. data/app/models/effective/order_item.rb +69 -0
  36. data/app/models/effective/stripe_charge.rb +35 -0
  37. data/app/models/effective/subscription.rb +95 -0
  38. data/app/models/inputs/price_field.rb +63 -0
  39. data/app/models/inputs/price_form_input.rb +7 -0
  40. data/app/models/inputs/price_formtastic_input.rb +9 -0
  41. data/app/models/inputs/price_input.rb +19 -0
  42. data/app/models/inputs/price_simple_form_input.rb +8 -0
  43. data/app/models/validators/effective/sold_out_validator.rb +7 -0
  44. data/app/views/active_admin/effective_orders/orders/_show.html.haml +70 -0
  45. data/app/views/admin/customers/_actions.html.haml +2 -0
  46. data/app/views/admin/customers/index.html.haml +10 -0
  47. data/app/views/admin/orders/index.html.haml +7 -0
  48. data/app/views/admin/orders/show.html.haml +11 -0
  49. data/app/views/effective/carts/_cart.html.haml +33 -0
  50. data/app/views/effective/carts/show.html.haml +18 -0
  51. data/app/views/effective/orders/_checkout_step_1.html.haml +39 -0
  52. data/app/views/effective/orders/_checkout_step_2.html.haml +18 -0
  53. data/app/views/effective/orders/_my_purchases.html.haml +15 -0
  54. data/app/views/effective/orders/_order.html.haml +4 -0
  55. data/app/views/effective/orders/_order_header.html.haml +21 -0
  56. data/app/views/effective/orders/_order_items.html.haml +39 -0
  57. data/app/views/effective/orders/_order_payment_details.html.haml +11 -0
  58. data/app/views/effective/orders/_order_shipping.html.haml +19 -0
  59. data/app/views/effective/orders/_order_user_fields.html.haml +10 -0
  60. data/app/views/effective/orders/checkout.html.haml +3 -0
  61. data/app/views/effective/orders/declined.html.haml +10 -0
  62. data/app/views/effective/orders/moneris/_form.html.haml +34 -0
  63. data/app/views/effective/orders/my_purchases.html.haml +6 -0
  64. data/app/views/effective/orders/my_sales.html.haml +28 -0
  65. data/app/views/effective/orders/new.html.haml +4 -0
  66. data/app/views/effective/orders/paypal/_form.html.haml +5 -0
  67. data/app/views/effective/orders/purchased.html.haml +10 -0
  68. data/app/views/effective/orders/show.html.haml +17 -0
  69. data/app/views/effective/orders/stripe/_form.html.haml +8 -0
  70. data/app/views/effective/orders/stripe/_subscription_fields.html.haml +7 -0
  71. data/app/views/effective/orders_mailer/order_receipt_to_admin.html.haml +8 -0
  72. data/app/views/effective/orders_mailer/order_receipt_to_buyer.html.haml +8 -0
  73. data/app/views/effective/orders_mailer/order_receipt_to_seller.html.haml +30 -0
  74. data/app/views/effective/subscriptions/index.html.haml +16 -0
  75. data/app/views/effective/subscriptions/new.html.haml +10 -0
  76. data/app/views/effective/subscriptions/show.html.haml +49 -0
  77. data/config/routes.rb +57 -0
  78. data/db/migrate/01_create_effective_orders.rb.erb +91 -0
  79. data/db/upgrade/02_upgrade_effective_orders_from03x.rb.erb +29 -0
  80. data/db/upgrade/upgrade_price_column_on_table.rb.erb +17 -0
  81. data/lib/effective_orders/engine.rb +52 -0
  82. data/lib/effective_orders/version.rb +3 -0
  83. data/lib/effective_orders.rb +76 -0
  84. data/lib/generators/effective_orders/install_generator.rb +38 -0
  85. data/lib/generators/effective_orders/upgrade_from03x_generator.rb +34 -0
  86. data/lib/generators/effective_orders/upgrade_price_column_generator.rb +34 -0
  87. data/lib/generators/templates/README +1 -0
  88. data/lib/generators/templates/effective_orders.rb +210 -0
  89. data/spec/controllers/carts_controller_spec.rb +143 -0
  90. data/spec/controllers/moneris_orders_controller_spec.rb +245 -0
  91. data/spec/controllers/orders_controller_spec.rb +418 -0
  92. data/spec/controllers/stripe_orders_controller_spec.rb +127 -0
  93. data/spec/controllers/webhooks_controller_spec.rb +79 -0
  94. data/spec/dummy/README.rdoc +8 -0
  95. data/spec/dummy/Rakefile +6 -0
  96. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  97. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  98. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  99. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  100. data/spec/dummy/app/models/product.rb +17 -0
  101. data/spec/dummy/app/models/product_with_float_price.rb +17 -0
  102. data/spec/dummy/app/models/user.rb +28 -0
  103. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  104. data/spec/dummy/bin/bundle +3 -0
  105. data/spec/dummy/bin/rails +4 -0
  106. data/spec/dummy/bin/rake +4 -0
  107. data/spec/dummy/config/application.rb +31 -0
  108. data/spec/dummy/config/boot.rb +5 -0
  109. data/spec/dummy/config/database.yml +25 -0
  110. data/spec/dummy/config/environment.rb +5 -0
  111. data/spec/dummy/config/environments/development.rb +37 -0
  112. data/spec/dummy/config/environments/production.rb +83 -0
  113. data/spec/dummy/config/environments/test.rb +39 -0
  114. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  115. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  116. data/spec/dummy/config/initializers/devise.rb +254 -0
  117. data/spec/dummy/config/initializers/effective_addresses.rb +15 -0
  118. data/spec/dummy/config/initializers/effective_orders.rb +22 -0
  119. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  120. data/spec/dummy/config/initializers/inflections.rb +16 -0
  121. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  122. data/spec/dummy/config/initializers/session_store.rb +3 -0
  123. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  124. data/spec/dummy/config/locales/en.yml +23 -0
  125. data/spec/dummy/config/routes.rb +3 -0
  126. data/spec/dummy/config/secrets.yml +22 -0
  127. data/spec/dummy/config.ru +4 -0
  128. data/spec/dummy/db/schema.rb +142 -0
  129. data/spec/dummy/db/test.sqlite3 +0 -0
  130. data/spec/dummy/log/development.log +487 -0
  131. data/spec/dummy/log/test.log +347 -0
  132. data/spec/dummy/public/404.html +67 -0
  133. data/spec/dummy/public/422.html +67 -0
  134. data/spec/dummy/public/500.html +66 -0
  135. data/spec/dummy/public/favicon.ico +0 -0
  136. data/spec/helpers/effective_orders_helper_spec.rb +21 -0
  137. data/spec/models/acts_as_purchasable_spec.rb +107 -0
  138. data/spec/models/customer_spec.rb +71 -0
  139. data/spec/models/factories_spec.rb +13 -0
  140. data/spec/models/order_item_spec.rb +35 -0
  141. data/spec/models/order_spec.rb +323 -0
  142. data/spec/models/stripe_charge_spec.rb +39 -0
  143. data/spec/models/subscription_spec.rb +103 -0
  144. data/spec/spec_helper.rb +44 -0
  145. data/spec/support/factories.rb +118 -0
  146. 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
@@ -0,0 +1,8 @@
1
+ == README
2
+
3
+ To change the test database in this dummy app:
4
+
5
+ - Delete the existing test.sqlite3
6
+ - No migrations, so just make whatever changes you want to schema.rb
7
+
8
+ bundle exec rake app:db:test:prepare
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -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
+ */
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end