spree_frontend 3.1.14 → 3.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (336) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/logo/spree_50.png +0 -0
  3. data/app/assets/javascripts/spree/frontend/cart.js.coffee +14 -1
  4. data/app/assets/javascripts/spree/frontend/checkout/payment.js.coffee +11 -35
  5. data/app/assets/javascripts/spree/frontend/checkout/shipment.js.coffee +38 -0
  6. data/app/assets/javascripts/spree/frontend/coupon_manager.js.coffee +37 -0
  7. data/app/assets/stylesheets/spree/frontend/frontend_bootstrap.css.scss +3 -3
  8. data/app/controllers/spree/checkout_controller.rb +0 -14
  9. data/app/controllers/spree/content_controller.rb +3 -3
  10. data/app/controllers/spree/orders_controller.rb +7 -2
  11. data/app/controllers/spree/products_controller.rb +3 -2
  12. data/app/controllers/spree/store_controller.rb +0 -18
  13. data/app/helpers/spree/frontend_helper.rb +1 -1
  14. data/app/helpers/spree/orders_helper.rb +0 -9
  15. data/app/views/kaminari/twitter-bootstrap-3/_first_page.html.erb +1 -1
  16. data/app/views/kaminari/twitter-bootstrap-3/_last_page.html.erb +1 -1
  17. data/app/views/kaminari/twitter-bootstrap-3/_next_page.html.erb +1 -1
  18. data/app/views/kaminari/twitter-bootstrap-3/_page.html.erb +1 -1
  19. data/app/views/kaminari/twitter-bootstrap-3/_prev_page.html.erb +1 -1
  20. data/app/views/spree/address/_form.html.erb +16 -16
  21. data/app/views/spree/checkout/_address.html.erb +4 -4
  22. data/app/views/spree/checkout/_confirm.html.erb +2 -2
  23. data/app/views/spree/checkout/_delivery.html.erb +5 -3
  24. data/app/views/spree/checkout/_payment.html.erb +3 -3
  25. data/app/views/spree/checkout/_summary.html.erb +3 -3
  26. data/app/views/spree/checkout/edit.html.erb +1 -0
  27. data/app/views/spree/checkout/payment/_gateway.html.erb +8 -8
  28. data/app/views/spree/home/index.html.erb +3 -2
  29. data/app/views/spree/orders/_adjustment_row.html.erb +1 -1
  30. data/app/views/spree/orders/_adjustments.html.erb +3 -3
  31. data/app/views/spree/orders/edit.html.erb +15 -2
  32. data/app/views/spree/products/_properties.html.erb +1 -1
  33. data/app/views/spree/products/index.html.erb +5 -5
  34. data/app/views/spree/products/show.html.erb +6 -6
  35. data/app/views/spree/shared/_address.html.erb +3 -1
  36. data/app/views/spree/shared/_error_messages.html.erb +1 -1
  37. data/app/views/spree/shared/_filters.html.erb +2 -2
  38. data/app/views/spree/shared/_google_add_items.js.erb +5 -5
  39. data/app/views/spree/shared/_head.html.erb +2 -0
  40. data/app/views/spree/shared/_header.html.erb +2 -2
  41. data/app/views/spree/shared/_login.html.erb +4 -4
  42. data/app/views/spree/shared/_nav_bar.html.erb +1 -1
  43. data/app/views/spree/shared/_order_details.html.erb +2 -2
  44. data/app/views/spree/shared/_search.html.erb +3 -3
  45. data/app/views/spree/shared/_translations.html.erb +7 -0
  46. data/config/initializers/assets.rb +1 -1
  47. data/config/routes.rb +1 -6
  48. data/lib/tasks/taxon.rake +2 -2
  49. data/spec/controllers/controller_extension_spec.rb +126 -0
  50. data/spec/controllers/controller_helpers_spec.rb +122 -0
  51. data/spec/controllers/spree/checkout_controller_spec.rb +462 -0
  52. data/spec/controllers/spree/checkout_controller_with_views_spec.rb +36 -0
  53. data/spec/controllers/spree/content_controller_spec.rb +12 -0
  54. data/spec/controllers/spree/current_order_tracking_spec.rb +44 -0
  55. data/spec/controllers/spree/home_controller_spec.rb +47 -0
  56. data/spec/controllers/spree/orders_controller_ability_spec.rb +96 -0
  57. data/spec/controllers/spree/orders_controller_spec.rb +134 -0
  58. data/spec/controllers/spree/orders_controller_transitions_spec.rb +31 -0
  59. data/spec/controllers/spree/products_controller_spec.rb +87 -0
  60. data/spec/controllers/spree/taxons_controller_spec.rb +12 -0
  61. data/spec/features/address_spec.rb +93 -0
  62. data/spec/features/automatic_promotion_adjustments_spec.rb +47 -0
  63. data/spec/features/caching/products_spec.rb +59 -0
  64. data/spec/features/caching/taxons_spec.rb +22 -0
  65. data/spec/features/cart_spec.rb +132 -0
  66. data/spec/features/checkout_spec.rb +572 -0
  67. data/spec/features/checkout_unshippable_spec.rb +34 -0
  68. data/spec/features/coupon_code_spec.rb +88 -0
  69. data/spec/features/currency_spec.rb +18 -0
  70. data/spec/features/delivery_spec.rb +64 -0
  71. data/spec/features/free_shipping_promotions_spec.rb +59 -0
  72. data/spec/features/locale_spec.rb +60 -0
  73. data/spec/features/microdata_spec.rb +0 -0
  74. data/spec/features/order_spec.rb +107 -0
  75. data/spec/features/page_promotions_spec.rb +36 -0
  76. data/spec/features/products_spec.rb +334 -0
  77. data/spec/features/taxons_spec.rb +147 -0
  78. data/spec/features/template_rendering_spec.rb +19 -0
  79. data/spec/helpers/frontend_helper_spec.rb +57 -0
  80. data/spec/helpers/taxons_helper_spec.rb +17 -0
  81. data/spec/spec_helper.rb +126 -0
  82. data/spec/support/shared_contexts/checkout_setup.rb +10 -0
  83. data/spec/support/shared_contexts/custom_products.rb +25 -0
  84. data/spec/support/shared_contexts/product_prototypes.rb +30 -0
  85. data/spec/views/spree/checkout/_summary_spec.rb +11 -0
  86. data/spree_frontend.gemspec +6 -3
  87. metadata +92 -263
  88. data/app/assets/images/flags/ad.png +0 -0
  89. data/app/assets/images/flags/ae.png +0 -0
  90. data/app/assets/images/flags/af.png +0 -0
  91. data/app/assets/images/flags/ag.png +0 -0
  92. data/app/assets/images/flags/ai.png +0 -0
  93. data/app/assets/images/flags/al.png +0 -0
  94. data/app/assets/images/flags/am.png +0 -0
  95. data/app/assets/images/flags/an.png +0 -0
  96. data/app/assets/images/flags/ao.png +0 -0
  97. data/app/assets/images/flags/ar.png +0 -0
  98. data/app/assets/images/flags/as.png +0 -0
  99. data/app/assets/images/flags/at.png +0 -0
  100. data/app/assets/images/flags/au.png +0 -0
  101. data/app/assets/images/flags/aw.png +0 -0
  102. data/app/assets/images/flags/ax.png +0 -0
  103. data/app/assets/images/flags/az.png +0 -0
  104. data/app/assets/images/flags/ba.png +0 -0
  105. data/app/assets/images/flags/bb.png +0 -0
  106. data/app/assets/images/flags/bd.png +0 -0
  107. data/app/assets/images/flags/be.png +0 -0
  108. data/app/assets/images/flags/bf.png +0 -0
  109. data/app/assets/images/flags/bg.png +0 -0
  110. data/app/assets/images/flags/bh.png +0 -0
  111. data/app/assets/images/flags/bi.png +0 -0
  112. data/app/assets/images/flags/bj.png +0 -0
  113. data/app/assets/images/flags/bm.png +0 -0
  114. data/app/assets/images/flags/bn.png +0 -0
  115. data/app/assets/images/flags/bo.png +0 -0
  116. data/app/assets/images/flags/br.png +0 -0
  117. data/app/assets/images/flags/bs.png +0 -0
  118. data/app/assets/images/flags/bt.png +0 -0
  119. data/app/assets/images/flags/bv.png +0 -0
  120. data/app/assets/images/flags/bw.png +0 -0
  121. data/app/assets/images/flags/by.png +0 -0
  122. data/app/assets/images/flags/bz.png +0 -0
  123. data/app/assets/images/flags/ca.png +0 -0
  124. data/app/assets/images/flags/catalonia.png +0 -0
  125. data/app/assets/images/flags/cc.png +0 -0
  126. data/app/assets/images/flags/cd.png +0 -0
  127. data/app/assets/images/flags/cf.png +0 -0
  128. data/app/assets/images/flags/cg.png +0 -0
  129. data/app/assets/images/flags/ch.png +0 -0
  130. data/app/assets/images/flags/ci.png +0 -0
  131. data/app/assets/images/flags/ck.png +0 -0
  132. data/app/assets/images/flags/cl.png +0 -0
  133. data/app/assets/images/flags/cm.png +0 -0
  134. data/app/assets/images/flags/cn.png +0 -0
  135. data/app/assets/images/flags/co.png +0 -0
  136. data/app/assets/images/flags/cr.png +0 -0
  137. data/app/assets/images/flags/cs.png +0 -0
  138. data/app/assets/images/flags/cu.png +0 -0
  139. data/app/assets/images/flags/cv.png +0 -0
  140. data/app/assets/images/flags/cx.png +0 -0
  141. data/app/assets/images/flags/cy.png +0 -0
  142. data/app/assets/images/flags/cz.png +0 -0
  143. data/app/assets/images/flags/de.png +0 -0
  144. data/app/assets/images/flags/dj.png +0 -0
  145. data/app/assets/images/flags/dk.png +0 -0
  146. data/app/assets/images/flags/dm.png +0 -0
  147. data/app/assets/images/flags/do.png +0 -0
  148. data/app/assets/images/flags/dz.png +0 -0
  149. data/app/assets/images/flags/ec.png +0 -0
  150. data/app/assets/images/flags/ee.png +0 -0
  151. data/app/assets/images/flags/eg.png +0 -0
  152. data/app/assets/images/flags/eh.png +0 -0
  153. data/app/assets/images/flags/england.png +0 -0
  154. data/app/assets/images/flags/er.png +0 -0
  155. data/app/assets/images/flags/es.png +0 -0
  156. data/app/assets/images/flags/et.png +0 -0
  157. data/app/assets/images/flags/europeanunion.png +0 -0
  158. data/app/assets/images/flags/fam.png +0 -0
  159. data/app/assets/images/flags/fi.png +0 -0
  160. data/app/assets/images/flags/fj.png +0 -0
  161. data/app/assets/images/flags/fk.png +0 -0
  162. data/app/assets/images/flags/fm.png +0 -0
  163. data/app/assets/images/flags/fo.png +0 -0
  164. data/app/assets/images/flags/fr.png +0 -0
  165. data/app/assets/images/flags/ga.png +0 -0
  166. data/app/assets/images/flags/gb.png +0 -0
  167. data/app/assets/images/flags/gd.png +0 -0
  168. data/app/assets/images/flags/ge.png +0 -0
  169. data/app/assets/images/flags/gf.png +0 -0
  170. data/app/assets/images/flags/gh.png +0 -0
  171. data/app/assets/images/flags/gi.png +0 -0
  172. data/app/assets/images/flags/gl.png +0 -0
  173. data/app/assets/images/flags/gm.png +0 -0
  174. data/app/assets/images/flags/gn.png +0 -0
  175. data/app/assets/images/flags/gp.png +0 -0
  176. data/app/assets/images/flags/gq.png +0 -0
  177. data/app/assets/images/flags/gr.png +0 -0
  178. data/app/assets/images/flags/gs.png +0 -0
  179. data/app/assets/images/flags/gt.png +0 -0
  180. data/app/assets/images/flags/gu.png +0 -0
  181. data/app/assets/images/flags/gw.png +0 -0
  182. data/app/assets/images/flags/gy.png +0 -0
  183. data/app/assets/images/flags/hk.png +0 -0
  184. data/app/assets/images/flags/hm.png +0 -0
  185. data/app/assets/images/flags/hn.png +0 -0
  186. data/app/assets/images/flags/hr.png +0 -0
  187. data/app/assets/images/flags/ht.png +0 -0
  188. data/app/assets/images/flags/hu.png +0 -0
  189. data/app/assets/images/flags/id.png +0 -0
  190. data/app/assets/images/flags/ie.png +0 -0
  191. data/app/assets/images/flags/il.png +0 -0
  192. data/app/assets/images/flags/in.png +0 -0
  193. data/app/assets/images/flags/io.png +0 -0
  194. data/app/assets/images/flags/iq.png +0 -0
  195. data/app/assets/images/flags/ir.png +0 -0
  196. data/app/assets/images/flags/is.png +0 -0
  197. data/app/assets/images/flags/it.png +0 -0
  198. data/app/assets/images/flags/ja.png +0 -0
  199. data/app/assets/images/flags/jm.png +0 -0
  200. data/app/assets/images/flags/jo.png +0 -0
  201. data/app/assets/images/flags/ke.png +0 -0
  202. data/app/assets/images/flags/kg.png +0 -0
  203. data/app/assets/images/flags/kh.png +0 -0
  204. data/app/assets/images/flags/ki.png +0 -0
  205. data/app/assets/images/flags/km.png +0 -0
  206. data/app/assets/images/flags/kn.png +0 -0
  207. data/app/assets/images/flags/kp.png +0 -0
  208. data/app/assets/images/flags/kr.png +0 -0
  209. data/app/assets/images/flags/kw.png +0 -0
  210. data/app/assets/images/flags/ky.png +0 -0
  211. data/app/assets/images/flags/kz.png +0 -0
  212. data/app/assets/images/flags/la.png +0 -0
  213. data/app/assets/images/flags/lb.png +0 -0
  214. data/app/assets/images/flags/lc.png +0 -0
  215. data/app/assets/images/flags/li.png +0 -0
  216. data/app/assets/images/flags/lk.png +0 -0
  217. data/app/assets/images/flags/lr.png +0 -0
  218. data/app/assets/images/flags/ls.png +0 -0
  219. data/app/assets/images/flags/lt.png +0 -0
  220. data/app/assets/images/flags/lu.png +0 -0
  221. data/app/assets/images/flags/lv.png +0 -0
  222. data/app/assets/images/flags/ly.png +0 -0
  223. data/app/assets/images/flags/ma.png +0 -0
  224. data/app/assets/images/flags/mc.png +0 -0
  225. data/app/assets/images/flags/md.png +0 -0
  226. data/app/assets/images/flags/me.png +0 -0
  227. data/app/assets/images/flags/mg.png +0 -0
  228. data/app/assets/images/flags/mh.png +0 -0
  229. data/app/assets/images/flags/mk.png +0 -0
  230. data/app/assets/images/flags/ml.png +0 -0
  231. data/app/assets/images/flags/mm.png +0 -0
  232. data/app/assets/images/flags/mn.png +0 -0
  233. data/app/assets/images/flags/mo.png +0 -0
  234. data/app/assets/images/flags/mp.png +0 -0
  235. data/app/assets/images/flags/mq.png +0 -0
  236. data/app/assets/images/flags/mr.png +0 -0
  237. data/app/assets/images/flags/ms.png +0 -0
  238. data/app/assets/images/flags/mt.png +0 -0
  239. data/app/assets/images/flags/mu.png +0 -0
  240. data/app/assets/images/flags/mv.png +0 -0
  241. data/app/assets/images/flags/mw.png +0 -0
  242. data/app/assets/images/flags/mx.png +0 -0
  243. data/app/assets/images/flags/my.png +0 -0
  244. data/app/assets/images/flags/mz.png +0 -0
  245. data/app/assets/images/flags/na.png +0 -0
  246. data/app/assets/images/flags/nc.png +0 -0
  247. data/app/assets/images/flags/ne.png +0 -0
  248. data/app/assets/images/flags/nf.png +0 -0
  249. data/app/assets/images/flags/ng.png +0 -0
  250. data/app/assets/images/flags/ni.png +0 -0
  251. data/app/assets/images/flags/nl.png +0 -0
  252. data/app/assets/images/flags/no.png +0 -0
  253. data/app/assets/images/flags/np.png +0 -0
  254. data/app/assets/images/flags/nr.png +0 -0
  255. data/app/assets/images/flags/nu.png +0 -0
  256. data/app/assets/images/flags/nz.png +0 -0
  257. data/app/assets/images/flags/om.png +0 -0
  258. data/app/assets/images/flags/pa.png +0 -0
  259. data/app/assets/images/flags/pe.png +0 -0
  260. data/app/assets/images/flags/pf.png +0 -0
  261. data/app/assets/images/flags/pg.png +0 -0
  262. data/app/assets/images/flags/ph.png +0 -0
  263. data/app/assets/images/flags/pk.png +0 -0
  264. data/app/assets/images/flags/pl.png +0 -0
  265. data/app/assets/images/flags/pm.png +0 -0
  266. data/app/assets/images/flags/pn.png +0 -0
  267. data/app/assets/images/flags/pr.png +0 -0
  268. data/app/assets/images/flags/ps.png +0 -0
  269. data/app/assets/images/flags/pt.png +0 -0
  270. data/app/assets/images/flags/pw.png +0 -0
  271. data/app/assets/images/flags/py.png +0 -0
  272. data/app/assets/images/flags/qa.png +0 -0
  273. data/app/assets/images/flags/re.png +0 -0
  274. data/app/assets/images/flags/ro.png +0 -0
  275. data/app/assets/images/flags/rs.png +0 -0
  276. data/app/assets/images/flags/ru.png +0 -0
  277. data/app/assets/images/flags/rw.png +0 -0
  278. data/app/assets/images/flags/sa.png +0 -0
  279. data/app/assets/images/flags/sb.png +0 -0
  280. data/app/assets/images/flags/sc.png +0 -0
  281. data/app/assets/images/flags/scotland.png +0 -0
  282. data/app/assets/images/flags/sd.png +0 -0
  283. data/app/assets/images/flags/se.png +0 -0
  284. data/app/assets/images/flags/sg.png +0 -0
  285. data/app/assets/images/flags/sh.png +0 -0
  286. data/app/assets/images/flags/si.png +0 -0
  287. data/app/assets/images/flags/sj.png +0 -0
  288. data/app/assets/images/flags/sk.png +0 -0
  289. data/app/assets/images/flags/sl.png +0 -0
  290. data/app/assets/images/flags/sm.png +0 -0
  291. data/app/assets/images/flags/sn.png +0 -0
  292. data/app/assets/images/flags/so.png +0 -0
  293. data/app/assets/images/flags/sr.png +0 -0
  294. data/app/assets/images/flags/st.png +0 -0
  295. data/app/assets/images/flags/sv.png +0 -0
  296. data/app/assets/images/flags/sy.png +0 -0
  297. data/app/assets/images/flags/sz.png +0 -0
  298. data/app/assets/images/flags/tc.png +0 -0
  299. data/app/assets/images/flags/td.png +0 -0
  300. data/app/assets/images/flags/tf.png +0 -0
  301. data/app/assets/images/flags/tg.png +0 -0
  302. data/app/assets/images/flags/th.png +0 -0
  303. data/app/assets/images/flags/tj.png +0 -0
  304. data/app/assets/images/flags/tk.png +0 -0
  305. data/app/assets/images/flags/tl.png +0 -0
  306. data/app/assets/images/flags/tm.png +0 -0
  307. data/app/assets/images/flags/tn.png +0 -0
  308. data/app/assets/images/flags/to.png +0 -0
  309. data/app/assets/images/flags/tr.png +0 -0
  310. data/app/assets/images/flags/tt.png +0 -0
  311. data/app/assets/images/flags/tv.png +0 -0
  312. data/app/assets/images/flags/tw.png +0 -0
  313. data/app/assets/images/flags/tz.png +0 -0
  314. data/app/assets/images/flags/ua.png +0 -0
  315. data/app/assets/images/flags/ug.png +0 -0
  316. data/app/assets/images/flags/um.png +0 -0
  317. data/app/assets/images/flags/us.png +0 -0
  318. data/app/assets/images/flags/uy.png +0 -0
  319. data/app/assets/images/flags/uz.png +0 -0
  320. data/app/assets/images/flags/va.png +0 -0
  321. data/app/assets/images/flags/vc.png +0 -0
  322. data/app/assets/images/flags/ve.png +0 -0
  323. data/app/assets/images/flags/vg.png +0 -0
  324. data/app/assets/images/flags/vi.png +0 -0
  325. data/app/assets/images/flags/vn.png +0 -0
  326. data/app/assets/images/flags/vu.png +0 -0
  327. data/app/assets/images/flags/wales.png +0 -0
  328. data/app/assets/images/flags/wf.png +0 -0
  329. data/app/assets/images/flags/ws.png +0 -0
  330. data/app/assets/images/flags/ye.png +0 -0
  331. data/app/assets/images/flags/yt.png +0 -0
  332. data/app/assets/images/flags/za.png +0 -0
  333. data/app/assets/images/flags/zm.png +0 -0
  334. data/app/assets/images/flags/zw.png +0 -0
  335. data/app/assets/images/spree_header.jpg +0 -0
  336. data/app/views/spree/products/_image.html.erb +0 -5
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::TaxonsController, type: :controller do
4
+ it "should provide the current user to the searcher class" do
5
+ taxon = create(:taxon, permalink: "test")
6
+ user = mock_model(Spree.user_class, last_incomplete_spree_order: nil, spree_api_key: 'fake')
7
+ allow(controller).to receive_messages spree_current_user: user
8
+ expect_any_instance_of(Spree::Config.searcher_class).to receive(:current_user=).with(user)
9
+ spree_get :show, id: taxon.permalink
10
+ expect(response.status).to eq(200)
11
+ end
12
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Address", type: :feature, inaccessible: true do
4
+ let!(:product) { create(:product, name: "RoR Mug") }
5
+ let!(:order) { create(:order_with_totals, state: 'cart') }
6
+
7
+ stub_authorization!
8
+
9
+ after do
10
+ Capybara.ignore_hidden_elements = true
11
+ end
12
+
13
+ before do
14
+ Capybara.ignore_hidden_elements = false
15
+
16
+ visit spree.root_path
17
+
18
+ click_link "RoR Mug"
19
+ click_button "add-to-cart-button"
20
+
21
+ address = "order_bill_address_attributes"
22
+ @country_css = "#{address}_country_id"
23
+ @state_select_css = "##{address}_state_id"
24
+ @state_name_css = "##{address}_state_name"
25
+ end
26
+
27
+ context "country requires state", js: true, focus: true do
28
+ let!(:canada) { create(:country, name: "Canada", states_required: true, iso: "CA") }
29
+ let!(:uk) { create(:country, name: "United Kingdom", states_required: true, iso: "UK") }
30
+
31
+ before { Spree::Config[:default_country_id] = uk.id }
32
+
33
+ context "but has no state" do
34
+ it "shows the state input field" do
35
+ click_button "Checkout"
36
+
37
+ select canada.name, from: @country_css
38
+ expect(page).to have_selector(@state_select_css, visible: false)
39
+ expect(page).to have_selector(@state_name_css, visible: true)
40
+ expect(find(@state_name_css)['class']).not_to match(/hidden/)
41
+ expect(find(@state_name_css)['class']).to match(/required/)
42
+ expect(find(@state_select_css)['class']).not_to match(/required/)
43
+ expect(page).not_to have_selector("input#{@state_name_css}[disabled]")
44
+ end
45
+ end
46
+
47
+ context "and has state" do
48
+ before { create(:state, name: "Ontario", country: canada) }
49
+
50
+ it "shows the state collection selection" do
51
+ click_button "Checkout"
52
+
53
+ select canada.name, from: @country_css
54
+ expect(page).to have_selector(@state_select_css, visible: true)
55
+ expect(page).to have_selector(@state_name_css, visible: false)
56
+ expect(find(@state_select_css)['class']).to match(/required/)
57
+ expect(find(@state_select_css)['class']).not_to match(/hidden/)
58
+ expect(find(@state_name_css)['class']).not_to match(/required/)
59
+ end
60
+ end
61
+
62
+ context "user changes to country without states required" do
63
+ let!(:france) { create(:country, name: "France", states_required: false, iso: "FRA") }
64
+
65
+ it "clears the state name" do
66
+ skip "This is failing on the CI server, but not when you run the tests manually... It also does not fail locally on a machine."
67
+ click_button "Checkout"
68
+ select canada.name, from: @country_css
69
+ page.find(@state_name_css).set("Toscana")
70
+
71
+ select france.name, from: @country_css
72
+ expect(page.find(@state_name_css)).to have_content('')
73
+ until page.evaluate_script("$.active").to_i == 0
74
+ expect(find(@state_name_css)['class']).not_to match(/hidden/)
75
+ expect(find(@state_name_css)['class']).not_to match(/required/)
76
+ expect(find(@state_select_css)['class']).not_to match(/required/)
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ context "country does not require state", js: true do
83
+ let!(:france) { create(:country, name: "France", states_required: false, iso: "FRA") }
84
+
85
+ it "shows a disabled state input field" do
86
+ click_button "Checkout"
87
+
88
+ select france.name, from: @country_css
89
+ expect(page).to have_selector(@state_select_css, visible: false)
90
+ expect(page).to have_selector(@state_name_css, visible: false)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Automatic promotions", type: :feature, js: true do
4
+ let!(:country) { create(:country, name: "United States of America", states_required: true) }
5
+ let!(:state) { create(:state, name: "Alabama", country: country) }
6
+ let!(:zone) { create(:zone) }
7
+ let!(:shipping_method) { create(:shipping_method) }
8
+ let!(:payment_method) { create(:check_payment_method) }
9
+ let!(:product) { create(:product, name: "RoR Mug", price: 20) }
10
+
11
+ let!(:promotion) do
12
+ promotion = Spree::Promotion.create!(name: "$10 off when you spend more than $100")
13
+
14
+ calculator = Spree::Calculator::FlatRate.new
15
+ calculator.preferred_amount = 10
16
+
17
+ rule = Spree::Promotion::Rules::ItemTotal.create
18
+ rule.preferred_amount_min = 100
19
+ rule.save
20
+
21
+ promotion.rules << rule
22
+
23
+ action = Spree::Promotion::Actions::CreateAdjustment.create
24
+ action.calculator = calculator
25
+ action.save
26
+
27
+ promotion.actions << action
28
+ end
29
+
30
+ context "on the cart page" do
31
+
32
+ before do
33
+ visit spree.root_path
34
+ click_link product.name
35
+ click_button "add-to-cart-button"
36
+ end
37
+
38
+ it "automatically applies the promotion once the order crosses the threshold" do
39
+ fill_in "order_line_items_attributes_0_quantity", with: 10
40
+ click_button "Update"
41
+ expect(page).to have_content("Promotion ($10 off when you spend more than $100) -$10.00")
42
+ fill_in "order_line_items_attributes_0_quantity", with: 1
43
+ click_button "Update"
44
+ expect(page).not_to have_content("Promotion ($10 off when you spend more than $100) -$10.00")
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'products', type: :feature, caching: true do
4
+ let!(:product) { create(:product) }
5
+ let!(:product2) { create(:product) }
6
+ let!(:taxonomy) { create(:taxonomy) }
7
+ let!(:taxon) { create(:taxon, taxonomy: taxonomy) }
8
+
9
+ before { Timecop.scale(1000) }
10
+
11
+ after { Timecop.return }
12
+
13
+ before do
14
+ product2.update_column(:updated_at, 1.day.ago)
15
+ # warm up the cache
16
+ visit spree.root_path
17
+ assert_written_to_cache("views/en/USD/spree/products/all--#{product.updated_at.utc.to_s(:number)}")
18
+ assert_written_to_cache("views/en/USD/spree/products/#{product.id}-#{product.updated_at.utc.to_s(:number)}")
19
+ assert_written_to_cache("views/en/spree/taxonomies/#{taxonomy.id}")
20
+ assert_written_to_cache("views/en/taxons/#{taxon.updated_at.utc.to_i}")
21
+
22
+ clear_cache_events
23
+ end
24
+
25
+ it "reads from cache upon a second viewing" do
26
+ visit spree.root_path
27
+ expect(cache_writes.count).to eq(0)
28
+ end
29
+
30
+ it "busts the cache when a product is updated" do
31
+ product.update_column(:updated_at, 1.day.from_now)
32
+ visit spree.root_path
33
+ assert_written_to_cache("views/en/USD/spree/products/all--#{product.updated_at.utc.to_s(:number)}")
34
+ assert_written_to_cache("views/en/USD/spree/products/#{product.id}-#{product.updated_at.utc.to_s(:number)}")
35
+ expect(cache_writes.count).to eq(2)
36
+ end
37
+
38
+ it "busts the cache when all products are deleted" do
39
+ product.destroy
40
+ product2.destroy
41
+ visit spree.root_path
42
+ assert_written_to_cache("views/en/USD/spree/products/all--#{Date.today.to_s(:number)}-0")
43
+ expect(cache_writes.count).to eq(1)
44
+ end
45
+
46
+ it "busts the cache when the newest product is deleted" do
47
+ product.destroy
48
+ visit spree.root_path
49
+ assert_written_to_cache("views/en/USD/spree/products/all--#{product2.updated_at.utc.to_s(:number)}")
50
+ expect(cache_writes.count).to eq(1)
51
+ end
52
+
53
+ it "busts the cache when an older product is deleted" do
54
+ product2.destroy
55
+ visit spree.root_path
56
+ assert_written_to_cache("views/en/USD/spree/products/all--#{product.updated_at.utc.to_s(:number)}")
57
+ expect(cache_writes.count).to eq(1)
58
+ end
59
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'taxons', type: :feature, caching: true do
4
+ let!(:taxonomy) { create(:taxonomy) }
5
+ let!(:taxon) { create(:taxon, taxonomy: taxonomy) }
6
+
7
+ before do
8
+ # warm up the cache
9
+ visit spree.root_path
10
+ assert_written_to_cache("views/en/spree/taxonomies/#{taxonomy.id}")
11
+ assert_written_to_cache("views/en/taxons/#{taxon.updated_at.utc.to_i}")
12
+
13
+ clear_cache_events
14
+ end
15
+
16
+ it "busts the cache when max_level_in_taxons_menu conf changes" do
17
+ Spree::Config[:max_level_in_taxons_menu] = 5
18
+ visit spree.root_path
19
+ assert_written_to_cache("views/en/spree/taxonomies/#{taxonomy.id}")
20
+ expect(cache_writes.count).to eq(1)
21
+ end
22
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Cart", type: :feature, inaccessible: true do
4
+ before { Timecop.scale(100) }
5
+
6
+ after { Timecop.return }
7
+
8
+ let!(:variant) { create(:variant) }
9
+ let!(:product) { variant.product }
10
+
11
+ def add_mug_to_cart
12
+ visit spree.root_path
13
+ click_link product.name
14
+ click_button "add-to-cart-button"
15
+ end
16
+
17
+ it "shows cart icon on non-cart pages" do
18
+ visit spree.root_path
19
+ expect(page).to have_selector("li#link-to-cart a", visible: true)
20
+ end
21
+
22
+ it "prevents double clicking the remove button on cart", js: true do
23
+ add_mug_to_cart
24
+ # prevent form submit to verify button is disabled
25
+ page.execute_script("$('#update-cart').submit(function(){return false;})")
26
+
27
+ expect(page).not_to have_selector('button#update-button[disabled]')
28
+ page.find(:css, '.delete span').click
29
+ expect(page).to have_selector('button#update-button[disabled]')
30
+ end
31
+
32
+ # Regression test for #2006
33
+ it "does not error out with a 404 when GET'ing to /orders/populate" do
34
+ visit '/orders/populate'
35
+ within(".alert-error") do
36
+ expect(page).to have_content(Spree.t(:populate_get_error))
37
+ end
38
+ end
39
+
40
+ it 'allows you to remove an item from the cart', js: true do
41
+ add_mug_to_cart
42
+ line_item = Spree::LineItem.first!
43
+ within("#line_items") do
44
+ click_link "delete_line_item_#{line_item.id}"
45
+ end
46
+
47
+ expect(page).to_not have_content("Line items quantity must be an integer")
48
+ expect(page).to_not have_content(product.name)
49
+ expect(page).to have_content("Your cart is empty")
50
+
51
+ within "#link-to-cart" do
52
+ expect(page).to have_content("Empty")
53
+ end
54
+ end
55
+
56
+ it 'allows you to empty the cart', js: true do
57
+ add_mug_to_cart
58
+ expect(page).to have_content(product.name)
59
+ click_on "Empty Cart"
60
+ expect(page).to have_content("Your cart is empty")
61
+
62
+ within "#link-to-cart" do
63
+ expect(page).to have_content("Empty")
64
+ end
65
+ end
66
+
67
+ # regression for #2276
68
+ context "product contains variants but no option values" do
69
+ before { variant.option_values.destroy_all }
70
+
71
+ it "still adds product to cart", inaccessible: true do
72
+ add_mug_to_cart
73
+ visit spree.cart_path
74
+ expect(page).to have_content(product.name)
75
+ end
76
+ end
77
+
78
+ it "should have a surrounding element with data-hook='cart_container'" do
79
+ visit spree.cart_path
80
+ expect(page).to have_selector("div[data-hook='cart_container']")
81
+ end
82
+
83
+ describe 'add promotion coupon on cart page', js: true do
84
+ let!(:promotion) { Spree::Promotion.create(name: 'Huhuhu', code: 'huhu') }
85
+ let!(:calculator) { Spree::Calculator::FlatPercentItemTotal.create(preferred_flat_percent: '10') }
86
+ let!(:action) { Spree::Promotion::Actions::CreateItemAdjustments.create(calculator: calculator) }
87
+
88
+ before do
89
+ promotion.actions << action
90
+ add_mug_to_cart
91
+ expect(current_path).to eql(spree.cart_path)
92
+ end
93
+
94
+ def apply_coupon(code)
95
+ fill_in 'Coupon Code', with: code
96
+ click_on 'Update'
97
+ end
98
+
99
+ context 'valid coupon' do
100
+ before { apply_coupon(promotion.code) }
101
+
102
+ context 'for the first time' do
103
+ it 'makes sure payment reflects order total with discounts' do
104
+ expect(page).to have_content(promotion.name)
105
+ end
106
+ end
107
+
108
+ context 'same coupon for the second time' do
109
+ before { apply_coupon(promotion.code) }
110
+ it 'should reflect an error that coupon already applied' do
111
+ apply_coupon(promotion.code)
112
+ expect(page).to have_content(Spree.t(:coupon_code_already_applied))
113
+ expect(page).to have_content(promotion.name)
114
+ end
115
+ end
116
+ end
117
+
118
+ context 'invalid coupon' do
119
+ it 'doesnt create a payment record' do
120
+ apply_coupon('invalid')
121
+ expect(page).to have_content(Spree.t(:coupon_code_not_found))
122
+ end
123
+ end
124
+
125
+ context "doesn't fill in coupon code input" do
126
+ it 'advances just fine' do
127
+ click_on 'Update'
128
+ expect(current_path).to match(spree.cart_path)
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,572 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Checkout', type: :feature, inaccessible: true, js: true do
4
+ include_context 'checkout setup'
5
+
6
+ let(:country) { create(:country, name: 'United States of America', iso_name: 'UNITED STATES') }
7
+ let(:state) { create(:state, name: 'Alabama', abbr: 'AL', country: country) }
8
+
9
+ context "visitor makes checkout as guest without registration" do
10
+ before(:each) do
11
+ stock_location.stock_items.update_all(count_on_hand: 1)
12
+ end
13
+
14
+ context 'defaults to use billing address' do
15
+ before do
16
+ add_mug_to_cart
17
+ Spree::Order.last.update_column(:email, 'test@example.com')
18
+ click_button 'Checkout'
19
+ end
20
+
21
+ it 'should default checkbox to checked' do
22
+ expect(find('input#order_use_billing')).to be_checked
23
+ end
24
+
25
+ it 'should remain checked when used and visitor steps back to address step' do
26
+ fill_in_address
27
+ expect(find('input#order_use_billing')).to be_checked
28
+ end
29
+ end
30
+
31
+ # Regression test for #4079
32
+ context 'persists state when on address page' do
33
+ before do
34
+ add_mug_to_cart
35
+ click_button 'Checkout'
36
+ end
37
+
38
+ specify do
39
+ expect(Spree::Order.count).to eq 1
40
+ expect(Spree::Order.last.state).to eq 'address'
41
+ end
42
+ end
43
+
44
+ # Regression test for #1596
45
+ context 'full checkout' do
46
+ before do
47
+ shipping_method.calculator.update!(preferred_amount: 10)
48
+ mug.shipping_category = shipping_method.shipping_categories.first
49
+ mug.save!
50
+ end
51
+
52
+ it 'does not break the per-item shipping method calculator', js: true do
53
+ add_mug_to_cart
54
+ click_button 'Checkout'
55
+
56
+ fill_in 'order_email', with: 'test@example.com'
57
+ click_on 'Continue'
58
+ fill_in_address
59
+
60
+ click_button 'Save and Continue'
61
+ expect(page).to_not have_content("undefined method `promotion'")
62
+ click_button 'Save and Continue'
63
+ expect(page).to have_content('Shipping total: $10.00')
64
+ end
65
+ end
66
+
67
+ # Regression test for #4306
68
+ context 'free shipping' do
69
+ before do
70
+ add_mug_to_cart
71
+ click_button 'Checkout'
72
+ fill_in 'order_email', with: 'test@example.com'
73
+ click_on 'Continue'
74
+ end
75
+
76
+ it "should not show 'Free Shipping' when there are no shipments" do
77
+ within('#checkout-summary') do
78
+ expect(page).to_not have_content('Free Shipping')
79
+ end
80
+ end
81
+ end
82
+
83
+ # Regression test for #4190
84
+ it 'updates state_lock_version on form submission', js: true do
85
+ add_mug_to_cart
86
+ click_button "Checkout"
87
+
88
+ expect(find('input#order_state_lock_version', visible: false).value).to eq '0'
89
+
90
+ fill_in 'order_email', with: 'test@example.com'
91
+ fill_in_address
92
+ click_button 'Save and Continue'
93
+
94
+ expect(find('input#order_state_lock_version', visible: false).value).to eq '1'
95
+ end
96
+ end
97
+
98
+ # Regression test for #2694 and #4117
99
+ context "doesn't allow bad credit card numbers" do
100
+ before(:each) do
101
+ order = OrderWalkthrough.up_to(:payment)
102
+ allow(order).to receive_messages confirmation_required?: true
103
+ allow(order).to receive_messages(available_payment_methods: [create(:credit_card_payment_method)])
104
+
105
+ user = create(:user)
106
+ order.user = user
107
+ order.update_with_updater!
108
+
109
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
110
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
111
+ end
112
+
113
+ it 'redirects to payment page', inaccessible: true, js: true do
114
+ visit spree.checkout_state_path(:payment)
115
+ click_button 'Save and Continue'
116
+ choose 'Credit Card'
117
+ fill_in 'Card Number', with: '123'
118
+ fill_in 'card_expiry', with: '04 / 20'
119
+ fill_in 'Card Code', with: '123'
120
+ click_button 'Save and Continue'
121
+ click_button 'Place Order'
122
+ expect(page).to have_content('Bogus Gateway: Forced failure')
123
+ expect(page.current_url).to include('/checkout/payment')
124
+ end
125
+ end
126
+
127
+ # regression test for #3945
128
+ context 'when Spree::Config[:always_include_confirm_step] is true' do
129
+ before do
130
+ Spree::Config[:always_include_confirm_step] = true
131
+ end
132
+
133
+ it 'displays confirmation step', js: true do
134
+ add_mug_to_cart
135
+ click_button 'Checkout'
136
+
137
+ fill_in 'order_email', with: 'test@example.com'
138
+ click_on 'Continue'
139
+ fill_in_address
140
+
141
+ click_button 'Save and Continue'
142
+ click_button 'Save and Continue'
143
+ click_button 'Save and Continue'
144
+
145
+ continue_button = find('#checkout .btn-success')
146
+ expect(continue_button.value).to eq 'Place Order'
147
+ end
148
+ end
149
+
150
+ context 'and likes to double click buttons' do
151
+ let!(:user) { create(:user) }
152
+
153
+ let!(:order) do
154
+ order = OrderWalkthrough.up_to(:payment)
155
+ allow(order).to receive_messages confirmation_required?: true
156
+
157
+ order.reload
158
+ order.user = user
159
+ order.update_with_updater!
160
+ order
161
+ end
162
+
163
+ before(:each) do
164
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
165
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
166
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(skip_state_validation?: true)
167
+ end
168
+
169
+ it 'prevents double clicking the payment button on checkout', js: true do
170
+ visit spree.checkout_state_path(:payment)
171
+
172
+ # prevent form submit to verify button is disabled
173
+ page.execute_script("$('#checkout_form_payment').submit(function(){return false;})")
174
+
175
+ expect(page).to_not have_selector('input.btn.disabled')
176
+ click_button 'Save and Continue'
177
+ expect(page).to have_selector('input.btn.disabled')
178
+ end
179
+
180
+ it 'prevents double clicking the confirm button on checkout', js: true do
181
+ order.payments << create(:payment, amount: order.amount)
182
+ visit spree.checkout_state_path(:confirm)
183
+
184
+ # prevent form submit to verify button is disabled
185
+ page.execute_script("$('#checkout_form_confirm').submit(function(){return false;})")
186
+
187
+ expect(page).to_not have_selector('input.btn.disabled')
188
+ click_button 'Place Order'
189
+ expect(page).to have_selector('input.btn.disabled')
190
+ end
191
+ end
192
+
193
+ context 'when several payment methods are available', js: true do
194
+ let(:credit_cart_payment) { create(:credit_card_payment_method) }
195
+ let(:check_payment) { create(:check_payment_method) }
196
+
197
+ after do
198
+ Capybara.ignore_hidden_elements = true
199
+ end
200
+
201
+ before do
202
+ Capybara.ignore_hidden_elements = false
203
+ order = OrderWalkthrough.up_to(:payment)
204
+ allow(order).to receive_messages(available_payment_methods: [check_payment, credit_cart_payment])
205
+ order.user = create(:user)
206
+ order.update_with_updater!
207
+
208
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
209
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: order.user)
210
+
211
+ visit spree.checkout_state_path(:payment)
212
+ end
213
+
214
+ it 'the first payment method should be selected' do
215
+ payment_method_css = '#order_payments_attributes__payment_method_id_'
216
+ expect(find("#{payment_method_css}#{check_payment.id}")).to be_checked
217
+ expect(find("#{payment_method_css}#{credit_cart_payment.id}")).not_to be_checked
218
+ end
219
+
220
+ it 'the fields for the other payment methods should be hidden' do
221
+ payment_method_css = '#payment_method_'
222
+ expect(find("#{payment_method_css}#{check_payment.id}")).to be_visible
223
+ expect(find("#{payment_method_css}#{credit_cart_payment.id}")).not_to be_visible
224
+ end
225
+ end
226
+
227
+ context 'user has payment sources', js: true do
228
+ let(:bogus) { create(:credit_card_payment_method) }
229
+ let(:user) { create(:user) }
230
+
231
+ let!(:credit_card) do
232
+ create(:credit_card, user_id: user.id, payment_method: bogus, gateway_customer_profile_id: 'BGS-WEFWF')
233
+ end
234
+
235
+ before do
236
+ order = OrderWalkthrough.up_to(:payment)
237
+ allow(order).to receive_messages(available_payment_methods: [bogus])
238
+
239
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
240
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
241
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
242
+
243
+ visit spree.checkout_state_path(:payment)
244
+ end
245
+
246
+ it 'selects first source available and customer moves on' do
247
+ expect(find('#use_existing_card_yes')).to be_checked
248
+
249
+ expect { click_on 'Save and Continue' }.not_to change { Spree::CreditCard.count }
250
+
251
+ click_on 'Place Order'
252
+ expect(current_path).to match(spree.order_path(Spree::Order.last))
253
+ end
254
+
255
+ it 'allows user to enter a new source' do
256
+ choose 'use_existing_card_no'
257
+
258
+ fill_in 'Name on card', with: 'Spree Commerce'
259
+ fill_in 'Card Number', with: '4111111111111111'
260
+ fill_in 'card_expiry', with: '04 / 20'
261
+ fill_in 'Card Code', with: '123'
262
+
263
+ expect { click_on 'Save and Continue' }.to change { Spree::CreditCard.count }.by 1
264
+
265
+ click_on 'Place Order'
266
+ expect(current_path).to match(spree.order_path(Spree::Order.last))
267
+ end
268
+ end
269
+
270
+ # regression for #2921
271
+ context 'goes back from payment to add another item', js: true do
272
+ let!(:bag) { create(:product, name: 'RoR Bag') }
273
+
274
+ it 'transit nicely through checkout steps again' do
275
+ add_mug_to_cart
276
+ click_on 'Checkout'
277
+ fill_in 'order_email', with: 'test@example.com'
278
+ click_on 'Continue'
279
+ fill_in_address
280
+ click_on 'Save and Continue'
281
+ click_on 'Save and Continue'
282
+ expect(current_path).to eql(spree.checkout_state_path('payment'))
283
+
284
+ visit spree.root_path
285
+ click_link bag.name
286
+ click_button 'add-to-cart-button'
287
+
288
+ click_on 'Checkout'
289
+ click_on 'Save and Continue'
290
+ click_on 'Save and Continue'
291
+ click_on 'Save and Continue'
292
+
293
+ expect(current_path).to match(spree.order_path(Spree::Order.last))
294
+ end
295
+ end
296
+
297
+ context 'from payment step customer goes back to cart', js: true do
298
+ before do
299
+ add_mug_to_cart
300
+ click_on 'Checkout'
301
+ fill_in 'order_email', with: 'test@example.com'
302
+ click_on 'Continue'
303
+ fill_in_address
304
+ click_on 'Save and Continue'
305
+ click_on 'Save and Continue'
306
+ expect(current_path).to eql(spree.checkout_state_path('payment'))
307
+ end
308
+
309
+ context 'and updates line item quantity and try to reach payment page' do
310
+ before do
311
+ visit spree.cart_path
312
+ within '.cart-item-quantity' do
313
+ fill_in first('input')['name'], with: 3
314
+ end
315
+
316
+ click_on 'Update'
317
+ end
318
+
319
+ it 'redirects user back to address step' do
320
+ visit spree.checkout_state_path('payment')
321
+ expect(current_path).to eql(spree.checkout_state_path('address'))
322
+ end
323
+
324
+ it 'updates shipments properly through step address -> delivery transitions' do
325
+ visit spree.checkout_state_path('payment')
326
+ click_on 'Save and Continue'
327
+ click_on 'Save and Continue'
328
+
329
+ expect(Spree::InventoryUnit.count).to eq 3
330
+ end
331
+ end
332
+
333
+ context 'and adds new product to cart and try to reach payment page' do
334
+ let!(:bag) { create(:product, name: 'RoR Bag') }
335
+
336
+ before do
337
+ visit spree.root_path
338
+ click_link bag.name
339
+ click_button 'add-to-cart-button'
340
+ end
341
+
342
+ it 'redirects user back to address step' do
343
+ visit spree.checkout_state_path('payment')
344
+ expect(current_path).to eql(spree.checkout_state_path('address'))
345
+ end
346
+
347
+ it 'updates shipments properly through step address -> delivery transitions' do
348
+ visit spree.checkout_state_path("payment")
349
+ click_on 'Save and Continue'
350
+ click_on 'Save and Continue'
351
+
352
+ expect(Spree::InventoryUnit.count).to eq 2
353
+ end
354
+ end
355
+ end
356
+
357
+ context 'if coupon promotion, submits coupon along with payment', js: true do
358
+ let!(:promotion) { Spree::Promotion.create(name: 'Huhuhu', code: 'huhu') }
359
+ let!(:calculator) { Spree::Calculator::FlatPercentItemTotal.create(preferred_flat_percent: '10') }
360
+ let!(:action) { Spree::Promotion::Actions::CreateItemAdjustments.create(calculator: calculator) }
361
+
362
+ before do
363
+ promotion.actions << action
364
+
365
+ add_mug_to_cart
366
+ click_on 'Checkout'
367
+
368
+ fill_in 'order_email', with: 'test@example.com'
369
+ click_on 'Continue'
370
+ fill_in_address
371
+ click_on 'Save and Continue'
372
+
373
+ click_on 'Save and Continue'
374
+ expect(current_path).to eql(spree.checkout_state_path('payment'))
375
+ end
376
+
377
+ it 'makes sure payment reflects order total with discounts' do
378
+ fill_in 'Coupon Code', with: promotion.code
379
+ click_on 'Save and Continue'
380
+
381
+ expect(page).to have_content(promotion.name)
382
+ expect(Spree::Payment.first.amount.to_f).to eq Spree::Order.last.total.to_f
383
+ end
384
+
385
+ context 'invalid coupon' do
386
+ it 'doesnt create a payment record' do
387
+ fill_in 'Coupon Code', with: 'invalid'
388
+ click_on 'Save and Continue'
389
+
390
+ expect(Spree::Payment.count).to eq 0
391
+ expect(page).to have_content(Spree.t(:coupon_code_not_found))
392
+ end
393
+ end
394
+
395
+ context "doesn't fill in coupon code input" do
396
+ it 'advances just fine' do
397
+ click_on 'Save and Continue'
398
+ expect(current_path).to match(spree.order_path(Spree::Order.last))
399
+ end
400
+ end
401
+ end
402
+
403
+ context 'order has only payment step' do
404
+ before do
405
+ create(:credit_card_payment_method)
406
+ @old_checkout_flow = Spree::Order.checkout_flow
407
+ Spree::Order.class_eval do
408
+ checkout_flow do
409
+ go_to_state :payment
410
+ go_to_state :confirm
411
+ end
412
+ end
413
+
414
+ allow_any_instance_of(Spree::Order).to receive_messages email: 'spree@commerce.com'
415
+
416
+ add_mug_to_cart
417
+ click_on 'Checkout'
418
+ end
419
+
420
+ after do
421
+ Spree::Order.checkout_flow(&@old_checkout_flow)
422
+ end
423
+
424
+ it 'goes right payment step and place order just fine' do
425
+ expect(current_path).to eq spree.checkout_state_path('payment')
426
+
427
+ choose 'Credit Card'
428
+ fill_in 'Name on card', with: 'Spree Commerce'
429
+ fill_in 'Card Number', with: '4111111111111111'
430
+ fill_in 'card_expiry', with: '04 / 20'
431
+ fill_in 'Card Code', with: '123'
432
+ click_button 'Save and Continue'
433
+
434
+ expect(current_path).to eq spree.checkout_state_path('confirm')
435
+ click_button 'Place Order'
436
+ end
437
+ end
438
+
439
+ context 'save my address' do
440
+ before do
441
+ stock_location.stock_items.update_all(count_on_hand: 1)
442
+ add_mug_to_cart
443
+ end
444
+
445
+ context 'as a guest' do
446
+ before do
447
+ Spree::Order.last.update_column(:email, 'test@example.com')
448
+ click_button 'Checkout'
449
+ end
450
+
451
+ it 'should not be displayed' do
452
+ expect(page).to_not have_css('[data-hook=save_user_address]')
453
+ end
454
+ end
455
+
456
+ context 'as a User' do
457
+ before do
458
+ user = create(:user)
459
+ Spree::Order.last.update_column :user_id, user.id
460
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
461
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
462
+ click_button 'Checkout'
463
+ end
464
+
465
+ it 'should be displayed' do
466
+ expect(page).to have_css('[data-hook=save_user_address]')
467
+ end
468
+ end
469
+ end
470
+
471
+ context 'when order is completed' do
472
+ let!(:user) { create(:user) }
473
+ let!(:order) { OrderWalkthrough.up_to(:payment) }
474
+
475
+ before(:each) do
476
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
477
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
478
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
479
+
480
+ visit spree.checkout_state_path(:payment)
481
+ click_button 'Save and Continue'
482
+ end
483
+
484
+ it 'displays a thank you message' do
485
+ expect(page).to have_content(Spree.t(:thank_you_for_your_order))
486
+ end
487
+
488
+ it 'does not display a thank you message on that order future visits' do
489
+ visit spree.order_path(order)
490
+ expect(page).to_not have_content(Spree.t(:thank_you_for_your_order))
491
+ end
492
+ end
493
+
494
+ context 'user has store credits', js: true do
495
+ let(:bogus) { create(:credit_card_payment_method) }
496
+ let(:store_credit_payment_method) { create(:store_credit_payment_method) }
497
+ let(:user) { create(:user) }
498
+ let(:order) { OrderWalkthrough.up_to(:payment) }
499
+
500
+ let(:prepare_checkout!) do
501
+ order.update(user: user)
502
+ allow(order).to receive_messages(available_payment_methods: [bogus, store_credit_payment_method])
503
+
504
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
505
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(try_spree_current_user: user)
506
+ allow_any_instance_of(Spree::OrdersController).to receive_messages(try_spree_current_user: user)
507
+ visit spree.checkout_state_path(:payment)
508
+ end
509
+
510
+ context 'when not all Store Credits are used' do
511
+ let!(:store_credit) { create(:store_credit, user: user) }
512
+ let!(:additional_store_credit) { create(:store_credit, user: user, amount: 13) }
513
+
514
+ before { prepare_checkout! }
515
+
516
+ it 'page has data for (multiple) Store Credits' do
517
+ expect(page).to have_selector('[data-hook="checkout_payment_store_credit_available"]')
518
+ expect(page).to have_selector('button[name="apply_store_credit"]')
519
+
520
+ amount = Spree::Money.new(store_credit.amount_remaining + additional_store_credit.amount_remaining)
521
+ expect(page).to have_content(Spree.t('store_credit.available_amount', amount: amount))
522
+ end
523
+
524
+ it 'apply store credits button should move checkout to next step if amount is sufficient' do
525
+ click_button 'Apply Store Credit'
526
+ expect(current_path).to eq spree.order_path(order)
527
+ expect(page).to have_content(Spree.t('order_processed_successfully'))
528
+ end
529
+
530
+ it 'apply store credits button should wait on payment step for other payment' do
531
+ store_credit.update(amount_used: 145)
532
+ additional_store_credit.update(amount_used: 12)
533
+ click_button 'Apply Store Credit'
534
+
535
+ expect(current_path).to eq spree.checkout_state_path(:payment)
536
+ amount = Spree::Money.new(store_credit.amount_remaining + additional_store_credit.amount_remaining)
537
+ remaining_amount = Spree::Money.new(order.total - amount.money.to_f)
538
+ expect(page).to have_content(Spree.t('store_credit.applicable_amount', amount: amount))
539
+ expect(page).to have_content(Spree.t('store_credit.additional_payment_needed', amount: remaining_amount))
540
+ end
541
+ end
542
+
543
+ context 'when all Store Credits are used' do
544
+ let!(:store_credit) { create(:store_credit, user: user, amount_used: 150) }
545
+
546
+ before { prepare_checkout! }
547
+
548
+ it 'page has no data for Store Credits when all Store Credits are used' do
549
+ expect(page).to_not have_selector('[data-hook="checkout_payment_store_credit_available"]')
550
+ expect(page).to_not have_selector('button[name="apply_store_credit"]')
551
+ end
552
+ end
553
+ end
554
+
555
+ def fill_in_address
556
+ address = "order_bill_address_attributes"
557
+ fill_in "#{address}_firstname", with: "Ryan"
558
+ fill_in "#{address}_lastname", with: "Bigg"
559
+ fill_in "#{address}_address1", with: "143 Swan Street"
560
+ fill_in "#{address}_city", with: "Richmond"
561
+ select country.name, from: "#{address}_country_id"
562
+ select state.name, from: "#{address}_state_id"
563
+ fill_in "#{address}_zipcode", with: "12345"
564
+ fill_in "#{address}_phone", with: "(555) 555-5555"
565
+ end
566
+
567
+ def add_mug_to_cart
568
+ visit spree.root_path
569
+ click_link mug.name
570
+ click_button "add-to-cart-button"
571
+ end
572
+ end