spree_frontend 2.4.10 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (378) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE +1 -1
  5. data/README.md +39 -10
  6. data/Rakefile +29 -0
  7. data/{vendor → app}/assets/images/flags/ad.png +0 -0
  8. data/{vendor → app}/assets/images/flags/ae.png +0 -0
  9. data/{vendor → app}/assets/images/flags/af.png +0 -0
  10. data/{vendor → app}/assets/images/flags/ag.png +0 -0
  11. data/{vendor → app}/assets/images/flags/ai.png +0 -0
  12. data/{vendor → app}/assets/images/flags/al.png +0 -0
  13. data/{vendor → app}/assets/images/flags/am.png +0 -0
  14. data/{vendor → app}/assets/images/flags/an.png +0 -0
  15. data/{vendor → app}/assets/images/flags/ao.png +0 -0
  16. data/{vendor → app}/assets/images/flags/ar.png +0 -0
  17. data/{vendor → app}/assets/images/flags/as.png +0 -0
  18. data/{vendor → app}/assets/images/flags/at.png +0 -0
  19. data/{vendor → app}/assets/images/flags/au.png +0 -0
  20. data/{vendor → app}/assets/images/flags/aw.png +0 -0
  21. data/{vendor → app}/assets/images/flags/ax.png +0 -0
  22. data/{vendor → app}/assets/images/flags/az.png +0 -0
  23. data/{vendor → app}/assets/images/flags/ba.png +0 -0
  24. data/{vendor → app}/assets/images/flags/bb.png +0 -0
  25. data/{vendor → app}/assets/images/flags/bd.png +0 -0
  26. data/{vendor → app}/assets/images/flags/be.png +0 -0
  27. data/{vendor → app}/assets/images/flags/bf.png +0 -0
  28. data/{vendor → app}/assets/images/flags/bg.png +0 -0
  29. data/{vendor → app}/assets/images/flags/bh.png +0 -0
  30. data/{vendor → app}/assets/images/flags/bi.png +0 -0
  31. data/{vendor → app}/assets/images/flags/bj.png +0 -0
  32. data/{vendor → app}/assets/images/flags/bm.png +0 -0
  33. data/{vendor → app}/assets/images/flags/bn.png +0 -0
  34. data/{vendor → app}/assets/images/flags/bo.png +0 -0
  35. data/{vendor → app}/assets/images/flags/br.png +0 -0
  36. data/{vendor → app}/assets/images/flags/bs.png +0 -0
  37. data/{vendor → app}/assets/images/flags/bt.png +0 -0
  38. data/{vendor → app}/assets/images/flags/bv.png +0 -0
  39. data/{vendor → app}/assets/images/flags/bw.png +0 -0
  40. data/{vendor → app}/assets/images/flags/by.png +0 -0
  41. data/{vendor → app}/assets/images/flags/bz.png +0 -0
  42. data/{vendor → app}/assets/images/flags/ca.png +0 -0
  43. data/{vendor → app}/assets/images/flags/catalonia.png +0 -0
  44. data/{vendor → app}/assets/images/flags/cc.png +0 -0
  45. data/{vendor → app}/assets/images/flags/cd.png +0 -0
  46. data/{vendor → app}/assets/images/flags/cf.png +0 -0
  47. data/{vendor → app}/assets/images/flags/cg.png +0 -0
  48. data/{vendor → app}/assets/images/flags/ch.png +0 -0
  49. data/{vendor → app}/assets/images/flags/ci.png +0 -0
  50. data/{vendor → app}/assets/images/flags/ck.png +0 -0
  51. data/{vendor → app}/assets/images/flags/cl.png +0 -0
  52. data/{vendor → app}/assets/images/flags/cm.png +0 -0
  53. data/{vendor → app}/assets/images/flags/cn.png +0 -0
  54. data/{vendor → app}/assets/images/flags/co.png +0 -0
  55. data/{vendor → app}/assets/images/flags/cr.png +0 -0
  56. data/{vendor → app}/assets/images/flags/cs.png +0 -0
  57. data/{vendor → app}/assets/images/flags/cu.png +0 -0
  58. data/{vendor → app}/assets/images/flags/cv.png +0 -0
  59. data/{vendor → app}/assets/images/flags/cx.png +0 -0
  60. data/{vendor → app}/assets/images/flags/cy.png +0 -0
  61. data/{vendor → app}/assets/images/flags/cz.png +0 -0
  62. data/{vendor → app}/assets/images/flags/de.png +0 -0
  63. data/{vendor → app}/assets/images/flags/dj.png +0 -0
  64. data/{vendor → app}/assets/images/flags/dk.png +0 -0
  65. data/{vendor → app}/assets/images/flags/dm.png +0 -0
  66. data/{vendor → app}/assets/images/flags/do.png +0 -0
  67. data/{vendor → app}/assets/images/flags/dz.png +0 -0
  68. data/{vendor → app}/assets/images/flags/ec.png +0 -0
  69. data/{vendor → app}/assets/images/flags/ee.png +0 -0
  70. data/{vendor → app}/assets/images/flags/eg.png +0 -0
  71. data/{vendor → app}/assets/images/flags/eh.png +0 -0
  72. data/{vendor → app}/assets/images/flags/england.png +0 -0
  73. data/{vendor → app}/assets/images/flags/er.png +0 -0
  74. data/{vendor → app}/assets/images/flags/es.png +0 -0
  75. data/{vendor → app}/assets/images/flags/et.png +0 -0
  76. data/{vendor → app}/assets/images/flags/europeanunion.png +0 -0
  77. data/{vendor → app}/assets/images/flags/fam.png +0 -0
  78. data/{vendor → app}/assets/images/flags/fi.png +0 -0
  79. data/{vendor → app}/assets/images/flags/fj.png +0 -0
  80. data/{vendor → app}/assets/images/flags/fk.png +0 -0
  81. data/{vendor → app}/assets/images/flags/fm.png +0 -0
  82. data/{vendor → app}/assets/images/flags/fo.png +0 -0
  83. data/{vendor → app}/assets/images/flags/fr.png +0 -0
  84. data/{vendor → app}/assets/images/flags/ga.png +0 -0
  85. data/{vendor → app}/assets/images/flags/gb.png +0 -0
  86. data/{vendor → app}/assets/images/flags/gd.png +0 -0
  87. data/{vendor → app}/assets/images/flags/ge.png +0 -0
  88. data/{vendor → app}/assets/images/flags/gf.png +0 -0
  89. data/{vendor → app}/assets/images/flags/gh.png +0 -0
  90. data/{vendor → app}/assets/images/flags/gi.png +0 -0
  91. data/{vendor → app}/assets/images/flags/gl.png +0 -0
  92. data/{vendor → app}/assets/images/flags/gm.png +0 -0
  93. data/{vendor → app}/assets/images/flags/gn.png +0 -0
  94. data/{vendor → app}/assets/images/flags/gp.png +0 -0
  95. data/{vendor → app}/assets/images/flags/gq.png +0 -0
  96. data/{vendor → app}/assets/images/flags/gr.png +0 -0
  97. data/{vendor → app}/assets/images/flags/gs.png +0 -0
  98. data/{vendor → app}/assets/images/flags/gt.png +0 -0
  99. data/{vendor → app}/assets/images/flags/gu.png +0 -0
  100. data/{vendor → app}/assets/images/flags/gw.png +0 -0
  101. data/{vendor → app}/assets/images/flags/gy.png +0 -0
  102. data/{vendor → app}/assets/images/flags/hk.png +0 -0
  103. data/{vendor → app}/assets/images/flags/hm.png +0 -0
  104. data/{vendor → app}/assets/images/flags/hn.png +0 -0
  105. data/{vendor → app}/assets/images/flags/hr.png +0 -0
  106. data/{vendor → app}/assets/images/flags/ht.png +0 -0
  107. data/{vendor → app}/assets/images/flags/hu.png +0 -0
  108. data/{vendor → app}/assets/images/flags/id.png +0 -0
  109. data/{vendor → app}/assets/images/flags/ie.png +0 -0
  110. data/{vendor → app}/assets/images/flags/il.png +0 -0
  111. data/{vendor → app}/assets/images/flags/in.png +0 -0
  112. data/{vendor → app}/assets/images/flags/io.png +0 -0
  113. data/{vendor → app}/assets/images/flags/iq.png +0 -0
  114. data/{vendor → app}/assets/images/flags/ir.png +0 -0
  115. data/{vendor → app}/assets/images/flags/is.png +0 -0
  116. data/{vendor → app}/assets/images/flags/it.png +0 -0
  117. data/{vendor → app}/assets/images/flags/ja.png +0 -0
  118. data/{vendor → app}/assets/images/flags/jm.png +0 -0
  119. data/{vendor → app}/assets/images/flags/jo.png +0 -0
  120. data/{vendor → app}/assets/images/flags/ke.png +0 -0
  121. data/{vendor → app}/assets/images/flags/kg.png +0 -0
  122. data/{vendor → app}/assets/images/flags/kh.png +0 -0
  123. data/{vendor → app}/assets/images/flags/ki.png +0 -0
  124. data/{vendor → app}/assets/images/flags/km.png +0 -0
  125. data/{vendor → app}/assets/images/flags/kn.png +0 -0
  126. data/{vendor → app}/assets/images/flags/kp.png +0 -0
  127. data/{vendor → app}/assets/images/flags/kr.png +0 -0
  128. data/{vendor → app}/assets/images/flags/kw.png +0 -0
  129. data/{vendor → app}/assets/images/flags/ky.png +0 -0
  130. data/{vendor → app}/assets/images/flags/kz.png +0 -0
  131. data/{vendor → app}/assets/images/flags/la.png +0 -0
  132. data/{vendor → app}/assets/images/flags/lb.png +0 -0
  133. data/{vendor → app}/assets/images/flags/lc.png +0 -0
  134. data/{vendor → app}/assets/images/flags/li.png +0 -0
  135. data/{vendor → app}/assets/images/flags/lk.png +0 -0
  136. data/{vendor → app}/assets/images/flags/lr.png +0 -0
  137. data/{vendor → app}/assets/images/flags/ls.png +0 -0
  138. data/{vendor → app}/assets/images/flags/lt.png +0 -0
  139. data/{vendor → app}/assets/images/flags/lu.png +0 -0
  140. data/{vendor → app}/assets/images/flags/lv.png +0 -0
  141. data/{vendor → app}/assets/images/flags/ly.png +0 -0
  142. data/{vendor → app}/assets/images/flags/ma.png +0 -0
  143. data/{vendor → app}/assets/images/flags/mc.png +0 -0
  144. data/{vendor → app}/assets/images/flags/md.png +0 -0
  145. data/{vendor → app}/assets/images/flags/me.png +0 -0
  146. data/{vendor → app}/assets/images/flags/mg.png +0 -0
  147. data/{vendor → app}/assets/images/flags/mh.png +0 -0
  148. data/{vendor → app}/assets/images/flags/mk.png +0 -0
  149. data/{vendor → app}/assets/images/flags/ml.png +0 -0
  150. data/{vendor → app}/assets/images/flags/mm.png +0 -0
  151. data/{vendor → app}/assets/images/flags/mn.png +0 -0
  152. data/{vendor → app}/assets/images/flags/mo.png +0 -0
  153. data/{vendor → app}/assets/images/flags/mp.png +0 -0
  154. data/{vendor → app}/assets/images/flags/mq.png +0 -0
  155. data/{vendor → app}/assets/images/flags/mr.png +0 -0
  156. data/{vendor → app}/assets/images/flags/ms.png +0 -0
  157. data/{vendor → app}/assets/images/flags/mt.png +0 -0
  158. data/{vendor → app}/assets/images/flags/mu.png +0 -0
  159. data/{vendor → app}/assets/images/flags/mv.png +0 -0
  160. data/{vendor → app}/assets/images/flags/mw.png +0 -0
  161. data/{vendor → app}/assets/images/flags/mx.png +0 -0
  162. data/{vendor → app}/assets/images/flags/my.png +0 -0
  163. data/{vendor → app}/assets/images/flags/mz.png +0 -0
  164. data/{vendor → app}/assets/images/flags/na.png +0 -0
  165. data/{vendor → app}/assets/images/flags/nc.png +0 -0
  166. data/{vendor → app}/assets/images/flags/ne.png +0 -0
  167. data/{vendor → app}/assets/images/flags/nf.png +0 -0
  168. data/{vendor → app}/assets/images/flags/ng.png +0 -0
  169. data/{vendor → app}/assets/images/flags/ni.png +0 -0
  170. data/{vendor → app}/assets/images/flags/nl.png +0 -0
  171. data/{vendor → app}/assets/images/flags/no.png +0 -0
  172. data/{vendor → app}/assets/images/flags/np.png +0 -0
  173. data/{vendor → app}/assets/images/flags/nr.png +0 -0
  174. data/{vendor → app}/assets/images/flags/nu.png +0 -0
  175. data/{vendor → app}/assets/images/flags/nz.png +0 -0
  176. data/{vendor → app}/assets/images/flags/om.png +0 -0
  177. data/{vendor → app}/assets/images/flags/pa.png +0 -0
  178. data/{vendor → app}/assets/images/flags/pe.png +0 -0
  179. data/{vendor → app}/assets/images/flags/pf.png +0 -0
  180. data/{vendor → app}/assets/images/flags/pg.png +0 -0
  181. data/{vendor → app}/assets/images/flags/ph.png +0 -0
  182. data/{vendor → app}/assets/images/flags/pk.png +0 -0
  183. data/{vendor → app}/assets/images/flags/pl.png +0 -0
  184. data/{vendor → app}/assets/images/flags/pm.png +0 -0
  185. data/{vendor → app}/assets/images/flags/pn.png +0 -0
  186. data/{vendor → app}/assets/images/flags/pr.png +0 -0
  187. data/{vendor → app}/assets/images/flags/ps.png +0 -0
  188. data/{vendor → app}/assets/images/flags/pt.png +0 -0
  189. data/{vendor → app}/assets/images/flags/pw.png +0 -0
  190. data/{vendor → app}/assets/images/flags/py.png +0 -0
  191. data/{vendor → app}/assets/images/flags/qa.png +0 -0
  192. data/{vendor → app}/assets/images/flags/re.png +0 -0
  193. data/{vendor → app}/assets/images/flags/ro.png +0 -0
  194. data/{vendor → app}/assets/images/flags/rs.png +0 -0
  195. data/{vendor → app}/assets/images/flags/ru.png +0 -0
  196. data/{vendor → app}/assets/images/flags/rw.png +0 -0
  197. data/{vendor → app}/assets/images/flags/sa.png +0 -0
  198. data/{vendor → app}/assets/images/flags/sb.png +0 -0
  199. data/{vendor → app}/assets/images/flags/sc.png +0 -0
  200. data/{vendor → app}/assets/images/flags/scotland.png +0 -0
  201. data/{vendor → app}/assets/images/flags/sd.png +0 -0
  202. data/{vendor → app}/assets/images/flags/se.png +0 -0
  203. data/{vendor → app}/assets/images/flags/sg.png +0 -0
  204. data/{vendor → app}/assets/images/flags/sh.png +0 -0
  205. data/{vendor → app}/assets/images/flags/si.png +0 -0
  206. data/{vendor → app}/assets/images/flags/sj.png +0 -0
  207. data/{vendor → app}/assets/images/flags/sk.png +0 -0
  208. data/{vendor → app}/assets/images/flags/sl.png +0 -0
  209. data/{vendor → app}/assets/images/flags/sm.png +0 -0
  210. data/{vendor → app}/assets/images/flags/sn.png +0 -0
  211. data/{vendor → app}/assets/images/flags/so.png +0 -0
  212. data/{vendor → app}/assets/images/flags/sr.png +0 -0
  213. data/{vendor → app}/assets/images/flags/st.png +0 -0
  214. data/{vendor → app}/assets/images/flags/sv.png +0 -0
  215. data/{vendor → app}/assets/images/flags/sy.png +0 -0
  216. data/{vendor → app}/assets/images/flags/sz.png +0 -0
  217. data/{vendor → app}/assets/images/flags/tc.png +0 -0
  218. data/{vendor → app}/assets/images/flags/td.png +0 -0
  219. data/{vendor → app}/assets/images/flags/tf.png +0 -0
  220. data/{vendor → app}/assets/images/flags/tg.png +0 -0
  221. data/{vendor → app}/assets/images/flags/th.png +0 -0
  222. data/{vendor → app}/assets/images/flags/tj.png +0 -0
  223. data/{vendor → app}/assets/images/flags/tk.png +0 -0
  224. data/{vendor → app}/assets/images/flags/tl.png +0 -0
  225. data/{vendor → app}/assets/images/flags/tm.png +0 -0
  226. data/{vendor → app}/assets/images/flags/tn.png +0 -0
  227. data/{vendor → app}/assets/images/flags/to.png +0 -0
  228. data/{vendor → app}/assets/images/flags/tr.png +0 -0
  229. data/{vendor → app}/assets/images/flags/tt.png +0 -0
  230. data/{vendor → app}/assets/images/flags/tv.png +0 -0
  231. data/{vendor → app}/assets/images/flags/tw.png +0 -0
  232. data/{vendor → app}/assets/images/flags/tz.png +0 -0
  233. data/{vendor → app}/assets/images/flags/ua.png +0 -0
  234. data/{vendor → app}/assets/images/flags/ug.png +0 -0
  235. data/{vendor → app}/assets/images/flags/um.png +0 -0
  236. data/{vendor → app}/assets/images/flags/us.png +0 -0
  237. data/{vendor → app}/assets/images/flags/uy.png +0 -0
  238. data/{vendor → app}/assets/images/flags/uz.png +0 -0
  239. data/{vendor → app}/assets/images/flags/va.png +0 -0
  240. data/{vendor → app}/assets/images/flags/vc.png +0 -0
  241. data/{vendor → app}/assets/images/flags/ve.png +0 -0
  242. data/{vendor → app}/assets/images/flags/vg.png +0 -0
  243. data/{vendor → app}/assets/images/flags/vi.png +0 -0
  244. data/{vendor → app}/assets/images/flags/vn.png +0 -0
  245. data/{vendor → app}/assets/images/flags/vu.png +0 -0
  246. data/{vendor → app}/assets/images/flags/wales.png +0 -0
  247. data/{vendor → app}/assets/images/flags/wf.png +0 -0
  248. data/{vendor → app}/assets/images/flags/ws.png +0 -0
  249. data/{vendor → app}/assets/images/flags/ye.png +0 -0
  250. data/{vendor → app}/assets/images/flags/yt.png +0 -0
  251. data/{vendor → app}/assets/images/flags/za.png +0 -0
  252. data/{vendor → app}/assets/images/flags/zm.png +0 -0
  253. data/{vendor → app}/assets/images/flags/zw.png +0 -0
  254. data/app/assets/images/logo/spree_50.png +0 -0
  255. data/app/assets/images/spree_header.jpg +0 -0
  256. data/app/assets/javascripts/spree/frontend.js +1 -1
  257. data/app/assets/javascripts/spree/frontend/checkout/payment.js.coffee +2 -2
  258. data/app/assets/stylesheets/spree/frontend.css +4 -4
  259. data/app/assets/stylesheets/spree/frontend/_variables.scss +4 -61
  260. data/app/assets/stylesheets/spree/frontend/frontend_bootstrap.css.scss +102 -0
  261. data/app/controllers/spree/checkout_controller.rb +31 -27
  262. data/app/controllers/spree/orders_controller.rb +20 -8
  263. data/app/controllers/spree/store_controller.rb +2 -3
  264. data/app/controllers/spree/taxons_controller.rb +2 -2
  265. data/app/helpers/spree/frontend_helper.rb +93 -0
  266. data/app/helpers/spree/orders_helper.rb +16 -0
  267. data/app/helpers/spree/store_helper.rb +10 -0
  268. data/app/helpers/spree/taxons_helper.rb +19 -0
  269. data/app/models/spree/frontend_configuration.rb +1 -1
  270. data/app/views/kaminari/twitter-bootstrap-3/_first_page.html.erb +13 -0
  271. data/app/views/kaminari/twitter-bootstrap-3/_gap.html.erb +8 -0
  272. data/app/views/kaminari/twitter-bootstrap-3/_last_page.html.erb +13 -0
  273. data/app/views/kaminari/twitter-bootstrap-3/_next_page.html.erb +13 -0
  274. data/app/views/kaminari/twitter-bootstrap-3/_page.html.erb +12 -0
  275. data/app/views/kaminari/twitter-bootstrap-3/_paginator.html.erb +24 -0
  276. data/app/views/kaminari/twitter-bootstrap-3/_prev_page.html.erb +13 -0
  277. data/app/views/spree/address/_form.html.erb +24 -24
  278. data/app/views/spree/checkout/_address.html.erb +33 -22
  279. data/app/views/spree/checkout/_confirm.html.erb +10 -9
  280. data/app/views/spree/checkout/_delivery.html.erb +24 -20
  281. data/app/views/spree/checkout/_payment.html.erb +17 -18
  282. data/app/views/spree/checkout/_summary.html.erb +2 -2
  283. data/app/views/spree/checkout/edit.html.erb +23 -14
  284. data/app/views/spree/checkout/payment/_gateway.html.erb +31 -28
  285. data/app/views/spree/layouts/spree_application.html.erb +6 -12
  286. data/app/views/spree/orders/_adjustments.html.erb +5 -0
  287. data/app/views/spree/orders/_form.html.erb +8 -8
  288. data/app/views/spree/orders/_line_item.html.erb +6 -6
  289. data/app/views/spree/orders/edit.html.erb +14 -16
  290. data/app/views/spree/orders/show.html.erb +9 -4
  291. data/app/views/spree/products/_cart_form.html.erb +15 -11
  292. data/app/views/spree/products/_promotions.html.erb +1 -1
  293. data/app/views/spree/products/_properties.html.erb +2 -2
  294. data/app/views/spree/products/_taxons.html.erb +4 -4
  295. data/app/views/spree/products/_thumbnails.html.erb +3 -3
  296. data/app/views/spree/products/index.html.erb +13 -9
  297. data/app/views/spree/products/show.html.erb +11 -9
  298. data/app/views/spree/shared/_error_messages.html.erb +12 -0
  299. data/app/views/spree/shared/_filters.html.erb +4 -4
  300. data/app/views/spree/shared/_footer.html.erb +10 -6
  301. data/app/views/spree/shared/_google_add_items.js.erb +11 -0
  302. data/app/views/spree/shared/_google_analytics.js.erb +13 -0
  303. data/app/views/spree/shared/_google_checkout.js.erb +10 -0
  304. data/app/views/spree/shared/_google_purchase.js.erb +13 -0
  305. data/app/views/spree/shared/_head.html.erb +1 -1
  306. data/app/views/spree/shared/_header.html.erb +17 -5
  307. data/app/views/spree/shared/_login.html.erb +19 -0
  308. data/app/views/spree/shared/_login_bar.html.erb +6 -0
  309. data/app/views/spree/shared/_main_nav_bar.html.erb +15 -11
  310. data/app/views/spree/shared/_nav_bar.html.erb +3 -2
  311. data/app/views/spree/shared/_order_details.html.erb +30 -31
  312. data/app/views/spree/shared/_products.html.erb +19 -15
  313. data/app/views/spree/shared/_search.html.erb +8 -4
  314. data/app/views/spree/shared/_sidebar.html.erb +1 -1
  315. data/app/views/spree/shared/_taxonomies.html.erb +1 -1
  316. data/app/views/spree/taxons/show.html.erb +1 -1
  317. data/config/initializers/spree.rb +0 -2
  318. data/lib/spree/frontend.rb +5 -4
  319. data/lib/spree/frontend/engine.rb +2 -2
  320. data/script/rails +9 -0
  321. data/spec/controllers/controller_extension_spec.rb +115 -0
  322. data/spec/controllers/controller_helpers_spec.rb +26 -0
  323. data/spec/controllers/spree/checkout_controller_spec.rb +424 -0
  324. data/spec/controllers/spree/checkout_controller_with_views_spec.rb +36 -0
  325. data/spec/controllers/spree/content_controller_spec.rb +12 -0
  326. data/spec/controllers/spree/current_order_tracking_spec.rb +44 -0
  327. data/spec/controllers/spree/home_controller_spec.rb +27 -0
  328. data/spec/controllers/spree/orders_controller_ability_spec.rb +104 -0
  329. data/spec/controllers/spree/orders_controller_spec.rb +134 -0
  330. data/spec/controllers/spree/orders_controller_transitions_spec.rb +31 -0
  331. data/spec/controllers/spree/products_controller_spec.rb +36 -0
  332. data/spec/controllers/spree/taxons_controller_spec.rb +12 -0
  333. data/spec/features/address_spec.rb +93 -0
  334. data/spec/features/automatic_promotion_adjustments_spec.rb +47 -0
  335. data/spec/features/caching/products_spec.rb +55 -0
  336. data/spec/features/caching/taxons_spec.rb +22 -0
  337. data/spec/features/cart_spec.rb +84 -0
  338. data/spec/features/checkout_spec.rb +515 -0
  339. data/spec/features/checkout_unshippable_spec.rb +34 -0
  340. data/spec/features/coupon_code_spec.rb +87 -0
  341. data/spec/features/currency_spec.rb +18 -0
  342. data/spec/features/free_shipping_promotions_spec.rb +59 -0
  343. data/spec/features/locale_spec.rb +60 -0
  344. data/spec/features/order_spec.rb +74 -0
  345. data/spec/features/page_promotions_spec.rb +36 -0
  346. data/spec/features/products_spec.rb +262 -0
  347. data/spec/features/taxons_spec.rb +147 -0
  348. data/spec/features/template_rendering_spec.rb +19 -0
  349. data/spec/fixtures/thinking-cat.jpg +0 -0
  350. data/spec/helpers/frontend_helper_spec.rb +41 -0
  351. data/spec/helpers/order_helper_spec.rb +12 -0
  352. data/spec/helpers/taxons_helper_spec.rb +17 -0
  353. data/spec/spec_helper.rb +115 -0
  354. data/spec/support/shared_contexts/checkout_setup.rb +9 -0
  355. data/spec/support/shared_contexts/custom_products.rb +25 -0
  356. data/spec/support/shared_contexts/product_prototypes.rb +30 -0
  357. data/spec/views/spree/checkout/_summary_spec.rb +11 -0
  358. data/spree_frontend.gemspec +30 -0
  359. metadata +392 -282
  360. data/app/assets/images/icons/add-to-cart.png +0 -0
  361. data/app/assets/images/icons/checkout.png +0 -0
  362. data/app/assets/images/icons/delete.png +0 -0
  363. data/app/assets/images/icons/update.png +0 -0
  364. data/app/assets/images/spinner.gif +0 -0
  365. data/app/assets/images/spree/frontend/cart.png +0 -0
  366. data/app/assets/images/spree/frontend/select_arrow.gif +0 -0
  367. data/app/assets/stylesheets/spree/frontend/screen.css.scss +0 -1321
  368. data/app/views/spree/shared/_google_analytics.html.erb +0 -40
  369. data/config/initializers/assets.rb +0 -1
  370. data/config/initializers/check_for_orphaned_preferences.rb +0 -9
  371. data/config/initializers/deprecation_checker.rb +0 -7
  372. data/config/initializers/rails_5868.rb +0 -8
  373. data/lib/spree/frontend/preference_rescue.rb +0 -25
  374. data/vendor/assets/images/datepicker/cal.gif +0 -0
  375. data/vendor/assets/images/jquery.formalize/button.png +0 -0
  376. data/vendor/assets/images/jquery.formalize/select_arrow.gif +0 -0
  377. data/vendor/assets/javascripts/jquery.formalize.min.js +0 -1
  378. data/vendor/assets/stylesheets/jquery.formalize.css.erb +0 -363
