spree_core 3.1.14 → 3.2.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/{spree.js.coffee.erb → spree.js.coffee} +2 -2
  3. data/app/helpers/spree/base_helper.rb +1 -1
  4. data/app/helpers/spree/products_helper.rb +0 -6
  5. data/app/mailers/spree/reimbursement_mailer.rb +6 -6
  6. data/app/models/concerns/spree/acts_as_taggable.rb +11 -0
  7. data/app/models/concerns/spree/adjustment_source.rb +1 -1
  8. data/app/models/concerns/spree/ransackable_attributes.rb +0 -5
  9. data/app/models/spree/address.rb +67 -38
  10. data/app/models/spree/app_configuration.rb +9 -6
  11. data/app/models/spree/base.rb +1 -1
  12. data/app/models/spree/calculator.rb +1 -1
  13. data/app/models/spree/country.rb +5 -4
  14. data/app/models/spree/credit_card.rb +3 -3
  15. data/app/models/spree/gateway/bogus.rb +11 -11
  16. data/app/models/spree/gateway/bogus_simple.rb +4 -4
  17. data/app/models/spree/gateway.rb +1 -1
  18. data/app/models/spree/image.rb +2 -2
  19. data/app/models/spree/inventory_unit.rb +6 -10
  20. data/app/models/spree/line_item.rb +17 -6
  21. data/app/models/spree/order/checkout.rb +2 -2
  22. data/app/models/spree/order.rb +12 -25
  23. data/app/models/spree/order_contents.rb +7 -6
  24. data/app/models/spree/order_inventory.rb +12 -1
  25. data/app/models/spree/order_updater.rb +1 -2
  26. data/app/models/spree/payment/processing.rb +3 -3
  27. data/app/models/spree/payment_method.rb +7 -1
  28. data/app/models/spree/preferences/store.rb +3 -3
  29. data/app/models/spree/product/scopes.rb +16 -20
  30. data/app/models/spree/product.rb +11 -3
  31. data/app/models/spree/promotion/actions/create_line_items.rb +21 -3
  32. data/app/models/spree/promotion/rules/country.rb +23 -0
  33. data/app/models/spree/promotion/rules/option_value.rb +13 -10
  34. data/app/models/spree/promotion/rules/taxon.rb +1 -1
  35. data/app/models/spree/promotion.rb +35 -1
  36. data/app/models/spree/promotion_handler/cart.rb +3 -17
  37. data/app/models/spree/promotion_handler/coupon.rb +22 -22
  38. data/app/models/spree/promotion_handler/page.rb +2 -2
  39. data/app/models/spree/refund.rb +1 -1
  40. data/app/models/spree/refund_reason.rb +1 -1
  41. data/app/models/spree/reimbursement_type.rb +5 -1
  42. data/app/models/spree/return_item.rb +1 -1
  43. data/app/models/spree/shipment.rb +4 -6
  44. data/app/models/spree/shipment_handler.rb +1 -1
  45. data/app/models/spree/stock/adjuster.rb +9 -2
  46. data/app/models/spree/stock/coordinator.rb +11 -4
  47. data/app/models/spree/stock/inventory_unit_builder.rb +1 -1
  48. data/app/models/spree/stock/package.rb +11 -3
  49. data/app/models/spree/stock/packer.rb +15 -5
  50. data/app/models/spree/stock/prioritizer.rb +25 -15
  51. data/app/models/spree/stock/splitter/shipping_category.rb +6 -1
  52. data/app/models/spree/stock_item.rb +2 -1
  53. data/app/models/spree/stock_movement.rb +11 -6
  54. data/app/models/spree/store.rb +1 -0
  55. data/app/models/spree/store_credit.rb +1 -1
  56. data/app/models/spree/tag.rb +4 -0
  57. data/app/models/spree/tax_rate.rb +6 -0
  58. data/app/models/spree/taxon.rb +3 -3
  59. data/app/models/spree/variant.rb +6 -3
  60. data/app/models/spree/zone.rb +2 -2
  61. data/app/views/spree/shared/_paths.html.erb +8 -0
  62. data/config/initializers/acts_as_taggable_on.rb +9 -0
  63. data/config/initializers/friendly_id.rb +0 -81
  64. data/config/locales/en.yml +11 -0
  65. data/db/default/spree/countries.rb +5 -1
  66. data/db/default/spree/roles.rb +2 -2
  67. data/db/default/spree/states.rb +1 -1
  68. data/db/migrate/20120831092320_spree_one_two.rb +101 -101
  69. data/db/migrate/20120831092359_spree_promo_one_two.rb +14 -14
  70. data/db/migrate/20120905145253_add_tax_rate_label.rb +1 -1
  71. data/db/migrate/20120905151823_add_toggle_tax_rate_display.rb +2 -2
  72. data/db/migrate/20120929093553_remove_unused_preference_columns.rb +4 -4
  73. data/db/migrate/20121009142519_add_lock_version_to_variant.rb +2 -2
  74. data/db/migrate/20121010142909_add_states_required_to_countries.rb +2 -2
  75. data/db/migrate/20121012071449_add_on_demand_to_product_and_variant.rb +3 -3
  76. data/db/migrate/20121017010007_remove_not_null_constraint_from_products_on_hand.rb +5 -5
  77. data/db/migrate/20121031162139_split_prices_from_variants.rb +10 -10
  78. data/db/migrate/20121107003422_remove_not_null_from_spree_prices_amount.rb +3 -3
  79. data/db/migrate/20121107184631_add_currency_to_line_items.rb +1 -1
  80. data/db/migrate/20121107194006_add_currency_to_orders.rb +1 -1
  81. data/db/migrate/20121109173623_add_cost_currency_to_variants.rb +2 -2
  82. data/db/migrate/20121111231553_remove_display_on_from_payment_methods.rb +1 -1
  83. data/db/migrate/20121124203911_add_position_to_taxonomies.rb +2 -2
  84. data/db/migrate/20121126040517_add_last_ip_to_spree_orders.rb +1 -1
  85. data/db/migrate/20121213162028_add_state_to_spree_adjustments.rb +1 -1
  86. data/db/migrate/20130114053446_add_display_on_to_spree_payment_methods.rb +1 -1
  87. data/db/migrate/20130120201805_add_position_to_product_properties.spree.rb +2 -2
  88. data/db/migrate/20130203232234_add_identifier_to_spree_payments.rb +1 -1
  89. data/db/migrate/20130207155350_add_order_id_index_to_payments.rb +1 -1
  90. data/db/migrate/20130208032954_add_primary_to_spree_products_taxons.rb +1 -1
  91. data/db/migrate/20130211190146_create_spree_stock_items.rb +2 -2
  92. data/db/migrate/20130211191120_create_spree_stock_locations.rb +1 -1
  93. data/db/migrate/20130213191427_create_default_stock.rb +1 -2
  94. data/db/migrate/20130222032153_add_order_id_index_to_shipments.rb +1 -1
  95. data/db/migrate/20130226032817_change_meta_description_on_spree_products_to_text.rb +2 -2
  96. data/db/migrate/20130226191231_add_stock_location_id_to_spree_shipments.rb +1 -1
  97. data/db/migrate/20130227143905_add_pending_to_inventory_unit.rb +3 -3
  98. data/db/migrate/20130228164411_remove_on_demand_from_product_and_variant.rb +1 -1
  99. data/db/migrate/20130228210442_create_shipping_method_zone.rb +3 -3
  100. data/db/migrate/20130301162745_remove_shipping_category_id_from_shipping_method.rb +1 -1
  101. data/db/migrate/20130301162924_create_shipping_method_categories.rb +3 -3
  102. data/db/migrate/20130301205200_add_tracking_url_to_spree_shipping_methods.rb +1 -1
  103. data/db/migrate/20130304162240_create_spree_shipping_rates.rb +5 -5
  104. data/db/migrate/20130304192936_remove_category_match_attributes_from_shipping_method.rb +1 -1
  105. data/db/migrate/20130305143310_create_stock_movements.rb +1 -1
  106. data/db/migrate/20130306181701_add_address_fields_to_stock_location.rb +3 -3
  107. data/db/migrate/20130306191917_add_active_field_to_stock_locations.rb +2 -2
  108. data/db/migrate/20130306195650_add_backorderable_to_stock_item.rb +2 -2
  109. data/db/migrate/20130307161754_add_default_quantity_to_stock_movement.rb +2 -2
  110. data/db/migrate/20130318151756_add_source_and_destination_to_stock_movements.rb +1 -1
  111. data/db/migrate/20130319062004_change_orders_total_precision.rb +5 -5
  112. data/db/migrate/20130319063911_change_spree_payments_amount_precision.rb +2 -2
  113. data/db/migrate/20130319064308_change_spree_return_authorization_amount_precision.rb +2 -2
  114. data/db/migrate/20130319082943_change_adjustments_amount_precision.rb +2 -2
  115. data/db/migrate/20130319183250_add_originator_to_stock_movement.rb +1 -1
  116. data/db/migrate/20130319190507_drop_source_and_destination_from_stock_movement.rb +3 -3
  117. data/db/migrate/20130325163316_migrate_inventory_unit_sold_to_on_hand.rb +3 -3
  118. data/db/migrate/20130326175857_add_stock_location_to_rma.rb +1 -1
  119. data/db/migrate/20130328130308_update_shipment_state_for_canceled_orders.rb +1 -1
  120. data/db/migrate/20130328195253_add_seo_metas_to_taxons.rb +1 -1
  121. data/db/migrate/20130329134939_remove_stock_item_and_variant_lock.rb +1 -1
  122. data/db/migrate/20130413230529_add_name_to_spree_credit_cards.rb +1 -1
  123. data/db/migrate/20130414000512_update_name_fields_on_spree_credit_cards.rb +2 -2
  124. data/db/migrate/20130417120034_add_index_to_source_columns_on_adjustments.rb +1 -1
  125. data/db/migrate/20130417120035_update_adjustment_states.rb +3 -3
  126. data/db/migrate/20130417123427_add_shipping_rates_to_shipments.rb +4 -4
  127. data/db/migrate/20130418125341_create_spree_stock_transfers.rb +1 -1
  128. data/db/migrate/20130423110707_drop_products_count_on_hand.rb +1 -1
  129. data/db/migrate/20130423223847_set_default_shipping_rate_cost.rb +1 -1
  130. data/db/migrate/20130509115210_add_number_to_stock_transfer.rb +1 -1
  131. data/db/migrate/20130514151929_add_sku_index_to_spree_variants.rb +1 -1
  132. data/db/migrate/20130515180736_add_backorderable_default_to_spree_stock_location.rb +1 -1
  133. data/db/migrate/20130516151222_add_propage_all_variants_to_spree_stock_location.rb +1 -1
  134. data/db/migrate/20130611054351_rename_shipping_methods_zones_to_spree_shipping_methods_zones.rb +1 -1
  135. data/db/migrate/20130611185927_add_user_id_index_to_spree_orders.rb +1 -1
  136. data/db/migrate/20130618041418_add_updated_at_to_spree_countries.rb +1 -1
  137. data/db/migrate/20130619012236_add_updated_at_to_spree_states.rb +1 -1
  138. data/db/migrate/20130626232741_add_cvv_result_code_and_cvv_result_message_to_spree_payments.rb +1 -1
  139. data/db/migrate/20130628021056_add_unique_index_to_permalink_on_spree_products.rb +2 -2
  140. data/db/migrate/20130628022817_add_unique_index_to_orders_shipments_and_stock_transfers.rb +4 -4
  141. data/db/migrate/20130708052307_add_deleted_at_to_spree_tax_rates.rb +1 -1
  142. data/db/migrate/20130711200933_remove_lock_version_from_inventory_units.rb +1 -1
  143. data/db/migrate/20130718042445_add_cost_price_to_line_item.rb +2 -2
  144. data/db/migrate/20130718233855_set_backorderable_to_default_to_false.rb +3 -3
  145. data/db/migrate/20130725031716_add_created_by_id_to_spree_orders.rb +1 -1
  146. data/db/migrate/20130729214043_index_completed_at_on_spree_orders.rb +1 -1
  147. data/db/migrate/20130802014537_add_tax_category_id_to_spree_line_items.rb +1 -1
  148. data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +1 -1
  149. data/db/migrate/20130806022521_drop_spree_mail_methods.rb +1 -1
  150. data/db/migrate/20130806145853_set_default_stock_location_on_shipments.rb +1 -1
  151. data/db/migrate/20130807024301_upgrade_adjustments.rb +4 -4
  152. data/db/migrate/20130807024302_rename_adjustment_fields.rb +1 -1
  153. data/db/migrate/20130809164245_add_admin_name_column_to_spree_shipping_methods.rb +1 -1
  154. data/db/migrate/20130809164330_add_admin_name_column_to_spree_stock_locations.rb +1 -1
  155. data/db/migrate/20130813004002_add_shipment_total_to_spree_orders.rb +2 -2
  156. data/db/migrate/20130813140619_expand_order_number_size.rb +3 -3
  157. data/db/migrate/20130813232134_rename_activators_to_promotions.rb +1 -1
  158. data/db/migrate/20130815000406_add_adjustment_total_to_line_items.rb +2 -2
  159. data/db/migrate/20130815024413_add_adjustment_total_to_shipments.rb +2 -2
  160. data/db/migrate/20130826062534_add_depth_to_spree_taxons.rb +1 -1
  161. data/db/migrate/20130828234942_add_tax_total_to_line_items_shipments_and_orders.rb +2 -2
  162. data/db/migrate/20130830001033_add_shipping_category_to_shipping_methods_and_products.rb +2 -2
  163. data/db/migrate/20130830001159_migrate_old_shipping_calculators.rb +1 -1
  164. data/db/migrate/20130903183026_add_code_to_spree_promotion_rules.rb +1 -1
  165. data/db/migrate/20130909115621_change_states_required_for_countries.rb +1 -1
  166. data/db/migrate/20130915032339_add_deleted_at_to_spree_stock_items.rb +1 -1
  167. data/db/migrate/20130917024658_remove_promotions_event_name_field.rb +1 -1
  168. data/db/migrate/20130924040529_add_promo_total_to_line_items_and_shipments_and_orders.rb +1 -1
  169. data/db/migrate/20131001013410_remove_unused_credit_card_fields.rb +2 -2
  170. data/db/migrate/20131026154747_add_track_inventory_to_variant.rb +2 -2
  171. data/db/migrate/20131107132123_add_tax_category_to_variants.rb +1 -1
  172. data/db/migrate/20131113035136_add_channel_to_spree_orders.rb +1 -1
  173. data/db/migrate/20131118043959_add_included_to_adjustments.rb +2 -2
  174. data/db/migrate/20131118050234_rename_tax_total_fields.rb +1 -1
  175. data/db/migrate/20131118183431_add_line_item_id_to_spree_inventory_units.rb +1 -1
  176. data/db/migrate/20131120234456_add_updated_at_to_variants.rb +1 -1
  177. data/db/migrate/20131127001002_add_position_to_classifications.rb +1 -1
  178. data/db/migrate/20131211112807_create_spree_orders_promotions.rb +2 -2
  179. data/db/migrate/20131211192741_unique_shipping_method_categories.rb +1 -1
  180. data/db/migrate/20131218054603_add_item_count_to_spree_orders.rb +2 -2
  181. data/db/migrate/20140106065820_remove_value_type_from_spree_preferences.rb +1 -1
  182. data/db/migrate/20140106224208_rename_permalink_to_slug_for_products.rb +1 -1
  183. data/db/migrate/20140120160805_add_index_to_variant_id_and_currency_on_prices.rb +1 -1
  184. data/db/migrate/20140124023232_rename_activator_id_in_rules_and_actions_to_promotion_id.rb +1 -1
  185. data/db/migrate/20140129024326_add_deleted_at_to_spree_prices.rb +1 -1
  186. data/db/migrate/20140203161722_add_approver_id_and_approved_at_to_orders.rb +1 -1
  187. data/db/migrate/20140204115338_add_confirmation_delivered_to_spree_orders.rb +1 -1
  188. data/db/migrate/20140204192230_add_auto_capture_to_payment_methods.rb +1 -1
  189. data/db/migrate/20140205120320_create_spree_payment_capture_events.rb +1 -1
  190. data/db/migrate/20140205144710_add_uncaptured_amount_to_payments.rb +1 -1
  191. data/db/migrate/20140205181631_default_variant_weight_to_zero.rb +1 -1
  192. data/db/migrate/20140207085910_add_tax_category_id_to_shipping_methods.rb +1 -1
  193. data/db/migrate/20140207093021_add_tax_rate_id_to_shipping_rates.rb +1 -1
  194. data/db/migrate/20140211040159_add_pre_tax_amount_to_line_items_and_shipments.rb +1 -1
  195. data/db/migrate/20140213184916_add_more_indexes.rb +1 -1
  196. data/db/migrate/20140219060952_add_considered_risky_to_orders.rb +2 -2
  197. data/db/migrate/20140227112348_add_preference_store_to_everything.rb +1 -1
  198. data/db/migrate/20140307235515_add_user_id_to_spree_credit_cards.rb +1 -1
  199. data/db/migrate/20140309023735_migrate_old_preferences.rb +1 -1
  200. data/db/migrate/20140309024355_create_spree_stores.rb +2 -2
  201. data/db/migrate/20140309033438_create_store_from_preferences.rb +2 -2
  202. data/db/migrate/20140315053743_add_timestamps_to_spree_assets.rb +1 -1
  203. data/db/migrate/20140318191500_create_spree_taxons_promotion_rules.rb +1 -1
  204. data/db/migrate/20140331100557_add_additional_store_fields.rb +1 -1
  205. data/db/migrate/20140410141842_add_many_missing_indexes.rb +1 -1
  206. data/db/migrate/20140410150358_correct_some_polymorphic_index_and_add_more_missing.rb +1 -1
  207. data/db/migrate/20140415041315_add_user_id_created_by_id_index_to_order.rb +1 -1
  208. data/db/migrate/20140508151342_change_spree_price_amount_precision.rb +5 -5
  209. data/db/migrate/20140518174634_add_token_to_spree_orders.rb +1 -1
  210. data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +2 -2
  211. data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +1 -1
  212. data/db/migrate/20140604135309_drop_credit_card_first_name_and_last_name.rb +1 -1
  213. data/db/migrate/20140609201656_add_deleted_at_to_spree_promotion_actions.rb +1 -1
  214. data/db/migrate/20140616202624_remove_uncaptured_amount_from_spree_payments.rb +1 -1
  215. data/db/migrate/20140625214618_create_spree_refunds.rb +1 -1
  216. data/db/migrate/20140702140656_create_spree_return_authorization_inventory_unit.rb +1 -1
  217. data/db/migrate/20140707125621_rename_return_authorization_inventory_unit_to_return_items.rb +1 -1
  218. data/db/migrate/20140709160534_backfill_line_item_pre_tax_amount.rb +1 -1
  219. data/db/migrate/20140710041921_recreate_spree_return_authorizations.rb +2 -2
  220. data/db/migrate/20140710181204_add_amount_fields_to_return_items.rb +1 -1
  221. data/db/migrate/20140710190048_drop_return_authorization_amount.rb +1 -1
  222. data/db/migrate/20140713140455_create_spree_return_authorization_reasons.rb +1 -1
  223. data/db/migrate/20140713140527_create_spree_refund_reasons.rb +1 -1
  224. data/db/migrate/20140713142214_rename_return_authorization_reason.rb +1 -1
  225. data/db/migrate/20140715182625_create_spree_promotion_categories.rb +1 -1
  226. data/db/migrate/20140716204111_drop_received_at_on_return_items.rb +1 -1
  227. data/db/migrate/20140716212330_add_reception_and_acceptance_status_to_return_items.rb +1 -1
  228. data/db/migrate/20140717155155_create_default_refund_reason.rb +1 -1
  229. data/db/migrate/20140717185932_add_default_to_spree_stock_locations.rb +1 -1
  230. data/db/migrate/20140718133010_create_spree_customer_returns.rb +1 -1
  231. data/db/migrate/20140718133349_add_customer_return_id_to_return_item.rb +1 -1
  232. data/db/migrate/20140718195325_create_friendly_id_slugs.rb +5 -5
  233. data/db/migrate/20140723004419_rename_spree_refund_return_authorization_id.rb +1 -1
  234. data/db/migrate/20140723152808_increase_return_item_pre_tax_amount_precision.rb +1 -1
  235. data/db/migrate/20140723214541_copy_product_slugs_to_slug_history.rb +2 -2
  236. data/db/migrate/20140725131539_create_spree_reimbursements.rb +1 -1
  237. data/db/migrate/20140728225422_add_promotionable_to_spree_products.rb +1 -1
  238. data/db/migrate/20140729133613_add_exchange_inventory_unit_foreign_keys.rb +1 -1
  239. data/db/migrate/20140730155938_add_acceptance_status_errors_to_return_item.rb +1 -1
  240. data/db/migrate/20140731150017_create_spree_reimbursement_types.rb +1 -1
  241. data/db/migrate/20140804185157_add_default_to_shipment_cost.rb +1 -1
  242. data/db/migrate/20140805171035_add_default_to_spree_credit_cards.rb +1 -1
  243. data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +1 -1
  244. data/db/migrate/20140806144901_add_type_to_reimbursement_type.rb +1 -1
  245. data/db/migrate/20140808184039_create_spree_reimbursement_credits.rb +1 -1
  246. data/db/migrate/20140827170513_add_meta_title_to_spree_products.rb +1 -1
  247. data/db/migrate/20140911173301_add_kind_to_zone.rb +1 -1
  248. data/db/migrate/20140924164824_add_code_to_spree_tax_categories.rb +1 -1
  249. data/db/migrate/20140927193717_default_pre_tax_amount_should_be_zero.rb +1 -1
  250. data/db/migrate/20141002191113_add_code_to_spree_shipping_methods.rb +1 -1
  251. data/db/migrate/20141007230328_add_cancel_audit_fields_to_spree_orders.rb +1 -1
  252. data/db/migrate/20141009204607_add_store_id_to_orders.rb +1 -1
  253. data/db/migrate/20141012083513_create_spree_taxons_prototypes.rb +1 -1
  254. data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +1 -1
  255. data/db/migrate/20141023005240_add_counter_cache_from_spree_variants_to_spree_stock_items.rb +2 -7
  256. data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +1 -1
  257. data/db/migrate/20141105213646_update_classifications_positions.rb +1 -1
  258. data/db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb +1 -1
  259. data/db/migrate/20141215232040_remove_token_permissions_table.rb +1 -1
  260. data/db/migrate/20141215235502_remove_extra_products_slug_index.rb +1 -1
  261. data/db/migrate/20141217215630_update_product_slug_index.rb +1 -1
  262. data/db/migrate/20141218025915_rename_identifier_to_number_for_payment.rb +1 -1
  263. data/db/migrate/20150118210639_create_spree_store_credits.rb +1 -1
  264. data/db/migrate/20150118211500_create_spree_store_credit_categories.rb +1 -1
  265. data/db/migrate/20150118212051_create_spree_store_credit_events.rb +1 -1
  266. data/db/migrate/20150118212101_create_spree_store_credit_types.rb +1 -1
  267. data/db/migrate/20150121022521_remove_environment_from_payment_method.rb +1 -1
  268. data/db/migrate/20150122145607_add_resellable_to_return_items.rb +1 -1
  269. data/db/migrate/20150122202432_add_code_to_spree_promotion_categories.rb +1 -1
  270. data/db/migrate/20150128032538_remove_environment_from_tracker.rb +1 -1
  271. data/db/migrate/20150128060325_remove_spree_configurations.rb +1 -1
  272. data/db/migrate/20150216173445_add_index_to_spree_stock_items_variant_id.rb +1 -1
  273. data/db/migrate/20150309161154_ensure_payments_have_numbers.rb +1 -1
  274. data/db/migrate/20150314013438_add_missing_indexes_on_spree_tables.rb +1 -1
  275. data/db/migrate/20150317174308_remove_duplicated_indexes_from_multi_columns.rb +1 -1
  276. data/db/migrate/20150324104002_remove_user_index_from_spree_state_changes.rb +1 -1
  277. data/db/migrate/20150515211137_fix_adjustment_order_id.rb +1 -1
  278. data/db/migrate/20150522071831_add_position_to_spree_payment_methods.rb +1 -1
  279. data/db/migrate/20150522181728_add_deleted_at_to_friendly_id_slugs.rb +1 -1
  280. data/db/migrate/20150609093816_increase_scale_on_pre_tax_amounts.rb +1 -1
  281. data/db/migrate/20150626181949_add_taxable_adjustment_total_to_line_item.rb +1 -1
  282. data/db/migrate/20150627090949_migrate_payment_methods_display.rb +1 -1
  283. data/db/migrate/20150707204155_enable_acts_as_paranoid_on_calculators.rb +1 -1
  284. data/db/migrate/20150714154102_spree_payment_method_store_credits.rb +1 -1
  285. data/db/migrate/20150726141425_rename_has_and_belongs_to_associations_to_model_names.rb +1 -1
  286. data/db/migrate/20150727191614_spree_store_credit_types.rb +1 -1
  287. data/db/migrate/20150819154308_add_discontinued_to_products_and_variants.rb +1 -1
  288. data/db/migrate/20151220072838_remove_shipping_method_id_from_spree_orders.rb +1 -1
  289. data/db/migrate/20160207191757_add_id_column_to_earlier_habtm_tables.rb +1 -1
  290. data/db/migrate/20160219165458_add_indexes.rb +1 -1
  291. data/db/migrate/20160509064646_remove_counter_cache_from_spree_variants_to_spree_stock_items.rb +10 -0
  292. data/db/migrate/20160511071954_acts_as_taggable_on_spree_migration.rb +40 -0
  293. data/db/migrate/20160511072249_change_collation_for_spree_tag_names.rb +9 -0
  294. data/db/migrate/20160511072335_add_missing_indexes_to_spree_taggings.rb +14 -0
  295. data/db/migrate/20160608090604_add_zipcode_required_to_spree_countries.rb +7 -0
  296. data/db/migrate/20161014145148_add_created_at_to_variant.rb +8 -0
  297. data/db/migrate/20161014152814_add_null_false_to_spree_variants_timestamps.rb +6 -0
  298. data/lib/generators/spree/custom_user/custom_user_generator.rb +1 -1
  299. data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +3 -3
  300. data/lib/generators/spree/custom_user/templates/migration.rb.tt +2 -2
  301. data/lib/generators/spree/dummy/dummy_generator.rb +11 -11
  302. data/lib/generators/spree/dummy/templates/rails/application.rb +1 -1
  303. data/lib/generators/spree/dummy/templates/rails/database.yml +9 -6
  304. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -2
  305. data/lib/generators/spree/install/install_generator.rb +37 -13
  306. data/lib/spree/core/controller_helpers/common.rb +3 -3
  307. data/lib/spree/core/controller_helpers/order.rb +2 -5
  308. data/lib/spree/core/controller_helpers/respond_with.rb +1 -1
  309. data/lib/spree/core/delegate_belongs_to.rb +2 -2
  310. data/lib/spree/core/engine.rb +5 -4
  311. data/lib/spree/core/importer/product.rb +2 -2
  312. data/lib/spree/core/product_duplicator.rb +1 -1
  313. data/lib/spree/core/product_filters.rb +1 -1
  314. data/lib/spree/core/search/base.rb +1 -1
  315. data/lib/spree/core/version.rb +1 -1
  316. data/lib/spree/i18n/initializer.rb +1 -1
  317. data/lib/spree/money.rb +1 -15
  318. data/lib/spree/permitted_attributes.rb +1 -1
  319. data/lib/spree/testing_support/caching.rb +3 -3
  320. data/lib/spree/testing_support/common_rake.rb +0 -2
  321. data/lib/spree/testing_support/controller_requests.rb +4 -4
  322. data/lib/spree/testing_support/factories/line_item_factory.rb +0 -1
  323. data/lib/spree/testing_support/factories/order_factory.rb +1 -0
  324. data/lib/spree/testing_support/factories/tag_factory.rb +5 -0
  325. data/lib/spree/testing_support/kernel.rb +18 -0
  326. data/lib/spree/testing_support/order_walkthrough.rb +4 -4
  327. data/lib/tasks/core.rake +2 -2
  328. data/spec/helpers/base_helper_spec.rb +200 -0
  329. data/spec/helpers/products_helper_spec.rb +289 -0
  330. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  331. data/spec/lib/i18n_spec.rb +123 -0
  332. data/spec/lib/search/base_spec.rb +86 -0
  333. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +103 -0
  334. data/spec/lib/spree/core/controller_helpers/order_spec.rb +110 -0
  335. data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
  336. data/spec/lib/spree/core/controller_helpers/store_spec.rb +72 -0
  337. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
  338. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
  339. data/spec/lib/spree/core/importer/order_spec.rb +605 -0
  340. data/spec/lib/spree/core/number_generator_spec.rb +175 -0
  341. data/spec/lib/spree/core/token_generator_spec.rb +24 -0
  342. data/spec/lib/spree/core/validators/email_spec.rb +53 -0
  343. data/spec/lib/spree/core_spec.rb +23 -0
  344. data/spec/lib/spree/localized_number_spec.rb +48 -0
  345. data/spec/lib/spree/migrations_spec.rb +36 -0
  346. data/spec/lib/spree/money_spec.rb +122 -0
  347. data/spec/lib/tasks/exchanges_spec.rb +136 -0
  348. data/spec/mailers/order_mailer_spec.rb +122 -0
  349. data/spec/mailers/reimbursement_mailer_spec.rb +47 -0
  350. data/spec/mailers/shipment_mailer_spec.rb +81 -0
  351. data/spec/mailers/test_mailer_spec.rb +38 -0
  352. data/spec/models/option_type_prototype_spec.rb +9 -0
  353. data/spec/models/spree/ability_spec.rb +251 -0
  354. data/spec/models/spree/address_spec.rb +402 -0
  355. data/spec/models/spree/adjustable/adjuster/base_spec.rb +10 -0
  356. data/spec/models/spree/adjustable/adjuster/promotion_spec.rb +211 -0
  357. data/spec/models/spree/adjustable/adjuster/tax_spec.rb +86 -0
  358. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +26 -0
  359. data/spec/models/spree/adjustment_spec.rb +189 -0
  360. data/spec/models/spree/app_configuration_spec.rb +26 -0
  361. data/spec/models/spree/asset_spec.rb +28 -0
  362. data/spec/models/spree/calculator/default_tax_spec.rb +152 -0
  363. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  364. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  365. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  366. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  367. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  368. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +47 -0
  369. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  370. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  371. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  372. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  373. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +29 -0
  374. data/spec/models/spree/calculator/shipping.rb +8 -0
  375. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +40 -0
  376. data/spec/models/spree/calculator/tiered_percent_spec.rb +51 -0
  377. data/spec/models/spree/calculator_spec.rb +69 -0
  378. data/spec/models/spree/classification_spec.rb +93 -0
  379. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  380. data/spec/models/spree/concerns/user_methods_spec.rb +82 -0
  381. data/spec/models/spree/concerns/vat_price_calculation_spec.rb +66 -0
  382. data/spec/models/spree/country_spec.rb +55 -0
  383. data/spec/models/spree/credit_card_spec.rb +328 -0
  384. data/spec/models/spree/customer_return_spec.rb +240 -0
  385. data/spec/models/spree/exchange_spec.rb +75 -0
  386. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  387. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  388. data/spec/models/spree/gateway_spec.rb +61 -0
  389. data/spec/models/spree/image_spec.rb +8 -0
  390. data/spec/models/spree/inventory_unit_spec.rb +256 -0
  391. data/spec/models/spree/line_item_spec.rb +346 -0
  392. data/spec/models/spree/option_type_spec.rb +14 -0
  393. data/spec/models/spree/option_value_spec.rb +18 -0
  394. data/spec/models/spree/order/address_spec.rb +50 -0
  395. data/spec/models/spree/order/adjustments_spec.rb +29 -0
  396. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  397. data/spec/models/spree/order/checkout_spec.rb +770 -0
  398. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  399. data/spec/models/spree/order/finalizing_spec.rb +114 -0
  400. data/spec/models/spree/order/helpers_spec.rb +5 -0
  401. data/spec/models/spree/order/payment_spec.rb +214 -0
  402. data/spec/models/spree/order/risk_assessment_spec.rb +84 -0
  403. data/spec/models/spree/order/shipments_spec.rb +43 -0
  404. data/spec/models/spree/order/state_machine_spec.rb +212 -0
  405. data/spec/models/spree/order/store_credit_spec.rb +426 -0
  406. data/spec/models/spree/order/tax_spec.rb +84 -0
  407. data/spec/models/spree/order/totals_spec.rb +24 -0
  408. data/spec/models/spree/order/updating_spec.rb +18 -0
  409. data/spec/models/spree/order/validations_spec.rb +15 -0
  410. data/spec/models/spree/order_contents_spec.rb +297 -0
  411. data/spec/models/spree/order_inventory_spec.rb +239 -0
  412. data/spec/models/spree/order_merger_spec.rb +135 -0
  413. data/spec/models/spree/order_spec.rb +1046 -0
  414. data/spec/models/spree/order_updater_spec.rb +294 -0
  415. data/spec/models/spree/payment/gateway_options_spec.rb +127 -0
  416. data/spec/models/spree/payment/store_credit_spec.rb +60 -0
  417. data/spec/models/spree/payment_method/store_credit_spec.rb +291 -0
  418. data/spec/models/spree/payment_method_spec.rb +103 -0
  419. data/spec/models/spree/payment_spec.rb +919 -0
  420. data/spec/models/spree/preference_spec.rb +80 -0
  421. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  422. data/spec/models/spree/preferences/preferable_spec.rb +344 -0
  423. data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
  424. data/spec/models/spree/preferences/store_spec.rb +46 -0
  425. data/spec/models/spree/price_spec.rb +128 -0
  426. data/spec/models/spree/product/scopes_spec.rb +183 -0
  427. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  428. data/spec/models/spree/product_filter_spec.rb +26 -0
  429. data/spec/models/spree/product_option_type_spec.rb +9 -0
  430. data/spec/models/spree/product_promotion_rule_spec.rb +9 -0
  431. data/spec/models/spree/product_property_spec.rb +22 -0
  432. data/spec/models/spree/product_spec.rb +619 -0
  433. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +50 -0
  434. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +148 -0
  435. data/spec/models/spree/promotion/actions/create_line_items_spec.rb +86 -0
  436. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +36 -0
  437. data/spec/models/spree/promotion/rules/country_spec.rb +36 -0
  438. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  439. data/spec/models/spree/promotion/rules/item_total_spec.rb +282 -0
  440. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  441. data/spec/models/spree/promotion/rules/option_value_spec.rb +90 -0
  442. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  443. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  444. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  445. data/spec/models/spree/promotion/rules/user_spec.rb +45 -0
  446. data/spec/models/spree/promotion_action_spec.rb +10 -0
  447. data/spec/models/spree/promotion_category_spec.rb +17 -0
  448. data/spec/models/spree/promotion_handler/cart_spec.rb +102 -0
  449. data/spec/models/spree/promotion_handler/coupon_spec.rb +323 -0
  450. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +48 -0
  451. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  452. data/spec/models/spree/promotion_rule_spec.rb +29 -0
  453. data/spec/models/spree/promotion_rule_taxon_spec.rb +9 -0
  454. data/spec/models/spree/promotion_rule_user_spec.rb +9 -0
  455. data/spec/models/spree/promotion_spec.rb +679 -0
  456. data/spec/models/spree/property_prototype_spec.rb +9 -0
  457. data/spec/models/spree/property_spec.rb +5 -0
  458. data/spec/models/spree/prototype_spec.rb +5 -0
  459. data/spec/models/spree/prototype_taxon_spec.rb +9 -0
  460. data/spec/models/spree/refund_reason_spec.rb +20 -0
  461. data/spec/models/spree/refund_spec.rb +195 -0
  462. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  463. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  464. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  465. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  466. data/spec/models/spree/reimbursement_spec.rb +188 -0
  467. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +63 -0
  468. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  469. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  470. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +55 -0
  471. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +101 -0
  472. data/spec/models/spree/return_authorization_reason_spec.rb +7 -0
  473. data/spec/models/spree/return_authorization_spec.rb +230 -0
  474. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  475. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  476. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +61 -0
  477. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  478. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  479. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  480. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  481. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  482. data/spec/models/spree/return_item_spec.rb +731 -0
  483. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  484. data/spec/models/spree/role_spec.rb +7 -0
  485. data/spec/models/spree/shipment_spec.rb +742 -0
  486. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  487. data/spec/models/spree/shipping_category_spec.rb +19 -0
  488. data/spec/models/spree/shipping_method_spec.rb +95 -0
  489. data/spec/models/spree/shipping_rate_spec.rb +140 -0
  490. data/spec/models/spree/state_spec.rb +29 -0
  491. data/spec/models/spree/stock/availability_validator_spec.rb +36 -0
  492. data/spec/models/spree/stock/content_item_spec.rb +31 -0
  493. data/spec/models/spree/stock/coordinator_spec.rb +61 -0
  494. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  495. data/spec/models/spree/stock/estimator_spec.rb +202 -0
  496. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  497. data/spec/models/spree/stock/package_spec.rb +182 -0
  498. data/spec/models/spree/stock/packer_spec.rb +70 -0
  499. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  500. data/spec/models/spree/stock/quantifier_spec.rb +126 -0
  501. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  502. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  503. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +47 -0
  504. data/spec/models/spree/stock/splitter/weight_spec.rb +32 -0
  505. data/spec/models/spree/stock_item_spec.rb +432 -0
  506. data/spec/models/spree/stock_location_spec.rb +243 -0
  507. data/spec/models/spree/stock_movement_spec.rb +120 -0
  508. data/spec/models/spree/stock_transfer_spec.rb +50 -0
  509. data/spec/models/spree/store_credit_event_spec.rb +101 -0
  510. data/spec/models/spree/store_credit_spec.rb +786 -0
  511. data/spec/models/spree/store_spec.rb +78 -0
  512. data/spec/models/spree/tax_category_spec.rb +32 -0
  513. data/spec/models/spree/tax_rate_spec.rb +561 -0
  514. data/spec/models/spree/taxon_spec.rb +85 -0
  515. data/spec/models/spree/taxonomy_spec.rb +18 -0
  516. data/spec/models/spree/tracker_spec.rb +21 -0
  517. data/spec/models/spree/user_spec.rb +203 -0
  518. data/spec/models/spree/variant_spec.rb +809 -0
  519. data/spec/models/spree/zone_member_spec.rb +38 -0
  520. data/spec/models/spree/zone_spec.rb +472 -0
  521. data/spec/spec_helper.rb +79 -0
  522. data/spec/support/big_decimal.rb +5 -0
  523. data/spec/support/concerns/adjustment_source.rb +23 -0
  524. data/spec/support/concerns/default_price.rb +37 -0
  525. data/spec/support/rake.rb +13 -0
  526. data/spec/support/test_gateway.rb +2 -0
  527. data/spree_core.gemspec +12 -12
  528. metadata +249 -43
  529. data/config/initializers/premailer_rails.rb +0 -3