@@ -22,25 +22,29 @@
22
22
  </div>
23
23
 
24
24
  <% if products.any? %>
25
- <ul id="products" class="inline product-listing" data-hook>
25
+ <div id="products" class="row" data-hook>
26
26
  <% products.each do |product| %>
27
- <% url = spree.product_path(product, :taxon_id => @taxon.try(:id)) %>
28
- <li id="product_<%= product.id %>" class="columns three <%= cycle("alpha", "secondary", "", "omega secondary", :name => "classes") %>" data-hook="products_list_item" itemscope itemtype="http://schema.org/Product">
29
- <% cache(@taxon.present? ? [I18n.locale, current_currency, @taxon, product] : [I18n.locale, current_currency, product]) do %>
30
- <div class="product-image">
31
- <%= link_to small_image(product, :itemprop => "image"), url, :itemprop => 'url' %>
32
- </div>
33
- <%= link_to truncate(product.name, :length => 50), url, :class => 'info', :itemprop => "name", :title => product.name %>
34
- <span itemprop="offers" itemscope itemtype="http://schema.org/Offer">
35
- <span class="price selling" itemprop="price"><%= display_price(product) %></span>
36
- </span>
37
- <% end %>
38
- </li>
27
+ <% url = product_url(product, taxon_id: @taxon.try(:id)) %>
28
+ <div id="product_<%= product.id %>" class="col-md-3 col-sm-6 product-list-item" data-hook="products_list_item" itemscope itemtype="http://schema.org/Product">
29
+ <div class="panel panel-default">
30
+ <% cache(@taxon.present? ? [I18n.locale, current_currency, @taxon, product] : [I18n.locale, current_currency, product]) do %>
31
+ <div class="panel-body text-center product-body">
32
+ <%= link_to small_image(product, itemprop: "image"), url, itemprop: 'url' %><br/>
33
+ <%= link_to truncate(product.name, length: 50), url, class: 'info', itemprop: "name", title: product.name %>
34
+ </div>
35
+ <div class="panel-footer text-center">
36
+ <span itemprop="offers" itemscope itemtype="http://schema.org/Offer">
37
+ <span class="price selling lead" itemprop="price"><%= display_price(product) %></span>
38
+ </span>
39
+ </div>
40
+ <% end %>
41
+ </div>
42
+ </div>
39
43
  <% end %>
40
44
  <% reset_cycle("classes") %>
41
- </ul>
45
+ </div>
42
46
  <% end %>
43
47
 
44
48
  <% if paginated_products.respond_to?(:num_pages) %>
45
- <%= paginate paginated_products %>
49
+ <%= paginate paginated_products, theme: 'twitter-bootstrap-3' %>
46
50
  <% end %>
@@ -1,11 +1,15 @@
1
1
  <% @taxons = @taxon && @taxon.parent ? @taxon.parent.children : Spree::Taxon.roots %>
2
- <%= form_tag spree.products_path, :method => :get do %>
2
+ <%= form_tag spree.products_path, :method => :get, class: "navbar-form" do %>
3
+ <div class="form-group">
3
4
  <% cache(cache_key_for_taxons) do %>
4
5
  <%= select_tag :taxon,
5
6
  options_for_select([[Spree.t(:all_departments), '']] +
6
7
  @taxons.map {|t| [t.name, t.id]},
7
- @taxon ? @taxon.id : params[:taxon]), 'aria-label' => 'Taxon' %>
8
+ @taxon ? @taxon.id : params[:taxon]), 'aria-label' => 'Taxon', class: "form-control" %>
8
9
  <% end %>
9
- <%= search_field_tag :keywords, params[:keywords], :placeholder => Spree.t(:search) %>
10
- <%= submit_tag Spree.t(:search), :name => nil %>
10
+ </div>
11
+ <div class="form-group">
12
+ <%= search_field_tag :keywords, params[:keywords], :placeholder => Spree.t(:search), class: "form-control" %>
13
+ </div>
14
+ <%= submit_tag Spree.t(:search), :name => nil, class: "btn btn-success" %>
11
15
  <% end %>