@@ -0,0 +1,919 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Payment, type: :model do
4
+ let(:order) { Spree::Order.create }
5
+ let(:refund_reason) { create(:refund_reason) }
6
+
7
+ let(:gateway) do
8
+ gateway = Spree::Gateway::Bogus.new(active: true)
9
+ allow(gateway).to receive_messages source_required: true
10
+ gateway
11
+ end
12
+
13
+ let(:avs_code) { 'D' }
14
+ let(:cvv_code) { 'M' }
15
+
16
+ let(:card) { create :credit_card }
17
+
18
+ let(:payment) do
19
+ payment = Spree::Payment.new
20
+ payment.source = card
21
+ payment.order = order
22
+ payment.payment_method = gateway
23
+ payment.amount = 5
24
+ payment
25
+ end
26
+
27
+ let(:amount_in_cents) { (payment.amount * 100).round }
28
+
29
+ let!(:success_response) do
30
+ ActiveMerchant::Billing::Response.new(true, '', {}, {
31
+ authorization: '123',
32
+ cvv_result: cvv_code,
33
+ avs_result: { code: avs_code }
34
+ })
35
+ end
36
+
37
+ let(:failed_response) do
38
+ ActiveMerchant::Billing::Response.new(false, '', {}, {})
39
+ end
40
+
41
+ before(:each) do
42
+ # So it doesn't create log entries every time a processing method is called
43
+ allow(payment.log_entries).to receive(:create!)
44
+ end
45
+
46
+ describe 'delegate' do
47
+ it { is_expected.to delegate_method(:currency).to(:order) }
48
+ end
49
+
50
+ describe 'Constants' do
51
+ it { expect(Spree::Payment::INVALID_STATES).to eq(%w(failed invalid)) }
52
+ end
53
+
54
+ describe 'scopes' do
55
+ describe '.valid' do
56
+ let!(:invalid_payment) do
57
+ create(:payment, avs_response: 'Y', cvv_response_code: 'M', cvv_response_message: '', state: 'invalid')
58
+ end
59
+
60
+ let!(:failed_payment) do
61
+ create(:payment, avs_response: 'Y', cvv_response_code: 'M', cvv_response_message: '', state: 'failed')
62
+ end
63
+
64
+ let!(:checkout_payment) do
65
+ create(:payment, avs_response: 'A', cvv_response_code: 'M', cvv_response_message: '', state: 'checkout')
66
+ end
67
+
68
+ let!(:completed_payment) do
69
+ create(:payment, avs_response: 'Y', cvv_response_code: 'N', cvv_response_message: '', state: 'completed')
70
+ end
71
+
72
+ subject { Spree::Payment.valid }
73
+
74
+ it { is_expected.to_not include(invalid_payment) }
75
+ it { is_expected.to_not include(failed_payment) }
76
+ it { is_expected.to include(checkout_payment) }
77
+ it { is_expected.to include(completed_payment) }
78
+ end
79
+ end
80
+
81
+ context '.risky' do
82
+
83
+ let!(:payment_1) { create(:payment, avs_response: 'Y', cvv_response_code: 'M', cvv_response_message: 'Match') }
84
+ let!(:payment_2) { create(:payment, avs_response: 'Y', cvv_response_code: 'M', cvv_response_message: '') }
85
+ let!(:payment_3) { create(:payment, avs_response: 'A', cvv_response_code: 'M', cvv_response_message: 'Match') }
86
+ let!(:payment_4) { create(:payment, avs_response: 'Y', cvv_response_code: 'N', cvv_response_message: 'No Match') }
87
+
88
+ it 'should not return successful responses' do
89
+ expect(subject.class.risky.to_a).to match_array([payment_3, payment_4])
90
+ end
91
+ end
92
+
93
+ context "#captured_amount" do
94
+ context "calculates based on capture events" do
95
+ it "with 0 capture events" do
96
+ expect(payment.captured_amount).to eq(0)
97
+ end
98
+
99
+ it "with some capture events" do
100
+ payment.save
101
+ payment.capture_events.create!(amount: 2.0)
102
+ payment.capture_events.create!(amount: 3.0)
103
+ expect(payment.captured_amount).to eq(5)
104
+ end
105
+ end
106
+ end
107
+
108
+ context '#uncaptured_amount' do
109
+ context "calculates based on capture events" do
110
+ it "with 0 capture events" do
111
+ expect(payment.uncaptured_amount).to eq(5.0)
112
+ end
113
+
114
+ it "with some capture events" do
115
+ payment.save
116
+ payment.capture_events.create!(amount: 2.0)
117
+ payment.capture_events.create!(amount: 3.0)
118
+ expect(payment.uncaptured_amount).to eq(0)
119
+ end
120
+ end
121
+ end
122
+
123
+ context 'validations' do
124
+ it "returns useful error messages when source is invalid" do
125
+ payment.source = Spree::CreditCard.new
126
+ expect(payment).not_to be_valid
127
+ cc_errors = payment.errors['Credit Card']
128
+ expect(cc_errors).to include("Number can't be blank")
129
+ expect(cc_errors).to include("Month is not a number")
130
+ expect(cc_errors).to include("Year is not a number")
131
+ expect(cc_errors).to include("Verification Value can't be blank")
132
+ end
133
+ end
134
+
135
+ # Regression test for https://github.com/spree/spree/pull/2224
136
+ context 'failure' do
137
+ it 'should transition to failed from pending state' do
138
+ payment.state = 'pending'
139
+ payment.failure
140
+ expect(payment.state).to eql('failed')
141
+ end
142
+
143
+ it 'should transition to failed from processing state' do
144
+ payment.state = 'processing'
145
+ payment.failure
146
+ expect(payment.state).to eql('failed')
147
+ end
148
+ end
149
+
150
+ context 'invalidate' do
151
+ it 'should transition from checkout to invalid' do
152
+ payment.state = 'checkout'
153
+ payment.invalidate
154
+ expect(payment.state).to eq('invalid')
155
+ end
156
+ end
157
+
158
+ context "processing" do
159
+ describe "#process!" do
160
+ it "should purchase if with auto_capture" do
161
+ expect(payment.payment_method).to receive(:auto_capture?).and_return(true)
162
+ payment.process!
163
+ expect(payment).to be_completed
164
+ end
165
+
166
+ it "should authorize without auto_capture" do
167
+ expect(payment.payment_method).to receive(:auto_capture?).and_return(false)
168
+ payment.process!
169
+ expect(payment).to be_pending
170
+ end
171
+
172
+ it "should make the state 'processing'" do
173
+ expect(payment).to receive(:started_processing!)
174
+ payment.process!
175
+ end
176
+
177
+ it "should invalidate if payment method doesnt support source" do
178
+ expect(payment.payment_method).to receive(:supports?).with(payment.source).and_return(false)
179
+ expect { payment.process!}.to raise_error(Spree::Core::GatewayError)
180
+ expect(payment.state).to eq('invalid')
181
+ end
182
+
183
+ # Regression test for #4598
184
+ it "should allow payments with a gateway_customer_profile_id" do
185
+ allow(payment.source).to receive_messages gateway_customer_profile_id: "customer_1"
186
+ expect(payment.payment_method).to receive(:supports?).with(payment.source).and_return(false)
187
+ expect(payment).to receive(:started_processing!)
188
+ payment.process!
189
+ end
190
+
191
+ # Another regression test for #4598
192
+ it "should allow payments with a gateway_payment_profile_id" do
193
+ allow(payment.source).to receive_messages gateway_payment_profile_id: "customer_1"
194
+ expect(payment.payment_method).to receive(:supports?).with(payment.source).and_return(false)
195
+ expect(payment).to receive(:started_processing!)
196
+ payment.process!
197
+ end
198
+ end
199
+
200
+ describe "#authorize!" do
201
+ it "should call authorize on the gateway with the payment amount" do
202
+ expect(payment.payment_method).to receive(:authorize).with(amount_in_cents,
203
+ card,
204
+ anything).and_return(success_response)
205
+ payment.authorize!
206
+ end
207
+
208
+ it "should call authorize on the gateway with the currency code" do
209
+ allow(payment).to receive_messages currency: 'GBP'
210
+ expect(payment.payment_method).to receive(:authorize).with(amount_in_cents,
211
+ card,
212
+ hash_including({currency: "GBP"})).and_return(success_response)
213
+ payment.authorize!
214
+ end
215
+
216
+ it "should log the response" do
217
+ payment.save!
218
+ expect(payment.log_entries).to receive(:create!).with(details: anything)
219
+ payment.authorize!
220
+ end
221
+
222
+ context "if successful" do
223
+ before do
224
+ expect(payment.payment_method).to receive(:authorize).with(amount_in_cents,
225
+ card,
226
+ anything).and_return(success_response)
227
+ end
228
+
229
+ it "should store the response_code, avs_response and cvv_response fields" do
230
+ payment.authorize!
231
+ expect(payment.response_code).to eq('123')
232
+ expect(payment.avs_response).to eq(avs_code)
233
+ expect(payment.cvv_response_code).to eq(cvv_code)
234
+ expect(payment.cvv_response_message).to eq(ActiveMerchant::Billing::CVVResult::MESSAGES[cvv_code])
235
+ end
236
+
237
+ it "should make payment pending" do
238
+ expect(payment).to receive(:pend!)
239
+ payment.authorize!
240
+ end
241
+ end
242
+
243
+ context "if unsuccessful" do
244
+ it "should mark payment as failed" do
245
+ allow(gateway).to receive(:authorize).and_return(failed_response)
246
+ expect(payment).to receive(:failure)
247
+ expect(payment).not_to receive(:pend)
248
+ expect {
249
+ payment.authorize!
250
+ }.to raise_error(Spree::Core::GatewayError)
251
+ end
252
+ end
253
+ end
254
+
255
+ describe "#purchase!" do
256
+ it "should call purchase on the gateway with the payment amount" do
257
+ expect(gateway).to receive(:purchase).with(amount_in_cents, card, anything).and_return(success_response)
258
+ payment.purchase!
259
+ end
260
+
261
+ it "should log the response" do
262
+ payment.save!
263
+ expect(payment.log_entries).to receive(:create!).with(details: anything)
264
+ payment.purchase!
265
+ end
266
+
267
+ context "if successful" do
268
+ before do
269
+ expect(payment.payment_method).to receive(:purchase).with(amount_in_cents,
270
+ card,
271
+ anything).and_return(success_response)
272
+ end
273
+
274
+ it "should store the response_code and avs_response" do
275
+ payment.purchase!
276
+ expect(payment.response_code).to eq('123')
277
+ expect(payment.avs_response).to eq(avs_code)
278
+ end
279
+
280
+ it "should make payment complete" do
281
+ expect(payment).to receive(:complete!)
282
+ payment.purchase!
283
+ end
284
+
285
+ it "should log a capture event" do
286
+ payment.purchase!
287
+ expect(payment.capture_events.count).to eq(1)
288
+ expect(payment.capture_events.first.amount).to eq(payment.amount)
289
+ end
290
+
291
+ it "should set the uncaptured amount to 0" do
292
+ payment.purchase!
293
+ expect(payment.uncaptured_amount).to eq(0)
294
+ end
295
+ end
296
+
297
+ context "if unsuccessful" do
298
+ before do
299
+ allow(gateway).to receive(:purchase).and_return(failed_response)
300
+ expect(payment).to receive(:failure)
301
+ expect(payment).not_to receive(:pend)
302
+ end
303
+
304
+ it "should make payment failed" do
305
+ expect { payment.purchase! }.to raise_error(Spree::Core::GatewayError)
306
+ end
307
+
308
+ it "should not log a capture event" do
309
+ expect { payment.purchase! }.to raise_error(Spree::Core::GatewayError)
310
+ expect(payment.capture_events.count).to eq(0)
311
+ end
312
+ end
313
+ end
314
+
315
+ describe "#capture!" do
316
+ context "when payment is pending" do
317
+ before do
318
+ payment.amount = 100
319
+ payment.state = 'pending'
320
+ payment.response_code = '12345'
321
+ end
322
+
323
+ context "if successful" do
324
+ context 'for entire amount' do
325
+ before do
326
+ expect(payment.payment_method).to receive(:capture).with(payment.display_amount.money.cents, payment.response_code, anything).and_return(success_response)
327
+ end
328
+
329
+ it "should make payment complete" do
330
+ expect(payment).to receive(:complete!)
331
+ payment.capture!
332
+ end
333
+
334
+ it "logs capture events" do
335
+ payment.capture!
336
+ expect(payment.capture_events.count).to eq(1)
337
+ expect(payment.capture_events.first.amount).to eq(payment.amount)
338
+ end
339
+ end
340
+
341
+ context 'for partial amount' do
342
+ let(:original_amount) { payment.money.money.cents }
343
+ let(:capture_amount) { original_amount - 100 }
344
+
345
+ before do
346
+ expect(payment.payment_method).to receive(:capture).with(capture_amount, payment.response_code, anything).and_return(success_response)
347
+ end
348
+
349
+ it "should make payment complete & create pending payment for remaining amount" do
350
+ expect(payment).to receive(:complete!)
351
+ payment.capture!(capture_amount)
352
+ order = payment.order
353
+ payments = order.payments
354
+
355
+ expect(payments.size).to eq 2
356
+ expect(payments.pending.first.amount).to eq 1
357
+ # Payment stays processing for spec because of receive(:complete!) stub.
358
+ expect(payments.processing.first.amount).to eq(capture_amount / 100)
359
+ expect(payments.processing.first.source).to eq(payments.pending.first.source)
360
+ end
361
+
362
+ it "logs capture events" do
363
+ payment.capture!(capture_amount)
364
+ expect(payment.capture_events.count).to eq(1)
365
+ expect(payment.capture_events.first.amount).to eq(capture_amount / 100)
366
+ end
367
+ end
368
+ end
369
+
370
+ context "if unsuccessful" do
371
+ it "should not make payment complete" do
372
+ allow(gateway).to receive_messages capture: failed_response
373
+ expect(payment).to receive(:failure)
374
+ expect(payment).not_to receive(:complete)
375
+ expect { payment.capture! }.to raise_error(Spree::Core::GatewayError)
376
+ end
377
+ end
378
+ end
379
+
380
+ # Regression test for #2119
381
+ context "when payment is completed" do
382
+ before do
383
+ payment.state = 'completed'
384
+ end
385
+
386
+ it "should do nothing" do
387
+ expect(payment).not_to receive(:complete)
388
+ expect(payment.payment_method).not_to receive(:capture)
389
+ expect(payment.log_entries).not_to receive(:create!)
390
+ payment.capture!
391
+ end
392
+ end
393
+ end
394
+
395
+ describe "#void_transaction!" do
396
+ before do
397
+ payment.response_code = '123'
398
+ payment.state = 'pending'
399
+ end
400
+
401
+ context "when profiles are supported" do
402
+ it "should call payment_gateway.void with the payment's response_code" do
403
+ allow(gateway).to receive_messages payment_profiles_supported?: true
404
+ expect(gateway).to receive(:void).with('123', card, anything).and_return(success_response)
405
+ payment.void_transaction!
406
+ end
407
+ end
408
+
409
+ context "when profiles are not supported" do
410
+ it "should call payment_gateway.void with the payment's response_code" do
411
+ allow(gateway).to receive_messages payment_profiles_supported?: false
412
+ expect(gateway).to receive(:void).with('123', anything).and_return(success_response)
413
+ payment.void_transaction!
414
+ end
415
+ end
416
+
417
+ it "should log the response" do
418
+ expect(payment.log_entries).to receive(:create!).with(details: anything)
419
+ payment.void_transaction!
420
+ end
421
+
422
+ context "if successful" do
423
+ it "should update the response_code with the authorization from the gateway" do
424
+ # Change it to something different
425
+ payment.response_code = 'abc'
426
+ payment.void_transaction!
427
+ expect(payment.response_code).to eq('12345')
428
+ end
429
+ end
430
+
431
+ context "if unsuccessful" do
432
+ it "should not void the payment" do
433
+ allow(gateway).to receive_messages void: failed_response
434
+ expect(payment).not_to receive(:void)
435
+ expect { payment.void_transaction! }.to raise_error(Spree::Core::GatewayError)
436
+ end
437
+ end
438
+
439
+ # Regression test for #2119
440
+ context "if payment is already voided" do
441
+ before do
442
+ payment.state = 'void'
443
+ end
444
+
445
+ it "should not void the payment" do
446
+ expect(payment.payment_method).not_to receive(:void)
447
+ payment.void_transaction!
448
+ end
449
+ end
450
+ end
451
+
452
+ end
453
+
454
+ context "when already processing" do
455
+ it "should return nil without trying to process the source" do
456
+ payment.state = 'processing'
457
+
458
+ expect(payment.process!).to be_nil
459
+ end
460
+ end
461
+
462
+ context "with source required" do
463
+ context "raises an error if no source is specified" do
464
+ before do
465
+ payment.source = nil
466
+ end
467
+
468
+ specify do
469
+ expect { payment.process! }.to raise_error(Spree::Core::GatewayError, Spree.t(:payment_processing_failed))
470
+ end
471
+ end
472
+ end
473
+
474
+ context "with source optional" do
475
+ context "raises no error if source is not specified" do
476
+ before do
477
+ payment.source = nil
478
+ allow(payment.payment_method).to receive_messages(source_required?: false)
479
+ end
480
+
481
+ specify do
482
+ expect { payment.process! }.not_to raise_error
483
+ end
484
+ end
485
+ end
486
+
487
+ describe "#credit_allowed" do
488
+ # Regression test for #4403 & #4407
489
+ it "is the difference between offsets total and payment amount" do
490
+ payment.amount = 100
491
+ allow(payment).to receive(:offsets_total).and_return(0)
492
+ expect(payment.credit_allowed).to eq(100)
493
+ allow(payment).to receive(:offsets_total).and_return(-80)
494
+ expect(payment.credit_allowed).to eq(20)
495
+ end
496
+ end
497
+
498
+ describe "#can_credit?" do
499
+ it "is true if credit_allowed > 0" do
500
+ allow(payment).to receive(:credit_allowed).and_return(100)
501
+ expect(payment.can_credit?).to be true
502
+ end
503
+
504
+ it "is false if credit_allowed is 0" do
505
+ allow(payment).to receive(:credit_allowed).and_return(0)
506
+ expect(payment.can_credit?).to be false
507
+ end
508
+ end
509
+
510
+ describe "#save" do
511
+ context "captured payments" do
512
+ it "update order payment total" do
513
+ payment = create(:payment, order: order, state: 'completed')
514
+ expect(order.payment_total).to eq payment.amount
515
+ end
516
+ end
517
+
518
+ context "not completed payments" do
519
+ it "doesn't update order payment total" do
520
+ expect {
521
+ Spree::Payment.create(amount: 100, order: order)
522
+ }.not_to change { order.payment_total }
523
+ end
524
+
525
+ it "requires a payment method" do
526
+ expect(Spree::Payment.create(amount: 100, order: order)).to have(1).error_on(:payment_method)
527
+ end
528
+ end
529
+
530
+ context 'when the payment was completed but now void' do
531
+ let(:payment) do
532
+ Spree::Payment.create(
533
+ amount: 100,
534
+ order: order,
535
+ state: 'completed'
536
+ )
537
+ end
538
+
539
+ it 'updates order payment total' do
540
+ payment.void
541
+ expect(order.payment_total).to eq 0
542
+ end
543
+ end
544
+
545
+ context "completed orders" do
546
+ before { allow(order).to receive_messages completed?: true }
547
+
548
+ it "updates payment_state and shipments" do
549
+ expect(order.updater).to receive(:update_payment_state)
550
+ expect(order.updater).to receive(:update_shipment_state)
551
+ Spree::Payment.create(amount: 100, order: order, payment_method: gateway)
552
+ end
553
+ end
554
+
555
+ context "when profiles are supported" do
556
+ before do
557
+ allow(gateway).to receive_messages payment_profiles_supported?: true
558
+ allow(payment.source).to receive_messages has_payment_profile?: false
559
+ end
560
+
561
+ context "when there is an error connecting to the gateway" do
562
+ it "should call gateway_error " do
563
+ message = double("gateway_error")
564
+ connection_error = ActiveMerchant::ConnectionError.new(message, nil)
565
+ expect(gateway).to receive(:create_profile).and_raise(connection_error)
566
+ expect do
567
+ Spree::Payment.create(
568
+ amount: 100,
569
+ order: order,
570
+ source: card,
571
+ payment_method: gateway
572
+ )
573
+ end.to raise_error(Spree::Core::GatewayError)
574
+ end
575
+ end
576
+
577
+ context "with multiple payment attempts" do
578
+ let(:attributes) { attributes_for(:credit_card) }
579
+ it "should not try to create profiles on old failed payment attempts" do
580
+ allow_any_instance_of(Spree::Payment).to receive(:payment_method) { gateway }
581
+
582
+ order.payments.create!(
583
+ source_attributes: attributes,
584
+ payment_method: gateway,
585
+ amount: 100
586
+ )
587
+ expect(gateway).to receive(:create_profile).exactly :once
588
+ expect(order.payments.count).to eq(1)
589
+ order.payments.create!(
590
+ source_attributes: attributes,
591
+ payment_method: gateway,
592
+ amount: 100
593
+ )
594
+ end
595
+
596
+ end
597
+
598
+ context "when successfully connecting to the gateway" do
599
+ it "should create a payment profile" do
600
+ expect(payment.payment_method).to receive :create_profile
601
+ payment = Spree::Payment.create(
602
+ amount: 100,
603
+ order: order,
604
+ source: card,
605
+ payment_method: gateway
606
+ )
607
+ end
608
+ end
609
+ end
610
+
611
+ context "when profiles are not supported" do
612
+ before { allow(gateway).to receive_messages payment_profiles_supported?: false }
613
+
614
+ it "should not create a payment profile" do
615
+ expect(gateway).not_to receive :create_profile
616
+ payment = Spree::Payment.create(
617
+ amount: 100,
618
+ order: order,
619
+ source: card,
620
+ payment_method: gateway
621
+ )
622
+ end
623
+ end
624
+ end
625
+
626
+ describe "#build_source" do
627
+ let(:params) do
628
+ {
629
+ amount: 100,
630
+ payment_method: gateway,
631
+ source_attributes: {
632
+ expiry:"01 / 99",
633
+ number: '1234567890123',
634
+ verification_value: '123',
635
+ name: 'Spree Commerce'
636
+ }
637
+ }
638
+ end
639
+
640
+ it "should build the payment's source" do
641
+ payment = Spree::Payment.new(params)
642
+ expect(payment).to be_valid
643
+ expect(payment.source).not_to be_nil
644
+ end
645
+
646
+ it "assigns user and gateway to payment source" do
647
+ order = create(:order)
648
+ source = order.payments.new(params).source
649
+
650
+ expect(source.user_id).to eq order.user_id
651
+ expect(source.payment_method_id).to eq gateway.id
652
+ end
653
+
654
+ it "errors when payment source not valid" do
655
+ params = { amount: 100, payment_method: gateway,
656
+ source_attributes: {expiry: "1 / 12" }}
657
+
658
+ payment = Spree::Payment.new(params)
659
+ expect(payment).not_to be_valid
660
+ expect(payment.source).not_to be_nil
661
+ expect(payment.source.error_on(:number).size).to eq(1)
662
+ expect(payment.source.error_on(:verification_value).size).to eq(1)
663
+ end
664
+
665
+ it "does not build a new source when duplicating the model with source_attributes set" do
666
+ payment = create(:payment)
667
+ payment.source_attributes = params[:source_attributes]
668
+ expect { payment.dup }.to_not change { payment.source }
669
+ end
670
+ end
671
+
672
+ describe "#currency" do
673
+ before { allow(order).to receive(:currency) { "ABC" } }
674
+ it "returns the order currency" do
675
+ expect(payment.currency).to eq("ABC")
676
+ end
677
+ end
678
+
679
+ describe "#display_amount" do
680
+ it "returns a Spree::Money for this amount" do
681
+ expect(payment.display_amount).to eq(Spree::Money.new(payment.amount))
682
+ end
683
+ end
684
+
685
+ # Regression test for #2216
686
+ describe "#gateway_options" do
687
+ before { allow(order).to receive_messages(last_ip_address: "192.168.1.1") }
688
+
689
+ it "contains an IP" do
690
+ expect(payment.gateway_options[:ip]).to eq(order.last_ip_address)
691
+ end
692
+
693
+ it "contains the email address from a persisted order" do
694
+ # Sets the payment's order to a different Ruby object entirely
695
+ payment.order = Spree::Order.find(payment.order_id)
696
+ email = 'foo@example.com'
697
+ order.update_attributes(email: email)
698
+ expect(payment.gateway_options[:email]).to eq(email)
699
+ end
700
+ end
701
+
702
+ describe "#amount=" do
703
+ before do
704
+ subject.amount = amount
705
+ end
706
+
707
+ context "when the amount is a string" do
708
+ context "amount is a decimal" do
709
+ let(:amount) { '2.99' }
710
+
711
+ it '#amount' do
712
+ expect(subject.amount).to eql(BigDecimal('2.99'))
713
+ end
714
+ end
715
+
716
+ context "amount is an integer" do
717
+ let(:amount) { '2' }
718
+
719
+ it '#amount' do
720
+ expect(subject.amount).to eql(BigDecimal('2.0'))
721
+ end
722
+ end
723
+
724
+ context "amount contains a dollar sign" do
725
+ let(:amount) { '$2.99' }
726
+
727
+ it '#amount' do
728
+ expect(subject.amount).to eql(BigDecimal('2.99'))
729
+ end
730
+ end
731
+
732
+ context "amount contains a comma" do
733
+ let(:amount) { '$2,999.99' }
734
+
735
+ it '#amount' do
736
+ expect(subject.amount).to eql(BigDecimal('2999.99'))
737
+ end
738
+ end
739
+
740
+ context "amount contains a negative sign" do
741
+ let(:amount) { '-2.99' }
742
+
743
+ it '#amount' do
744
+ expect(subject.amount).to eql(BigDecimal('-2.99'))
745
+ end
746
+ end
747
+
748
+ context "amount is invalid" do
749
+ let(:amount) { 'invalid' }
750
+
751
+ # this is a strange default for ActiveRecord
752
+
753
+ it '#amount' do
754
+ expect(subject.amount).to eql(BigDecimal('0'))
755
+ end
756
+ end
757
+
758
+ context "amount is an empty string" do
759
+ let(:amount) { '' }
760
+
761
+ it '#amount' do
762
+ expect(subject.amount).to be_nil
763
+ end
764
+ end
765
+ end
766
+
767
+ context "when the amount is a number" do
768
+ let(:amount) { 1.55 }
769
+
770
+ it '#amount' do
771
+ expect(subject.amount).to eql(BigDecimal('1.55'))
772
+ end
773
+ end
774
+
775
+ context "when the locale uses a coma as a decimal separator" do
776
+ before(:each) do
777
+ I18n.backend.store_translations(:fr, { number: { currency: { format: { delimiter: ' ', separator: ',' } } } })
778
+ I18n.locale = :fr
779
+ subject.amount = amount
780
+ end
781
+
782
+ after do
783
+ I18n.locale = I18n.default_locale
784
+ end
785
+
786
+ context "amount is a decimal" do
787
+ let(:amount) { '2,99' }
788
+
789
+ it '#amount' do
790
+ expect(subject.amount).to eql(BigDecimal('2.99'))
791
+ end
792
+ end
793
+
794
+ context "amount contains a $ sign" do
795
+ let(:amount) { '2,99 $' }
796
+
797
+ it '#amount' do
798
+ expect(subject.amount).to eql(BigDecimal('2.99'))
799
+ end
800
+ end
801
+
802
+ context "amount is a number" do
803
+ let(:amount) { 2.99 }
804
+
805
+ it '#amount' do
806
+ expect(subject.amount).to eql(BigDecimal('2.99'))
807
+ end
808
+ end
809
+
810
+ context "amount contains a negative sign" do
811
+ let(:amount) { '-2,99 $' }
812
+
813
+ it '#amount' do
814
+ expect(subject.amount).to eql(BigDecimal('-2.99'))
815
+ end
816
+ end
817
+
818
+ context "amount uses a dot as a decimal separator" do
819
+ let(:amount) { '2.99' }
820
+
821
+ it '#amount' do
822
+ expect(subject.amount).to eql(BigDecimal('2.99'))
823
+ end
824
+ end
825
+ end
826
+ end
827
+
828
+ describe "is_avs_risky?" do
829
+ it "returns false if avs_response included in NON_RISKY_AVS_CODES" do
830
+ ('A'..'Z').reject{ |x| subject.class::RISKY_AVS_CODES.include?(x) }.to_a.each do |char|
831
+ payment.update_attribute(:avs_response, char)
832
+ expect(payment.is_avs_risky?).to eq false
833
+ end
834
+ end
835
+
836
+ it "returns false if avs_response.blank?" do
837
+ payment.update_attribute(:avs_response, nil)
838
+ expect(payment.is_avs_risky?).to eq false
839
+ payment.update_attribute(:avs_response, '')
840
+ expect(payment.is_avs_risky?).to eq false
841
+ end
842
+
843
+ it "returns true if avs_response in RISKY_AVS_CODES" do
844
+ # should use avs_response_code helper
845
+ ('A'..'Z').reject{ |x| subject.class::NON_RISKY_AVS_CODES.include?(x) }.to_a.each do |char|
846
+ payment.update_attribute(:avs_response, char)
847
+ expect(payment.is_avs_risky?).to eq true
848
+ end
849
+ end
850
+ end
851
+
852
+ describe "is_cvv_risky?" do
853
+ it "returns false if cvv_response_code == 'M'" do
854
+ payment.update_attribute(:cvv_response_code, "M")
855
+ expect(payment.is_cvv_risky?).to eq(false)
856
+ end
857
+
858
+ it "returns false if cvv_response_code == nil" do
859
+ payment.update_attribute(:cvv_response_code, nil)
860
+ expect(payment.is_cvv_risky?).to eq(false)
861
+ end
862
+
863
+ it "returns false if cvv_response_message == ''" do
864
+ payment.update_attribute(:cvv_response_message, '')
865
+ expect(payment.is_cvv_risky?).to eq(false)
866
+ end
867
+
868
+ it "returns true if cvv_response_code == [A-Z], omitting D" do
869
+ # should use cvv_response_code helper
870
+ (%w{N P S U} << "").each do |char|
871
+ payment.update_attribute(:cvv_response_code, char)
872
+ expect(payment.is_cvv_risky?).to eq(true)
873
+ end
874
+ end
875
+ end
876
+
877
+ describe "#editable?" do
878
+ subject { payment }
879
+
880
+ before do
881
+ subject.state = state
882
+ end
883
+
884
+ context "when the state is 'checkout'" do
885
+ let(:state) { 'checkout' }
886
+
887
+ its(:editable?) { should be(true) }
888
+ end
889
+
890
+ context "when the state is 'pending'" do
891
+ let(:state) { 'pending' }
892
+
893
+ its(:editable?) { should be(true) }
894
+ end
895
+
896
+ %w[processing completed failed void invalid].each do |state|
897
+ context "when the state is '#{state}'" do
898
+ let(:state) { state }
899
+
900
+ its(:editable?) { should be(false) }
901
+ end
902
+ end
903
+ end
904
+
905
+ # Regression test for #4072 (kinda)
906
+ # The need for this was discovered in the research for #4072
907
+ context "state changes" do
908
+ it "are logged to the database" do
909
+ expect(payment.state_changes).to be_empty
910
+ expect(payment.process!).to be true
911
+ expect(payment.state_changes.count).to eq(2)
912
+ changes = payment.state_changes.map { |change| { change.previous_state => change.next_state} }
913
+ expect(changes).to match_array([
914
+ {"checkout" => "processing"},
915
+ { "processing" => "pending"}
916
+ ])
917
+ end
918
+ end
919
+ end