@@ -1,3 +1,3 @@
1
- <aside id="sidebar" class="columns four" data-hook>
1
+ <aside id="sidebar" class="col-sm-4 col-md-3" data-hook>
2
2
  <%= yield :sidebar %>
3
3
  </aside>
@@ -2,7 +2,7 @@
2
2
  <nav id="taxonomies" class="sidebar-item" data-hook>
3
3
  <% @taxonomies.each do |taxonomy| %>
4
4
  <% cache [I18n.locale, taxonomy, max_level] do %>
5
- <h6 class='taxonomy-root'><%= Spree.t(:shop_by_taxonomy, :taxonomy => taxonomy.name) %></h6>
5
+ <h4 class='taxonomy-root'><%= Spree.t(:shop_by_taxonomy, :taxonomy => taxonomy.name) %></h4>
6
6
  <%= taxons_tree(taxonomy.root, @taxon, max_level) %>
7
7
  <% end %>
8
8
  <% end %>
@@ -3,7 +3,7 @@
3
3
  <% content_for :sidebar do %>
4
4
  <div data-hook="taxon_sidebar_navigation">
5
5
  <%= render partial: 'spree/shared/taxonomies' %>
6
- <%= render partial: 'spree/shared/filters' if @taxon.leaf? %>
6
+ <%= render partial: 'spree/shared/filters' if @taxon.children.empty? %>
7
7
  </div>
8
8
  <% end %>
9
9
 
@@ -1,4 +1,2 @@
1
- require 'mail'
2
-
3
1
  # Spree Configuration
4
2
  SESSION_KEY = '_spree_session_id'
@@ -1,10 +1,11 @@
1
1
  require 'rails/all'
2
- require 'jquery-rails'
2
+ require 'sprockets/rails'
3
+
4
+ require 'bootstrap-sass'
3
5
  require 'canonical-rails'
4
6
  require 'deface'
5
-
7
+ require 'jquery-rails'
6
8
  require 'spree/core'
7
-
8
- require 'spree/responder'
9
9
  require 'spree/frontend/middleware/seo_assist'
10
10
  require 'spree/frontend/engine'
11
+ require 'spree/responder'
@@ -4,14 +4,14 @@ module Spree
4
4
  config.middleware.use "Spree::Frontend::Middleware::SeoAssist"
5
5
 
6
6
  # sets the manifests / assets to be precompiled, even when initialize_on_precompile is false
7
- initializer "spree.assets.precompile", :group => :all do |app|
7
+ initializer "spree.assets.precompile", group: :all do |app|
8
8
  app.config.assets.precompile += %w[
9
9
  spree/frontend/all*
10
10
  jquery.validate/localization/messages_*
11
11
  ]
12
12
  end
13
13
 
14
- initializer "spree.frontend.environment", :before => :load_config_initializers do |app|
14
+ initializer "spree.frontend.environment", before: :load_config_initializers do |app|
15
15
  Spree::Frontend::Config = Spree::FrontendConfiguration.new
16
16
  end
17
17
  end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/spree/frontend/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
9
+
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ # This test tests the functionality within
4
+ # spree/core/controller_helpers/respond_with.rb
5
+ # Rather than duck-punching the existing controllers, let's define a custom one:
6
+ class Spree::CustomController < Spree::BaseController
7
+ def index
8
+ respond_with(Spree::Address.new) do |format|
9
+ format.html { render :text => "neutral" }
10
+ end
11
+ end
12
+
13
+ def create
14
+ # Just need a model with validations
15
+ # Address is good enough, so let's go with that
16
+ address = Spree::Address.new(params[:address])
17
+ respond_with(address)
18
+ end
19
+ end
20
+
21
+ describe Spree::CustomController, :type => :controller do
22
+ after do
23
+ Spree::CustomController.clear_overrides!
24
+ end
25
+
26
+ context "extension testing" do
27
+ context "index" do
28
+ context "specify symbol for handler instead of Proc" do
29
+ before do
30
+ Spree::CustomController.class_eval do
31
+ respond_override({:index => {:html => {:success => :success_method}}})
32
+
33
+ private
34
+
35
+ def success_method
36
+ render :text => 'success!!!'
37
+ end
38
+ end
39
+ end
40
+ describe "GET" do
41
+ it "has value success" do
42
+ spree_get :index
43
+ expect(response).to be_success
44
+ assert (response.body =~ /success!!!/)
45
+ end
46
+ end
47
+ end
48
+
49
+ context "render" do
50
+ before do
51
+ Spree::CustomController.instance_eval do
52
+ respond_override({:index => {:html => {:success => lambda { render(:text => 'success!!!') }}}})
53
+ respond_override({:index => {:html => {:failure => lambda { render(:text => 'failure!!!') }}}})
54
+ end
55
+ end
56
+ describe "GET" do
57
+ it "has value success" do
58
+ spree_get :index
59
+ expect(response).to be_success
60
+ assert (response.body =~ /success!!!/)
61
+ end
62
+ end
63
+ end
64
+
65
+ context "redirect" do
66
+ before do
67
+ Spree::CustomController.instance_eval do
68
+ respond_override({:index => {:html => {:success => lambda { redirect_to('/cart') }}}})
69
+ respond_override({:index => {:html => {:failure => lambda { render(:text => 'failure!!!') }}}})
70
+ end
71
+ end
72
+ describe "GET" do
73
+ it "has value success" do
74
+ spree_get :index
75
+ expect(response).to be_redirect
76
+ end
77
+ end
78
+ end
79
+
80
+ context "validation error" do
81
+ before do
82
+ Spree::CustomController.instance_eval do
83
+ respond_to :html
84
+ respond_override({:create => {:html => {:success => lambda { render(:text => 'success!!!') }}}})
85
+ respond_override({:create => {:html => {:failure => lambda { render(:text => 'failure!!!') }}}})
86
+ end
87
+ end
88
+
89
+ describe "POST" do
90
+ it "has value success" do
91
+ spree_post :create
92
+ expect(response).to be_success
93
+ assert (response.body =~ /success!/)
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'A different controllers respond_override. Regression test for #1301' do
99
+ before do
100
+ Spree::CheckoutController.instance_eval do
101
+ respond_override({:index => {:html => {:success => lambda { render(:text => 'success!!!') }}}})
102
+ end
103
+ end
104
+ describe "POST" do
105
+ it "should not effect the wrong controller" do
106
+ spree_get :index
107
+ assert (response.body =~ /neutral/)
108
+ end
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ # In this file, we want to test that the controller helpers function correctly
4
+ # So we need to use one of the controllers inside Spree.
5
+ # ProductsController is good.
6
+ describe Spree::ProductsController, :type => :controller do
7
+
8
+ before do
9
+ I18n.enforce_available_locales = false
10
+ expect(I18n).to receive(:available_locales).and_return([:en, :de])
11
+ Spree::Frontend::Config[:locale] = :de
12
+ end
13
+
14
+ after do
15
+ Spree::Frontend::Config[:locale] = :en
16
+ I18n.locale = :en
17
+ I18n.enforce_available_locales = true
18
+ end
19
+
20
+ # Regression test for #1184
21
+ it "sets the default locale based off Spree::Frontend::Config[:locale]" do
22
+ expect(I18n.locale).to eq(:en)
23
+ spree_get :index
24
+ expect(I18n.locale).to eq(:de)
25
+ end
26
+ end
@@ -0,0 +1,424 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::CheckoutController, :type => :controller do
4
+ let(:token) { 'some_token' }
5
+ let(:user) { stub_model(Spree::LegacyUser) }
6
+ let(:order) { FactoryGirl.create(:order_with_totals) }
7
+
8
+ let(:address_params) do
9
+ address = FactoryGirl.build(:address)
10
+ address.attributes.except("created_at", "updated_at")
11
+ end
12
+
13
+ before do
14
+ allow(controller).to receive_messages try_spree_current_user: user
15
+ allow(controller).to receive_messages spree_current_user: user
16
+ allow(controller).to receive_messages current_order: order
17
+ end
18
+
19
+ context "#edit" do
20
+ it 'should check if the user is authorized for :edit' do
21
+ expect(controller).to receive(:authorize!).with(:edit, order, token)
22
+ request.cookie_jar.signed[:guest_token] = token
23
+ spree_get :edit, { state: 'address' }
24
+ end
25
+
26
+ it "should redirect to the cart path unless checkout_allowed?" do
27
+ allow(order).to receive_messages :checkout_allowed? => false
28
+ spree_get :edit, { :state => "delivery" }
29
+ expect(response).to redirect_to(spree.cart_path)
30
+ end
31
+
32
+ it "should redirect to the cart path if current_order is nil" do
33
+ allow(controller).to receive(:current_order).and_return(nil)
34
+ spree_get :edit, { :state => "delivery" }
35
+ expect(response).to redirect_to(spree.cart_path)
36
+ end
37
+
38
+ it "should redirect to cart if order is completed" do
39
+ allow(order).to receive_messages(:completed? => true)
40
+ spree_get :edit, { :state => "address" }
41
+ expect(response).to redirect_to(spree.cart_path)
42
+ end
43
+
44
+ # Regression test for #2280
45
+ it "should redirect to current step trying to access a future step" do
46
+ order.update_column(:state, "address")
47
+ spree_get :edit, { :state => "delivery" }
48
+ expect(response).to redirect_to spree.checkout_state_path("address")
49
+ end
50
+
51
+ context "when entering the checkout" do
52
+ before do
53
+ # The first step for checkout controller is address
54
+ # Transitioning into this state first is required
55
+ order.update_column(:state, "address")
56
+ end
57
+
58
+ it "should associate the order with a user" do
59
+ order.update_column :user_id, nil
60
+ expect(order).to receive(:associate_user!).with(user)
61
+ spree_get :edit, {}, order_id: 1
62
+ end
63
+ end
64
+ end
65
+
66
+ context "#update" do
67
+ it 'should check if the user is authorized for :edit' do
68
+ expect(controller).to receive(:authorize!).with(:edit, order, token)
69
+ request.cookie_jar.signed[:guest_token] = token
70
+ spree_post :update, { state: 'address' }
71
+ end
72
+
73
+ context "save successful" do
74
+ def spree_post_address
75
+ spree_post :update, {
76
+ :state => "address",
77
+ :order => {
78
+ :bill_address_attributes => address_params,
79
+ :use_billing => true
80
+ }
81
+ }
82
+ end
83
+
84
+ before do
85
+ # Must have *a* shipping method and a payment method so updating from address works
86
+ allow(order).to receive_messages :available_shipping_methods => [stub_model(Spree::ShippingMethod)]
87
+ allow(order).to receive_messages :available_payment_methods => [stub_model(Spree::PaymentMethod)]
88
+ allow(order).to receive_messages :ensure_available_shipping_rates => true
89
+ order.line_items << FactoryGirl.create(:line_item)
90
+ end
91
+
92
+ context "with the order in the cart state" do
93
+ before do
94
+ order.update_column(:state, "cart")
95
+ allow(order).to receive_messages :user => user
96
+ end
97
+
98
+ it "should assign order" do
99
+ spree_post :update, {:state => "address"}
100
+ expect(assigns[:order]).not_to be_nil
101
+ end
102
+
103
+ it "should advance the state" do
104
+ spree_post_address
105
+ expect(order.reload.state).to eq("delivery")
106
+ end
107
+
108
+ it "should redirect the next state" do
109
+ spree_post_address
110
+ expect(response).to redirect_to spree.checkout_state_path("delivery")
111
+ end
112
+
113
+ context "current_user respond to save address method" do
114
+ it "calls persist order address on user" do
115
+ expect(user).to receive(:persist_order_address)
116
+ spree_post :update, {
117
+ :state => "address",
118
+ :order => {
119
+ :bill_address_attributes => address_params,
120
+ :use_billing => true
121
+ },
122
+ :save_user_address => "1"
123
+ }
124
+ end
125
+ end
126
+
127
+ context "current_user doesnt respond to persist_order_address" do
128
+ it "doesnt raise any error" do
129
+ expect {
130
+ spree_post :update, {
131
+ :state => "address",
132
+ :order => {
133
+ :bill_address_attributes => address_params,
134
+ :use_billing => true
135
+ },
136
+ :save_user_address => "1"
137
+ }
138
+ }.to_not raise_error
139
+ end
140
+ end
141
+ end
142
+
143
+ context "with the order in the address state" do
144
+ before do
145
+ order.update_columns(ship_address_id: create(:address).id, state: "address")
146
+ allow(order).to receive_messages user: user
147
+ end
148
+
149
+ context "with a billing and shipping address" do
150
+ before do
151
+ @expected_bill_address_id = order.bill_address.id
152
+ @expected_ship_address_id = order.ship_address.id
153
+
154
+ spree_post :update, {
155
+ :state => "address",
156
+ :order => {
157
+ :bill_address_attributes => order.bill_address.attributes.except("created_at", "updated_at"),
158
+ :ship_address_attributes => order.ship_address.attributes.except("created_at", "updated_at"),
159
+ :use_billing => false
160
+ }
161
+ }
162
+
163
+ order.reload
164
+ end
165
+
166
+ it "updates the same billing and shipping address" do
167
+ expect(order.bill_address.id).to eq(@expected_bill_address_id)
168
+ expect(order.ship_address.id).to eq(@expected_ship_address_id)
169
+ end
170
+ end
171
+ end
172
+
173
+ context "when in the confirm state" do
174
+ before do
175
+ allow(order).to receive_messages :confirmation_required? => true
176
+ order.update_column(:state, "confirm")
177
+ allow(order).to receive_messages :user => user
178
+ # An order requires a payment to reach the complete state
179
+ # This is because payment_required? is true on the order
180
+ create(:payment, :amount => order.total, :order => order)
181
+ order.payments.reload
182
+ end
183
+
184
+ # This inadvertently is a regression test for #2694
185
+ it "should redirect to the order view" do
186
+ spree_post :update, {:state => "confirm"}
187
+ expect(response).to redirect_to spree.order_path(order)
188
+ end
189
+
190
+ it "should populate the flash message" do
191
+ spree_post :update, {:state => "confirm"}
192
+ expect(flash.notice).to eq(Spree.t(:order_processed_successfully))
193
+ end
194
+
195
+ it "should remove completed order from current_order" do
196
+ spree_post :update, {:state => "confirm"}, {:order_id => "foofah"}
197
+ expect(assigns(:current_order)).to be_nil
198
+ expect(assigns(:order)).to eql controller.current_order
199
+ end
200
+ end
201
+
202
+ # Regression test for #4190
203
+ context "state_lock_version" do
204
+ let(:post_params) {
205
+ {
206
+ state: "address",
207
+ order: {
208
+ bill_address_attributes: order.bill_address.attributes.except("created_at", "updated_at"),
209
+ state_lock_version: 0,
210
+ use_billing: true
211
+ }
212
+ }
213
+ }
214
+
215
+ context "correct" do
216
+ it "should properly update and increment version" do
217
+ spree_post :update, post_params
218
+ expect(order.state_lock_version).to eq 1
219
+ end
220
+ end
221
+
222
+ context "incorrect" do
223
+ before do
224
+ order.update_columns(state_lock_version: 1, state: "address")
225
+ end
226
+
227
+ it "order should receieve ensure_valid_order_version callback" do
228
+ expect_any_instance_of(described_class).to receive(:ensure_valid_state_lock_version)
229
+ spree_post :update, post_params
230
+ end
231
+
232
+ it "order should receieve with_lock message" do
233
+ expect(order).to receive(:with_lock)
234
+ spree_post :update, post_params
235
+ end
236
+
237
+ it "redirects back to current state" do
238
+ spree_post :update, post_params
239
+ expect(response).to redirect_to spree.checkout_state_path('address')
240
+ expect(flash[:error]).to eq "The order has already been updated."
241
+ end
242
+ end
243
+ end
244
+ end
245
+
246
+ context "save unsuccessful" do
247
+ before do
248
+ allow(order).to receive_messages :user => user
249
+ allow(order).to receive_messages :update_attributes => false
250
+ end
251
+
252
+ it "should not assign order" do
253
+ spree_post :update, {:state => "address"}
254
+ expect(assigns[:order]).not_to be_nil
255
+ end
256
+
257
+ it "should not change the order state" do
258
+ spree_post :update, { :state => 'address' }
259
+ end
260
+
261
+ it "should render the edit template" do
262
+ spree_post :update, { :state => 'address' }
263
+ expect(response).to render_template :edit
264
+ end
265
+ end
266
+
267
+ context "when current_order is nil" do
268
+ before { allow(controller).to receive_messages :current_order => nil }
269
+
270
+ it "should not change the state if order is completed" do
271
+ expect(order).not_to receive(:update_attribute)
272
+ spree_post :update, {:state => "confirm"}
273
+ end
274
+
275
+ it "should redirect to the cart_path" do
276
+ spree_post :update, {:state => "confirm"}
277
+ expect(response).to redirect_to spree.cart_path
278
+ end
279
+ end
280
+
281
+ context "Spree::Core::GatewayError" do
282
+ before do
283
+ allow(order).to receive_messages :user => user
284
+ allow(order).to receive(:update_attributes).and_raise(Spree::Core::GatewayError.new("Invalid something or other."))
285
+ spree_post :update, {:state => "address"}
286
+ end
287
+
288
+ it "should render the edit template and display exception message" do
289
+ expect(response).to render_template :edit
290
+ expect(flash.now[:error]).to eq(Spree.t(:spree_gateway_error_flash_for_checkout))
291
+ expect(assigns(:order).errors[:base]).to include("Invalid something or other.")
292
+ end
293
+ end
294
+
295
+ context "fails to transition from address" do
296
+ let(:order) do
297
+ FactoryGirl.create(:order_with_line_items).tap do |order|
298
+ order.next!
299
+ expect(order.state).to eq('address')
300
+ end
301
+ end
302
+
303
+ before do
304
+ allow(controller).to receive_messages :current_order => order
305
+ allow(controller).to receive_messages :check_authorization => true
306
+ end
307
+
308
+ context "when the country is not a shippable country" do
309
+ before do
310
+ order.ship_address.tap do |address|
311
+ # A different country which is not included in the list of shippable countries
312
+ address.country = FactoryGirl.create(:country, :name => "Australia")
313
+ address.state_name = 'Victoria'
314
+ address.save
315
+ end
316
+ end
317
+
318
+ it "due to no available shipping rates for any of the shipments" do
319
+ expect(order.shipments.count).to eq(1)
320
+ order.shipments.first.shipping_rates.delete_all
321
+ spree_put :update, :order => {}
322
+ expect(flash[:error]).to eq(Spree.t(:items_cannot_be_shipped))
323
+ expect(response).to redirect_to(spree.checkout_state_path('address'))
324
+ end
325
+ end
326
+
327
+ context "when the order is invalid" do
328
+ before do
329
+ allow(order).to receive_messages :update_attributes => true, :next => nil
330
+ order.errors.add :base, 'Base error'
331
+ order.errors.add :adjustments, 'error'
332
+ end
333
+
334
+ it "due to the order having errors" do
335
+ spree_put :update, :order => {}
336
+ expect(flash[:error]).to eq("Base error\nAdjustments error")
337
+ expect(response).to redirect_to(spree.checkout_state_path('address'))
338
+ end
339
+ end
340
+ end
341
+
342
+ context "fails to transition from payment to complete" do
343
+ let(:order) do
344
+ FactoryGirl.create(:order_with_line_items).tap do |order|
345
+ until order.state == 'payment'
346
+ order.next!
347
+ end
348
+ # So that the confirmation step is skipped and we get straight to the action.
349
+ payment_method = FactoryGirl.create(:simple_credit_card_payment_method)
350
+ payment = FactoryGirl.create(:payment, :payment_method => payment_method)
351
+ order.payments << payment
352
+ end
353
+ end
354
+
355
+ before do
356
+ allow(controller).to receive_messages :current_order => order
357
+ allow(controller).to receive_messages :check_authorization => true
358
+ end
359
+
360
+ it "when GatewayError is raised" do
361
+ allow_any_instance_of(Spree::Payment).to receive(:process!).and_raise(Spree::Core::GatewayError.new(Spree.t(:payment_processing_failed)))
362
+ spree_put :update, :order => {}
363
+ expect(flash[:error]).to eq(Spree.t(:payment_processing_failed))
364
+ end
365
+ end
366
+ end
367
+
368
+ context "When last inventory item has been purchased" do
369
+ let(:product) { mock_model(Spree::Product, :name => "Amazing Object") }
370
+ let(:variant) { mock_model(Spree::Variant) }
371
+ let(:line_item) { mock_model Spree::LineItem, :insufficient_stock? => true, :amount => 0 }
372
+ let(:order) { create(:order) }
373
+
374
+ before do
375
+ allow(order).to receive_messages(:line_items => [line_item], :state => "payment")
376
+
377
+ configure_spree_preferences do |config|
378
+ config.track_inventory_levels = true
379
+ end
380
+ end
381
+
382
+ context "and back orders are not allowed" do
383
+ before do
384
+ spree_post :update, { :state => "payment" }
385
+ end
386
+
387
+ it "should redirect to cart" do
388
+ expect(response).to redirect_to spree.cart_path
389
+ end
390
+
391
+ it "should set flash message for no inventory" do
392
+ expect(flash[:error]).to eq(Spree.t(:inventory_error_flash_for_insufficient_quantity , :names => "'#{product.name}'" ))
393
+ end
394
+ end
395
+ end
396
+
397
+ context "order doesn't have a delivery step" do
398
+ before do
399
+ allow(order).to receive_messages(:checkout_steps => ["cart", "address", "payment"])
400
+ allow(order).to receive_messages state: "address"
401
+ allow(controller).to receive_messages :check_authorization => true
402
+ end
403
+
404
+ it "doesn't set shipping address on the order" do
405
+ expect(order).to_not receive(:ship_address=)
406
+ spree_post :update
407
+ end
408
+
409
+ it "doesn't remove unshippable items before payment" do
410
+ expect {
411
+ spree_post :update, { :state => "payment" }
412
+ }.to_not change { order.line_items }
413
+ end
414
+ end
415
+
416
+ it "does remove unshippable items before payment" do
417
+ allow(order).to receive_messages :payment_required? => true
418
+ allow(controller).to receive_messages :check_authorization => true
419
+
420
+ expect {
421
+ spree_post :update, { :state => "payment" }
422
+ }.to change { order.line_items }
423
+ end
424
+ end