solidus_core 1.1.0 → 1.1.1

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 (228) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Rakefile +16 -0
  4. data/script/rails +9 -0
  5. data/solidus_core.gemspec +48 -0
  6. data/spec/fixtures/thinking-cat.jpg +0 -0
  7. data/spec/helpers/base_helper_spec.rb +173 -0
  8. data/spec/helpers/order_helper_spec.rb +12 -0
  9. data/spec/helpers/products_helper_spec.rb +208 -0
  10. data/spec/helpers/taxons_helper_spec.rb +17 -0
  11. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  12. data/spec/lib/i18n_spec.rb +106 -0
  13. data/spec/lib/search/base_spec.rb +86 -0
  14. data/spec/lib/search/variant_spec.rb +112 -0
  15. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
  16. data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -0
  17. data/spec/lib/spree/core/controller_helpers/payment_parameters_spec.rb +80 -0
  18. data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
  19. data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
  20. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
  21. data/spec/lib/spree/core/current_store_spec.rb +36 -0
  22. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +24 -0
  23. data/spec/lib/spree/core/importer/order_spec.rb +431 -0
  24. data/spec/lib/spree/core/role_configuration_spec.rb +156 -0
  25. data/spec/lib/spree/core/unreturned_item_charger_spec.rb +130 -0
  26. data/spec/lib/spree/core/validators/email_spec.rb +48 -0
  27. data/spec/lib/spree/localized_number_spec.rb +38 -0
  28. data/spec/lib/spree/migrations_spec.rb +36 -0
  29. data/spec/lib/spree/money_spec.rb +127 -0
  30. data/spec/lib/tasks/exchanges_spec.rb +231 -0
  31. data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
  32. data/spec/lib/tasks/order_capturing_spec.rb +56 -0
  33. data/spec/mailers/carton_mailer_spec.rb +55 -0
  34. data/spec/mailers/order_mailer_spec.rb +135 -0
  35. data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
  36. data/spec/mailers/test_mailer_spec.rb +15 -0
  37. data/spec/models/spree/ability_spec.rb +276 -0
  38. data/spec/models/spree/address_spec.rb +376 -0
  39. data/spec/models/spree/adjustment_reason_spec.rb +13 -0
  40. data/spec/models/spree/adjustment_spec.rb +169 -0
  41. data/spec/models/spree/app_configuration_spec.rb +24 -0
  42. data/spec/models/spree/asset_spec.rb +24 -0
  43. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  44. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  45. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  46. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  47. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  48. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  49. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +60 -0
  50. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  51. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  52. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  53. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  54. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
  55. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
  56. data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
  57. data/spec/models/spree/calculator_spec.rb +36 -0
  58. data/spec/models/spree/carton_spec.rb +133 -0
  59. data/spec/models/spree/classification_spec.rb +93 -0
  60. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  61. data/spec/models/spree/concerns/ordered_property_value_list_spec.rb +25 -0
  62. data/spec/models/spree/concerns/user_address_book_spec.rb +332 -0
  63. data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
  64. data/spec/models/spree/credit_card_spec.rb +341 -0
  65. data/spec/models/spree/customer_return_spec.rb +276 -0
  66. data/spec/models/spree/exchange_spec.rb +79 -0
  67. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  68. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  69. data/spec/models/spree/gateway_spec.rb +104 -0
  70. data/spec/models/spree/inventory_unit_spec.rb +307 -0
  71. data/spec/models/spree/item_adjustments_spec.rb +275 -0
  72. data/spec/models/spree/line_item_spec.rb +199 -0
  73. data/spec/models/spree/option_type_spec.rb +14 -0
  74. data/spec/models/spree/option_value_spec.rb +45 -0
  75. data/spec/models/spree/order/address_spec.rb +50 -0
  76. data/spec/models/spree/order/adjustments_spec.rb +27 -0
  77. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  78. data/spec/models/spree/order/checkout_spec.rb +884 -0
  79. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  80. data/spec/models/spree/order/finalizing_spec.rb +110 -0
  81. data/spec/models/spree/order/payment_spec.rb +243 -0
  82. data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
  83. data/spec/models/spree/order/state_machine_spec.rb +209 -0
  84. data/spec/models/spree/order/tax_spec.rb +84 -0
  85. data/spec/models/spree/order/totals_spec.rb +24 -0
  86. data/spec/models/spree/order/updating_spec.rb +18 -0
  87. data/spec/models/spree/order/validations_spec.rb +15 -0
  88. data/spec/models/spree/order_cancellations_spec.rb +120 -0
  89. data/spec/models/spree/order_capturing_spec.rb +150 -0
  90. data/spec/models/spree/order_contents_spec.rb +307 -0
  91. data/spec/models/spree/order_inventory_spec.rb +228 -0
  92. data/spec/models/spree/order_mutex_spec.rb +85 -0
  93. data/spec/models/spree/order_promotion_spec.rb +31 -0
  94. data/spec/models/spree/order_shipping_spec.rb +241 -0
  95. data/spec/models/spree/order_spec.rb +1482 -0
  96. data/spec/models/spree/order_stock_location_spec.rb +18 -0
  97. data/spec/models/spree/order_updater_spec.rb +283 -0
  98. data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
  99. data/spec/models/spree/payment_method_spec.rb +147 -0
  100. data/spec/models/spree/payment_spec.rb +1087 -0
  101. data/spec/models/spree/permission_sets/base_spec.rb +12 -0
  102. data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
  103. data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
  104. data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
  105. data/spec/models/spree/permission_sets/order_display_spec.rb +55 -0
  106. data/spec/models/spree/permission_sets/order_management_spec.rb +42 -0
  107. data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
  108. data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
  109. data/spec/models/spree/permission_sets/promotion_display_spec.rb +40 -0
  110. data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
  111. data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
  112. data/spec/models/spree/permission_sets/restricted_stock_display_spec.rb +41 -0
  113. data/spec/models/spree/permission_sets/restricted_stock_management_spec.rb +41 -0
  114. data/spec/models/spree/permission_sets/restricted_stock_transfer_display_spec.rb +50 -0
  115. data/spec/models/spree/permission_sets/restricted_stock_transfer_management_spec.rb +160 -0
  116. data/spec/models/spree/permission_sets/stock_display_spec.rb +24 -0
  117. data/spec/models/spree/permission_sets/stock_management_spec.rb +22 -0
  118. data/spec/models/spree/permission_sets/stock_transfer_display_spec.rb +24 -0
  119. data/spec/models/spree/permission_sets/stock_transfer_management_spec.rb +25 -0
  120. data/spec/models/spree/permission_sets/user_display_spec.rb +38 -0
  121. data/spec/models/spree/permission_sets/user_management_spec.rb +48 -0
  122. data/spec/models/spree/preference_spec.rb +80 -0
  123. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  124. data/spec/models/spree/preferences/preferable_spec.rb +294 -0
  125. data/spec/models/spree/preferences/scoped_store_spec.rb +60 -0
  126. data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
  127. data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
  128. data/spec/models/spree/preferences/store_spec.rb +39 -0
  129. data/spec/models/spree/price_spec.rb +42 -0
  130. data/spec/models/spree/product/scopes_spec.rb +116 -0
  131. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  132. data/spec/models/spree/product_filter_spec.rb +26 -0
  133. data/spec/models/spree/product_property_spec.rb +18 -0
  134. data/spec/models/spree/product_spec.rb +504 -0
  135. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
  136. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
  137. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
  138. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
  139. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  140. data/spec/models/spree/promotion/rules/first_repeat_purchase_since_spec.rb +69 -0
  141. data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
  142. data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
  143. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  144. data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
  145. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  146. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  147. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  148. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  149. data/spec/models/spree/promotion_builder_spec.rb +118 -0
  150. data/spec/models/spree/promotion_category_spec.rb +17 -0
  151. data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
  152. data/spec/models/spree/promotion_code_spec.rb +187 -0
  153. data/spec/models/spree/promotion_handler/cart_spec.rb +130 -0
  154. data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
  155. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
  156. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  157. data/spec/models/spree/promotion_rule_spec.rb +28 -0
  158. data/spec/models/spree/promotion_spec.rb +776 -0
  159. data/spec/models/spree/refund_spec.rb +192 -0
  160. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  161. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  162. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  163. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  164. data/spec/models/spree/reimbursement_spec.rb +231 -0
  165. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  166. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  167. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  168. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
  169. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
  170. data/spec/models/spree/return_authorization_spec.rb +290 -0
  171. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  172. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  173. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
  174. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  175. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  176. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  177. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  178. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  179. data/spec/models/spree/return_item_spec.rb +776 -0
  180. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  181. data/spec/models/spree/shipment_spec.rb +753 -0
  182. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  183. data/spec/models/spree/shipping_manifest_spec.rb +94 -0
  184. data/spec/models/spree/shipping_method_spec.rb +88 -0
  185. data/spec/models/spree/shipping_rate_spec.rb +142 -0
  186. data/spec/models/spree/state_spec.rb +14 -0
  187. data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
  188. data/spec/models/spree/stock/coordinator_spec.rb +116 -0
  189. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  190. data/spec/models/spree/stock/estimator_spec.rb +146 -0
  191. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  192. data/spec/models/spree/stock/package_spec.rb +163 -0
  193. data/spec/models/spree/stock/packer_spec.rb +91 -0
  194. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  195. data/spec/models/spree/stock/quantifier_spec.rb +115 -0
  196. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  197. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  198. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
  199. data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
  200. data/spec/models/spree/stock_item_spec.rb +444 -0
  201. data/spec/models/spree/stock_location_spec.rb +279 -0
  202. data/spec/models/spree/stock_movement_spec.rb +56 -0
  203. data/spec/models/spree/stock_transfer_spec.rb +290 -0
  204. data/spec/models/spree/store_credit_category_spec.rb +17 -0
  205. data/spec/models/spree/store_credit_event_spec.rb +314 -0
  206. data/spec/models/spree/store_credit_spec.rb +876 -0
  207. data/spec/models/spree/store_spec.rb +55 -0
  208. data/spec/models/spree/tax_category_spec.rb +27 -0
  209. data/spec/models/spree/tax_rate_spec.rb +378 -0
  210. data/spec/models/spree/taxon_spec.rb +74 -0
  211. data/spec/models/spree/taxonomy_spec.rb +18 -0
  212. data/spec/models/spree/tracker_spec.rb +21 -0
  213. data/spec/models/spree/transfer_item_spec.rb +264 -0
  214. data/spec/models/spree/unit_cancel_spec.rb +149 -0
  215. data/spec/models/spree/user_spec.rb +246 -0
  216. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
  217. data/spec/models/spree/variant/scopes_spec.rb +55 -0
  218. data/spec/models/spree/variant_property_rule_condition_spec.rb +15 -0
  219. data/spec/models/spree/variant_property_rule_spec.rb +83 -0
  220. data/spec/models/spree/variant_property_rule_value_spec.rb +18 -0
  221. data/spec/models/spree/variant_spec.rb +601 -0
  222. data/spec/models/spree/zone_spec.rb +305 -0
  223. data/spec/spec_helper.rb +80 -0
  224. data/spec/support/big_decimal.rb +5 -0
  225. data/spec/support/concerns/default_price.rb +34 -0
  226. data/spec/support/dummy_ability.rb +4 -0
  227. data/spec/support/test_gateway.rb +2 -0
  228. metadata +242 -2
@@ -0,0 +1,147 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PaymentMethod, :type => :model do
4
+ describe ".available" do
5
+ let!(:payment_method_nil_display) { create(:payment_method, active: true, display_on: nil) }
6
+ let!(:payment_method_both_display) { create(:payment_method, active: true, display_on: 'both') }
7
+ let!(:payment_method_front_display){ create(:payment_method, active: true, display_on: 'front_end') }
8
+ let!(:payment_method_back_display) { create(:payment_method, active: true, display_on: 'back_end') }
9
+
10
+ it "should have 4 total methods" do
11
+ expect(Spree::PaymentMethod.all.size).to eq(4)
12
+ end
13
+
14
+ it "should return all methods available to front-end/back-end when no parameter is passed" do
15
+ expect(Spree::PaymentMethod.available.size).to eq(2)
16
+ end
17
+
18
+ it "should return all methods available to front-end/back-end when display_on = :both" do
19
+ expect(Spree::PaymentMethod.available(:both).size).to eq(2)
20
+ end
21
+
22
+ it "should return all methods available to front-end when display_on = :front_end" do
23
+ expect(Spree::PaymentMethod.available(:front_end).size).to eq(2)
24
+ end
25
+
26
+ it "should return all methods available to back-end when display_on = :back_end" do
27
+ expect(Spree::PaymentMethod.available(:back_end).size).to eq(2)
28
+ end
29
+
30
+ context 'with stores' do
31
+ let!(:store_1) do
32
+ create(:store,
33
+ payment_methods: [
34
+ payment_method_nil_display,
35
+ payment_method_both_display,
36
+ payment_method_front_display,
37
+ payment_method_back_display,
38
+ ]
39
+ )
40
+ end
41
+
42
+ let!(:store_2) do
43
+ create(:store, payment_methods: [store_2_payment_method])
44
+ end
45
+
46
+ let!(:store_3) { create(:store) }
47
+
48
+ let!(:store_2_payment_method) { create(:payment_method, active: true) }
49
+ let!(:no_store_payment_method) { create(:payment_method, active: true) }
50
+
51
+ context 'when the store is specified' do
52
+ context 'when the store has payment methods' do
53
+ it 'finds the payment methods for the store' do
54
+ expect(Spree::PaymentMethod.available(:both, store: store_1)).to match_array(
55
+ [payment_method_nil_display, payment_method_both_display]
56
+ )
57
+ end
58
+ end
59
+
60
+ context "when store does not have payment_methods" do
61
+ it "returns all matching payment methods regardless of store" do
62
+ expect(Spree::PaymentMethod.available(:both)).to match_array(
63
+ [
64
+ payment_method_nil_display,
65
+ payment_method_both_display,
66
+ store_2_payment_method,
67
+ no_store_payment_method,
68
+ ]
69
+ )
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'when the store is not specified' do
75
+ it "returns all matching payment methods regardless of store" do
76
+ expect(Spree::PaymentMethod.available(:both)).to match_array(
77
+ [
78
+ payment_method_nil_display,
79
+ payment_method_both_display,
80
+ store_2_payment_method,
81
+ no_store_payment_method,
82
+ ]
83
+ )
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#auto_capture?' do
90
+ class TestGateway < Spree::Gateway
91
+ def provider_class
92
+ Provider
93
+ end
94
+ end
95
+
96
+ let(:gateway) { TestGateway.new }
97
+
98
+ subject { gateway.auto_capture? }
99
+
100
+ context 'when auto_capture is nil' do
101
+ before(:each) do
102
+ expect(Spree::Config).to receive('[]').with(:auto_capture).and_return(auto_capture)
103
+ end
104
+
105
+ context 'and when Spree::Config[:auto_capture] is false' do
106
+ let(:auto_capture) { false }
107
+
108
+ it 'should be false' do
109
+ expect(gateway.auto_capture).to be_nil
110
+ expect(subject).to be false
111
+ end
112
+ end
113
+
114
+ context 'and when Spree::Config[:auto_capture] is true' do
115
+ let(:auto_capture) { true }
116
+
117
+ it 'should be true' do
118
+ expect(gateway.auto_capture).to be_nil
119
+ expect(subject).to be true
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'when auto_capture is not nil' do
125
+ before(:each) do
126
+ gateway.auto_capture = auto_capture
127
+ end
128
+
129
+ context 'and is true' do
130
+ let(:auto_capture) { true }
131
+
132
+ it 'should be true' do
133
+ expect(subject).to be true
134
+ end
135
+ end
136
+
137
+ context 'and is false' do
138
+ let(:auto_capture) { false }
139
+
140
+ it 'should be true' do
141
+ expect(subject).to be false
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ end
@@ -0,0 +1,1087 @@
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, :name => 'Bogus gateway')
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
+ context '.risky' do
47
+
48
+ let!(:payment_1) { create(:payment, avs_response: 'Y', cvv_response_code: 'M', cvv_response_message: 'Match') }
49
+ let!(:payment_2) { create(:payment, avs_response: 'Y', cvv_response_code: 'M', cvv_response_message: '') }
50
+ let!(:payment_3) { create(:payment, avs_response: 'A', cvv_response_code: 'M', cvv_response_message: 'Match') }
51
+ let!(:payment_4) { create(:payment, avs_response: 'Y', cvv_response_code: 'N', cvv_response_message: 'No Match') }
52
+
53
+ it 'should not return successful responses' do
54
+ expect(subject.class.risky.to_a).to match_array([payment_3, payment_4])
55
+ end
56
+
57
+ end
58
+
59
+ context "#captured_amount" do
60
+ context "calculates based on capture events" do
61
+ it "with 0 capture events" do
62
+ expect(payment.captured_amount).to eq(0)
63
+ end
64
+
65
+ it "with some capture events" do
66
+ payment.save
67
+ payment.capture_events.create!(amount: 2.0)
68
+ payment.capture_events.create!(amount: 3.0)
69
+ expect(payment.captured_amount).to eq(5)
70
+ end
71
+ end
72
+ end
73
+
74
+ context '#uncaptured_amount' do
75
+ context "calculates based on capture events" do
76
+ it "with 0 capture events" do
77
+ expect(payment.uncaptured_amount).to eq(5.0)
78
+ end
79
+
80
+ it "with some capture events" do
81
+ payment.save
82
+ payment.capture_events.create!(amount: 2.0)
83
+ payment.capture_events.create!(amount: 3.0)
84
+ expect(payment.uncaptured_amount).to eq(0)
85
+ end
86
+ end
87
+ end
88
+
89
+ context 'validations' do
90
+ it "returns useful error messages when source is invalid" do
91
+ payment.source = Spree::CreditCard.new
92
+ expect(payment).not_to be_valid
93
+ cc_errors = payment.errors['Credit Card']
94
+ expect(cc_errors).to include("Number can't be blank")
95
+ expect(cc_errors).to include("Month is not a number")
96
+ expect(cc_errors).to include("Year is not a number")
97
+ expect(cc_errors).to include("Verification Value can't be blank")
98
+ end
99
+ end
100
+
101
+ # Regression test for https://github.com/spree/spree/pull/2224
102
+ context 'failure' do
103
+ it 'should transition to failed from pending state' do
104
+ payment.state = 'pending'
105
+ payment.failure
106
+ expect(payment.state).to eql('failed')
107
+ end
108
+
109
+ it 'should transition to failed from processing state' do
110
+ payment.state = 'processing'
111
+ payment.failure
112
+ expect(payment.state).to eql('failed')
113
+ end
114
+
115
+ end
116
+
117
+ context 'invalidate' do
118
+ it 'should transition from checkout to invalid' do
119
+ payment.state = 'checkout'
120
+ payment.invalidate
121
+ expect(payment.state).to eq('invalid')
122
+ end
123
+
124
+ context "the payment's source is invalid" do
125
+
126
+ before(:each) do
127
+ card.year = 2014
128
+ payment.source = card
129
+ end
130
+
131
+ it "transitions to invalid" do
132
+ payment.state = 'checkout'
133
+ payment.invalidate
134
+ expect(payment.state).to eq ('invalid')
135
+ end
136
+ end
137
+ end
138
+
139
+ context "processing" do
140
+ describe "#process!" do
141
+ context 'with autocapture' do
142
+ before do
143
+ payment.payment_method.update_attributes!(auto_capture: true)
144
+ end
145
+
146
+ it "should purchase" do
147
+ payment.process!
148
+ expect(payment).to be_completed
149
+ end
150
+ end
151
+
152
+ context 'without autocapture' do
153
+ before do
154
+ payment.payment_method.update_attributes!(auto_capture: false)
155
+ end
156
+
157
+ context 'when in the checkout state' do
158
+ before { payment.update_attributes!(state: 'checkout') }
159
+
160
+ it "authorizes" do
161
+ payment.process!
162
+ expect(payment).to be_pending
163
+ end
164
+ end
165
+
166
+ context 'when in the processing state' do
167
+ before { payment.update_attributes!(state: 'processing') }
168
+
169
+ it "does not authorize" do
170
+ payment.process!
171
+ expect(payment).to be_processing
172
+ end
173
+ end
174
+
175
+ context 'when in the pending state' do
176
+ before { payment.update_attributes!(state: 'pending') }
177
+
178
+ it "does not re-authorize" do
179
+ expect(payment).to_not receive(:authorize!)
180
+ payment.process!
181
+ expect(payment).to be_pending
182
+ end
183
+ end
184
+
185
+ context 'when in a failed state' do
186
+ before { payment.update_attributes!(state: 'failed') }
187
+
188
+ it "raises an exception" do
189
+ expect {
190
+ payment.process!
191
+ }.to raise_error(StateMachines::InvalidTransition, /Cannot transition/)
192
+ end
193
+ end
194
+
195
+ context 'when in the completed state' do
196
+ before { payment.update_attributes!(state: 'completed') }
197
+
198
+ it "authorizes" do
199
+ payment.process!
200
+ # TODO: Is this really what we want to happen in this case?
201
+ expect(payment).to be_pending
202
+ end
203
+ end
204
+ end
205
+
206
+ it "should make the state 'processing'" do
207
+ expect(payment).to receive(:started_processing!)
208
+ payment.process!
209
+ end
210
+
211
+ it "should invalidate if payment method doesnt support source" do
212
+ expect(payment.payment_method).to receive(:supports?).with(payment.source).and_return(false)
213
+ expect { payment.process!}.to raise_error(Spree::Core::GatewayError)
214
+ expect(payment.state).to eq('invalid')
215
+ end
216
+
217
+ # Regression test for #4598
218
+ it "should allow payments with a gateway_customer_profile_id" do
219
+ allow(payment.source).to receive_messages :gateway_customer_profile_id => "customer_1"
220
+ expect(payment.payment_method).to receive(:supports?).with(payment.source).and_return(false)
221
+ expect(payment).to receive(:started_processing!)
222
+ payment.process!
223
+ end
224
+
225
+ # Another regression test for #4598
226
+ it "should allow payments with a gateway_payment_profile_id" do
227
+ allow(payment.source).to receive_messages :gateway_payment_profile_id => "customer_1"
228
+ expect(payment.payment_method).to receive(:supports?).with(payment.source).and_return(false)
229
+ expect(payment).to receive(:started_processing!)
230
+ payment.process!
231
+ end
232
+ end
233
+
234
+ describe "#authorize!" do
235
+ it "should call authorize on the gateway with the payment amount" do
236
+ expect(payment.payment_method).to receive(:authorize).with(amount_in_cents,
237
+ card,
238
+ anything).and_return(success_response)
239
+ payment.authorize!
240
+ end
241
+
242
+ it "should call authorize on the gateway with the currency code" do
243
+ allow(payment).to receive_messages :currency => 'GBP'
244
+ expect(payment.payment_method).to receive(:authorize).with(amount_in_cents,
245
+ card,
246
+ hash_including({:currency => "GBP"})).and_return(success_response)
247
+ payment.authorize!
248
+ end
249
+
250
+ it "should log the response" do
251
+ payment.save!
252
+ expect(payment.log_entries).to receive(:create!).with(details: anything)
253
+ payment.authorize!
254
+ end
255
+
256
+ describe 'billing_address option' do
257
+ context 'when the source is a credit card with an address' do
258
+ let(:card) { create(:credit_card, address: address) }
259
+ let(:address) { create(:address) }
260
+
261
+ it 'sends the credit card address' do
262
+ expect(payment.payment_method).to(
263
+ receive(:authorize).
264
+ with(
265
+ amount_in_cents,
266
+ card,
267
+ hash_including(billing_address: card.address.active_merchant_hash)
268
+ ).
269
+ and_return(success_response)
270
+ )
271
+ payment.authorize!
272
+ end
273
+ end
274
+
275
+ context 'when the source is a credit card without an address' do
276
+ let(:card) { create(:credit_card, address: nil) }
277
+ before { order.update_attributes!(bill_address: address) }
278
+ let(:address) { create(:address) }
279
+
280
+ it 'send the order bill address' do
281
+ expect(payment.payment_method).to(
282
+ receive(:authorize).
283
+ with(
284
+ amount_in_cents,
285
+ card,
286
+ hash_including(billing_address: order.bill_address.active_merchant_hash)
287
+ ).
288
+ and_return(success_response)
289
+ )
290
+ payment.authorize!
291
+ end
292
+ end
293
+
294
+ context 'when the source is not a credit card' do
295
+ before do
296
+ payment.source = store_credit_payment
297
+ payment.payment_method = store_credit_payment_method
298
+ end
299
+
300
+ let(:store_credit_payment) { create(:store_credit_payment) }
301
+ let(:store_credit_payment_method) { create(:store_credit_payment_method) }
302
+ before { order.update_attributes!(bill_address: address) }
303
+ let(:address) { create(:address) }
304
+
305
+ it 'send the order bill address' do
306
+ expect(payment.payment_method).to(
307
+ receive(:authorize).
308
+ with(
309
+ amount_in_cents,
310
+ store_credit_payment,
311
+ hash_including(billing_address: order.bill_address.active_merchant_hash)
312
+ ).
313
+ and_return(success_response)
314
+ )
315
+ payment.authorize!
316
+ end
317
+ end
318
+ end
319
+
320
+ context "if successful" do
321
+ before do
322
+ expect(payment.payment_method).to receive(:authorize).with(amount_in_cents,
323
+ card,
324
+ anything).and_return(success_response)
325
+ end
326
+
327
+ it "should store the response_code, avs_response and cvv_response fields" do
328
+ payment.authorize!
329
+ expect(payment.response_code).to eq('123')
330
+ expect(payment.avs_response).to eq(avs_code)
331
+ expect(payment.cvv_response_code).to eq(cvv_code)
332
+ expect(payment.cvv_response_message).to eq(ActiveMerchant::Billing::CVVResult::MESSAGES[cvv_code])
333
+ end
334
+
335
+ it "should make payment pending" do
336
+ expect(payment).to receive(:pend!)
337
+ payment.authorize!
338
+ end
339
+ end
340
+
341
+ context "if unsuccessful" do
342
+ it "should mark payment as failed" do
343
+ allow(gateway).to receive(:authorize).and_return(failed_response)
344
+ expect(payment).to receive(:failure)
345
+ expect(payment).not_to receive(:pend)
346
+ expect {
347
+ payment.authorize!
348
+ }.to raise_error(Spree::Core::GatewayError)
349
+ end
350
+ end
351
+ end
352
+
353
+ describe "#purchase!" do
354
+ it "should call purchase on the gateway with the payment amount" do
355
+ expect(gateway).to receive(:purchase).with(amount_in_cents, card, anything).and_return(success_response)
356
+ payment.purchase!
357
+ end
358
+
359
+ it "should log the response" do
360
+ payment.save!
361
+ expect(payment.log_entries).to receive(:create!).with(details: anything)
362
+ payment.purchase!
363
+ end
364
+
365
+ context "if successful" do
366
+ before do
367
+ expect(payment.payment_method).to receive(:purchase).with(amount_in_cents,
368
+ card,
369
+ anything).and_return(success_response)
370
+ end
371
+
372
+ it "should store the response_code and avs_response" do
373
+ payment.purchase!
374
+ expect(payment.response_code).to eq('123')
375
+ expect(payment.avs_response).to eq(avs_code)
376
+ end
377
+
378
+ it "should make payment complete" do
379
+ expect(payment).to receive(:complete!)
380
+ payment.purchase!
381
+ end
382
+
383
+ it "should log a capture event" do
384
+ payment.purchase!
385
+ expect(payment.capture_events.count).to eq(1)
386
+ expect(payment.capture_events.first.amount).to eq(payment.amount)
387
+ end
388
+
389
+ it "should set the uncaptured amount to 0" do
390
+ payment.purchase!
391
+ expect(payment.uncaptured_amount).to eq(0)
392
+ end
393
+ end
394
+
395
+ context "if unsuccessful" do
396
+ before do
397
+ allow(gateway).to receive(:purchase).and_return(failed_response)
398
+ expect(payment).to receive(:failure)
399
+ expect(payment).not_to receive(:pend)
400
+ end
401
+
402
+ it "should make payment failed" do
403
+ expect { payment.purchase! }.to raise_error(Spree::Core::GatewayError)
404
+ end
405
+
406
+ it "should not log a capture event" do
407
+ expect { payment.purchase! }.to raise_error(Spree::Core::GatewayError)
408
+ expect(payment.capture_events.count).to eq(0)
409
+ end
410
+ end
411
+ end
412
+
413
+ describe "#capture!" do
414
+ context "when payment is pending" do
415
+ before do
416
+ payment.amount = 100
417
+ payment.state = 'pending'
418
+ payment.response_code = '12345'
419
+ end
420
+
421
+ context "if successful" do
422
+ context 'for entire amount' do
423
+ before do
424
+ expect(payment.payment_method).to receive(:capture).with(payment.display_amount.money.cents, payment.response_code, anything).and_return(success_response)
425
+ end
426
+
427
+ it "should make payment complete" do
428
+ expect(payment).to receive(:complete!)
429
+ payment.capture!
430
+ end
431
+
432
+ it "logs capture events" do
433
+ payment.capture!
434
+ expect(payment.capture_events.count).to eq(1)
435
+ expect(payment.capture_events.first.amount).to eq(payment.amount)
436
+ end
437
+ end
438
+
439
+ it "logs capture events" do
440
+ payment.capture!
441
+ expect(payment.capture_events.count).to eq(1)
442
+ expect(payment.capture_events.first.amount).to eq(payment.amount)
443
+ end
444
+ end
445
+
446
+ context "capturing a partial amount" do
447
+ it "logs capture events" do
448
+ payment.capture!(5000)
449
+ expect(payment.capture_events.count).to eq(1)
450
+ expect(payment.capture_events.first.amount).to eq(50)
451
+ end
452
+
453
+ it "stores the captured amount on the payment" do
454
+ payment.capture!(6000)
455
+ expect(payment.captured_amount).to eq(60)
456
+ end
457
+
458
+ it "updates the amount of the payment" do
459
+ payment.capture!(6000)
460
+ expect(payment.reload.amount).to eq(60)
461
+ end
462
+ end
463
+
464
+ context "if unsuccessful" do
465
+ it "should not make payment complete" do
466
+ allow(gateway).to receive_messages :capture => failed_response
467
+ expect(payment).to receive(:failure)
468
+ expect(payment).not_to receive(:complete)
469
+ expect { payment.capture! }.to raise_error(Spree::Core::GatewayError)
470
+ end
471
+ end
472
+ end
473
+
474
+ # Regression test for #2119
475
+ context "when payment is completed" do
476
+ before do
477
+ payment.state = 'completed'
478
+ end
479
+
480
+ it "should do nothing" do
481
+ expect(payment).not_to receive(:complete)
482
+ expect(payment.payment_method).not_to receive(:capture)
483
+ expect(payment.log_entries).not_to receive(:create!)
484
+ payment.capture!
485
+ end
486
+ end
487
+ end
488
+
489
+ describe "#cancel!" do
490
+ before do
491
+ payment.response_code = 'abc'
492
+ payment.state = 'pending'
493
+ end
494
+
495
+ context "if successful" do
496
+ it "should update the response_code with the authorization from the gateway" do
497
+ # Change it to something different
498
+ allow(gateway).to receive_messages :cancel => success_response
499
+ payment.cancel!
500
+ expect(payment.state).to eq('void')
501
+ expect(payment.response_code).to eq('123')
502
+ end
503
+ end
504
+
505
+ context "if unsuccessful" do
506
+ it "should not void the payment" do
507
+ allow(gateway).to receive_messages :cancel => failed_response
508
+ expect { payment.cancel! }.to raise_error(Spree::Core::GatewayError)
509
+ expect(payment.state).to eq('pending')
510
+ expect(payment.response_code).to eq('abc')
511
+ end
512
+ end
513
+
514
+ end
515
+
516
+
517
+ describe "#void_transaction!" do
518
+ before do
519
+ payment.response_code = '123'
520
+ payment.state = 'pending'
521
+ end
522
+
523
+ context "when profiles are supported" do
524
+ it "should call payment_gateway.void with the payment's response_code" do
525
+ allow(gateway).to receive_messages :payment_profiles_supported? => true
526
+ expect(gateway).to receive(:void).with('123', card, anything).and_return(success_response)
527
+ payment.void_transaction!
528
+ end
529
+ end
530
+
531
+ context "when profiles are not supported" do
532
+ it "should call payment_gateway.void with the payment's response_code" do
533
+ allow(gateway).to receive_messages :payment_profiles_supported? => false
534
+ expect(gateway).to receive(:void).with('123', anything).and_return(success_response)
535
+ payment.void_transaction!
536
+ end
537
+ end
538
+
539
+ it "should log the response" do
540
+ expect(payment.log_entries).to receive(:create!).with(:details => anything)
541
+ payment.void_transaction!
542
+ end
543
+
544
+ context "if successful" do
545
+ it "should update the response_code with the authorization from the gateway" do
546
+ # Change it to something different
547
+ payment.response_code = 'abc'
548
+ payment.void_transaction!
549
+ expect(payment.response_code).to eq('12345')
550
+ end
551
+ end
552
+
553
+ context "if unsuccessful" do
554
+ it "should not void the payment" do
555
+ allow(gateway).to receive_messages :void => failed_response
556
+ expect(payment).not_to receive(:void)
557
+ expect { payment.void_transaction! }.to raise_error(Spree::Core::GatewayError)
558
+ end
559
+ end
560
+
561
+ # Regression test for #2119
562
+ context "if payment is already voided" do
563
+ before do
564
+ payment.state = 'void'
565
+ end
566
+
567
+ it "should not void the payment" do
568
+ expect(payment.payment_method).not_to receive(:void)
569
+ payment.void_transaction!
570
+ end
571
+ end
572
+ end
573
+
574
+ end
575
+
576
+ context "when already processing" do
577
+ it "should return nil without trying to process the source" do
578
+ payment.state = 'processing'
579
+
580
+ expect(payment.process!).to be_nil
581
+ end
582
+ end
583
+
584
+ context "with source required" do
585
+ context "raises an error if no source is specified" do
586
+ before do
587
+ payment.source = nil
588
+ end
589
+
590
+ specify do
591
+ expect { payment.process! }.to raise_error(Spree::Core::GatewayError, Spree.t(:payment_processing_failed))
592
+ end
593
+ end
594
+ end
595
+
596
+ context "with source optional" do
597
+ context "raises no error if source is not specified" do
598
+ before do
599
+ payment.source = nil
600
+ allow(payment.payment_method).to receive_messages(:source_required? => false)
601
+ end
602
+
603
+ specify do
604
+ expect { payment.process! }.not_to raise_error
605
+ end
606
+ end
607
+ end
608
+
609
+ describe "#credit_allowed" do
610
+ # Regression test for #4403 & #4407
611
+ it "is the difference between offsets total and payment amount" do
612
+ payment.amount = 100
613
+ allow(payment).to receive(:offsets_total).and_return(0)
614
+ expect(payment.credit_allowed).to eq(100)
615
+ allow(payment).to receive(:offsets_total).and_return(-80)
616
+ expect(payment.credit_allowed).to eq(20)
617
+ end
618
+ end
619
+
620
+ describe "#can_credit?" do
621
+ it "is true if credit_allowed > 0" do
622
+ allow(payment).to receive(:credit_allowed).and_return(100)
623
+ expect(payment.can_credit?).to be true
624
+ end
625
+
626
+ it "is false if credit_allowed is 0" do
627
+ allow(payment).to receive(:credit_allowed).and_return(0)
628
+ expect(payment.can_credit?).to be false
629
+ end
630
+ end
631
+
632
+ describe "#save" do
633
+ context "captured payments" do
634
+ it "update order payment total" do
635
+ payment = create(:payment, order: order, state: 'completed')
636
+ expect(order.payment_total).to eq payment.amount
637
+ end
638
+ end
639
+
640
+ context "not completed payments" do
641
+ it "doesn't update order payment total" do
642
+ expect {
643
+ Spree::Payment.create(:amount => 100, :order => order)
644
+ }.not_to change { order.payment_total }
645
+ end
646
+ end
647
+
648
+ context 'when the payment was completed but now void' do
649
+ let(:payment) do
650
+ Spree::Payment.create(
651
+ amount: 100,
652
+ order: order,
653
+ state: 'completed'
654
+ )
655
+ end
656
+
657
+ it 'updates order payment total' do
658
+ payment.void
659
+ expect(order.payment_total).to eq 0
660
+ end
661
+ end
662
+
663
+ context "completed orders" do
664
+ before { allow(order).to receive_messages completed?: true }
665
+
666
+ it "updates payment_state and shipments" do
667
+ expect(order.updater).to receive(:update_payment_state)
668
+ expect(order.updater).to receive(:update_shipment_state)
669
+ Spree::Payment.create(:amount => 100, :order => order)
670
+ end
671
+ end
672
+
673
+ context "when profiles are supported" do
674
+ before do
675
+ allow(gateway).to receive_messages :payment_profiles_supported? => true
676
+ allow(payment.source).to receive_messages :has_payment_profile? => false
677
+ end
678
+
679
+ context "when there is an error connecting to the gateway" do
680
+ it "should call gateway_error " do
681
+ expect(gateway).to receive(:create_profile).and_raise(ActiveMerchant::ConnectionError.new("foo", nil))
682
+ expect do
683
+ Spree::Payment.create(
684
+ :amount => 100,
685
+ :order => order,
686
+ :source => card,
687
+ :payment_method => gateway
688
+ )
689
+ end.to raise_error(Spree::Core::GatewayError)
690
+ end
691
+ end
692
+
693
+ context "with multiple payment attempts" do
694
+ let(:attributes) { attributes_for(:credit_card) }
695
+ it "should not try to create profiles on old failed payment attempts" do
696
+ allow_any_instance_of(Spree::Payment).to receive(:payment_method) { gateway }
697
+
698
+ order.payments.create!(
699
+ source_attributes: attributes,
700
+ payment_method: gateway,
701
+ amount: 100
702
+ )
703
+ expect(gateway).to receive(:create_profile).exactly :once
704
+ expect(order.payments.count).to eq(1)
705
+ order.payments.create!(
706
+ source_attributes: attributes,
707
+ payment_method: gateway,
708
+ amount: 100
709
+ )
710
+ end
711
+
712
+ end
713
+
714
+ context "when successfully connecting to the gateway" do
715
+ it "should create a payment profile" do
716
+ expect(payment.payment_method).to receive :create_profile
717
+ payment = Spree::Payment.create(
718
+ :amount => 100,
719
+ :order => order,
720
+ :source => card,
721
+ :payment_method => gateway
722
+ )
723
+ end
724
+ end
725
+ end
726
+
727
+ context "when profiles are not supported" do
728
+ before { allow(gateway).to receive_messages :payment_profiles_supported? => false }
729
+
730
+ it "should not create a payment profile" do
731
+ expect(gateway).not_to receive :create_profile
732
+ payment = Spree::Payment.create(
733
+ :amount => 100,
734
+ :order => order,
735
+ :source => card,
736
+ :payment_method => gateway
737
+ )
738
+ end
739
+ end
740
+ end
741
+
742
+ describe '#invalidate_old_payments' do
743
+ it 'should not invalidate other payments if not valid' do
744
+ payment.save
745
+ invalid_payment = Spree::Payment.new(:amount => 100, :order => order, :state => 'invalid', :payment_method => gateway)
746
+ invalid_payment.save
747
+ expect(payment.reload.state).to eq('checkout')
748
+ end
749
+ end
750
+
751
+ describe "#build_source" do
752
+ let(:params) do
753
+ {
754
+ :amount => 100,
755
+ :payment_method => gateway,
756
+ :source_attributes => {
757
+ :expiry =>"01 / 99",
758
+ :number => '1234567890123',
759
+ :verification_value => '123',
760
+ :name => 'Spree Commerce'
761
+ }
762
+ }
763
+ end
764
+
765
+ it "should build the payment's source" do
766
+ payment = Spree::Payment.new(params)
767
+ expect(payment).to be_valid
768
+ expect(payment.source).not_to be_nil
769
+ end
770
+
771
+ it "assigns user and gateway to payment source" do
772
+ order = create(:order)
773
+ source = order.payments.new(params).source
774
+
775
+ expect(source.user_id).to eq order.user_id
776
+ expect(source.payment_method_id).to eq gateway.id
777
+ end
778
+
779
+ it "errors when payment source not valid" do
780
+ params = { :amount => 100, :payment_method => gateway,
781
+ :source_attributes => {:expiry => "1 / 12" }}
782
+
783
+ payment = Spree::Payment.new(params)
784
+ expect(payment).not_to be_valid
785
+ expect(payment.source).not_to be_nil
786
+ expect(payment.source.error_on(:number).size).to eq(1)
787
+ expect(payment.source.error_on(:verification_value).size).to eq(1)
788
+ end
789
+
790
+ it "does not build a new source when duplicating the model with source_attributes set" do
791
+ payment = create(:payment)
792
+ payment.source_attributes = params[:source_attributes]
793
+ expect { payment.dup }.to_not change { payment.source }
794
+ end
795
+ end
796
+
797
+ describe "#currency" do
798
+ before { allow(order).to receive(:currency) { "ABC" } }
799
+ it "returns the order currency" do
800
+ expect(payment.currency).to eq("ABC")
801
+ end
802
+ end
803
+
804
+ describe "#display_amount" do
805
+ it "returns a Spree::Money for this amount" do
806
+ expect(payment.display_amount).to eq(Spree::Money.new(payment.amount))
807
+ end
808
+ end
809
+
810
+ # Regression test for #2216
811
+ describe "#gateway_options" do
812
+ before { allow(order).to receive_messages(:last_ip_address => "192.168.1.1") }
813
+
814
+ it "contains an IP" do
815
+ expect(payment.gateway_options[:ip]).to eq(order.last_ip_address)
816
+ end
817
+
818
+ it "contains the email address from a persisted order" do
819
+ # Sets the payment's order to a different Ruby object entirely
820
+ payment.order = Spree::Order.find(payment.order_id)
821
+ email = 'foo@example.com'
822
+ order.update_attributes(:email => email)
823
+ expect(payment.gateway_options[:email]).to eq(email)
824
+ end
825
+ end
826
+
827
+ describe "#set_unique_identifier" do
828
+ # Regression test for #1998
829
+ it "sets a unique identifier on create" do
830
+ payment.run_callbacks(:create)
831
+ expect(payment.number).not_to be_blank
832
+ expect(payment.number.size).to eq(8)
833
+ expect(payment.number).to be_a(String)
834
+ end
835
+
836
+ # Regression test for #3733
837
+ it "does not regenerate the identifier on re-save" do
838
+ payment.save!
839
+ old_number = payment.number
840
+ payment.save!
841
+ expect(payment.number).to eq(old_number)
842
+ end
843
+
844
+ context "other payment exists" do
845
+ let(:other_payment) {
846
+ payment = Spree::Payment.new
847
+ payment.source = card
848
+ payment.order = order
849
+ payment.payment_method = gateway
850
+ payment
851
+ }
852
+
853
+ before { other_payment.save! }
854
+
855
+ it "doesn't set duplicate identifier" do
856
+ expect(payment).to receive(:generate_identifier).and_return(other_payment.number)
857
+ expect(payment).to receive(:generate_identifier).and_call_original
858
+
859
+ payment.run_callbacks(:create)
860
+
861
+ expect(payment.number).not_to be_blank
862
+ expect(payment.number).not_to eq(other_payment.number)
863
+ end
864
+ end
865
+ end
866
+
867
+ describe "#amount=" do
868
+ before do
869
+ subject.amount = amount
870
+ end
871
+
872
+ context "when the amount is a string" do
873
+ context "amount is a decimal" do
874
+ let(:amount) { '2.99' }
875
+
876
+ it '#amount' do
877
+ expect(subject.amount).to eql(BigDecimal('2.99'))
878
+ end
879
+ end
880
+
881
+ context "amount is an integer" do
882
+ let(:amount) { '2' }
883
+
884
+ it '#amount' do
885
+ expect(subject.amount).to eql(BigDecimal('2.0'))
886
+ end
887
+ end
888
+
889
+ context "amount contains a dollar sign" do
890
+ let(:amount) { '$2.99' }
891
+
892
+ it '#amount' do
893
+ expect(subject.amount).to eql(BigDecimal('2.99'))
894
+ end
895
+ end
896
+
897
+ context "amount contains a comma" do
898
+ let(:amount) { '$2,999.99' }
899
+
900
+ it '#amount' do
901
+ expect(subject.amount).to eql(BigDecimal('2999.99'))
902
+ end
903
+ end
904
+
905
+ context "amount contains a negative sign" do
906
+ let(:amount) { '-2.99' }
907
+
908
+ it '#amount' do
909
+ expect(subject.amount).to eql(BigDecimal('-2.99'))
910
+ end
911
+ end
912
+
913
+ context "amount is invalid" do
914
+ let(:amount) { 'invalid' }
915
+
916
+ # this is a strange default for ActiveRecord
917
+
918
+ it '#amount' do
919
+ expect(subject.amount).to eql(BigDecimal('0'))
920
+ end
921
+ end
922
+
923
+ context "amount is an empty string" do
924
+ let(:amount) { '' }
925
+
926
+ it '#amount' do
927
+ expect(subject.amount).to be_nil
928
+ end
929
+ end
930
+ end
931
+
932
+ context "when the amount is a number" do
933
+ let(:amount) { 1.55 }
934
+
935
+ it '#amount' do
936
+ expect(subject.amount).to eql(BigDecimal('1.55'))
937
+ end
938
+ end
939
+
940
+ context "when the locale uses a coma as a decimal separator" do
941
+ before(:each) do
942
+ I18n.backend.store_translations(:fr, { :number => { :currency => { :format => { :delimiter => ' ', :separator => ',' } } } })
943
+ I18n.locale = :fr
944
+ subject.amount = amount
945
+ end
946
+
947
+ after do
948
+ I18n.locale = I18n.default_locale
949
+ end
950
+
951
+ context "amount is a decimal" do
952
+ let(:amount) { '2,99' }
953
+
954
+ it '#amount' do
955
+ expect(subject.amount).to eql(BigDecimal('2.99'))
956
+ end
957
+ end
958
+
959
+ context "amount contains a $ sign" do
960
+ let(:amount) { '2,99 $' }
961
+
962
+ it '#amount' do
963
+ expect(subject.amount).to eql(BigDecimal('2.99'))
964
+ end
965
+ end
966
+
967
+ context "amount is a number" do
968
+ let(:amount) { 2.99 }
969
+
970
+ it '#amount' do
971
+ expect(subject.amount).to eql(BigDecimal('2.99'))
972
+ end
973
+ end
974
+
975
+ context "amount contains a negative sign" do
976
+ let(:amount) { '-2,99 $' }
977
+
978
+ it '#amount' do
979
+ expect(subject.amount).to eql(BigDecimal('-2.99'))
980
+ end
981
+ end
982
+
983
+ context "amount uses a dot as a decimal separator" do
984
+ let(:amount) { '2.99' }
985
+
986
+ it '#amount' do
987
+ expect(subject.amount).to eql(BigDecimal('2.99'))
988
+ end
989
+ end
990
+ end
991
+ end
992
+
993
+ describe "is_avs_risky?" do
994
+ it "returns false if avs_response included in NON_RISKY_AVS_CODES" do
995
+ ('A'..'Z').reject{ |x| subject.class::RISKY_AVS_CODES.include?(x) }.to_a.each do |char|
996
+ payment.update_attribute(:avs_response, char)
997
+ expect(payment.is_avs_risky?).to eq false
998
+ end
999
+ end
1000
+
1001
+ it "returns false if avs_response.blank?" do
1002
+ payment.update_attribute(:avs_response, nil)
1003
+ expect(payment.is_avs_risky?).to eq false
1004
+ payment.update_attribute(:avs_response, '')
1005
+ expect(payment.is_avs_risky?).to eq false
1006
+ end
1007
+
1008
+ it "returns true if avs_response in RISKY_AVS_CODES" do
1009
+ # should use avs_response_code helper
1010
+ ('A'..'Z').reject{ |x| subject.class::NON_RISKY_AVS_CODES.include?(x) }.to_a.each do |char|
1011
+ payment.update_attribute(:avs_response, char)
1012
+ expect(payment.is_avs_risky?).to eq true
1013
+ end
1014
+ end
1015
+ end
1016
+
1017
+ describe "is_cvv_risky?" do
1018
+ it "returns false if cvv_response_code == 'M'" do
1019
+ payment.update_attribute(:cvv_response_code, "M")
1020
+ expect(payment.is_cvv_risky?).to eq(false)
1021
+ end
1022
+
1023
+ it "returns false if cvv_response_code == nil" do
1024
+ payment.update_attribute(:cvv_response_code, nil)
1025
+ expect(payment.is_cvv_risky?).to eq(false)
1026
+ end
1027
+
1028
+ it "returns false if cvv_response_message == ''" do
1029
+ payment.update_attribute(:cvv_response_message, '')
1030
+ expect(payment.is_cvv_risky?).to eq(false)
1031
+ end
1032
+
1033
+ it "returns true if cvv_response_code == [A-Z], omitting D" do
1034
+ # should use cvv_response_code helper
1035
+ (%w{N P S U} << "").each do |char|
1036
+ payment.update_attribute(:cvv_response_code, char)
1037
+ expect(payment.is_cvv_risky?).to eq(true)
1038
+ end
1039
+ end
1040
+ end
1041
+
1042
+ # Regression test for #4072 (kinda)
1043
+ # The need for this was discovered in the research for #4072
1044
+ context "state changes" do
1045
+ it "are logged to the database" do
1046
+ expect(payment.state_changes).to be_empty
1047
+ expect(payment.process!).to be true
1048
+ expect(payment.state_changes.count).to eq(2)
1049
+ changes = payment.state_changes.map { |change| { change.previous_state => change.next_state} }
1050
+ expect(changes).to match_array([
1051
+ {"checkout" => "processing"},
1052
+ { "processing" => "pending"}
1053
+ ])
1054
+ end
1055
+ end
1056
+
1057
+ describe "#actions" do
1058
+ let(:source) { Spree::CreditCard.new }
1059
+ before { allow(subject).to receive(:payment_source) { source } }
1060
+
1061
+ it "includes the actions that the source can take" do
1062
+ allow(source).to receive(:can_capture?) { true }
1063
+ expect(subject.actions).to include "capture"
1064
+ end
1065
+
1066
+ it "excludes actions that the source cannot take" do
1067
+ allow(source).to receive(:can_capture?) { false }
1068
+ expect(subject.actions).not_to include "capture"
1069
+ end
1070
+
1071
+ it "does not include 'failure' by default" do
1072
+ expect(subject.actions).not_to include "failure"
1073
+ end
1074
+
1075
+ context "payment state is processing" do
1076
+ it "includes the 'failure' action" do
1077
+ # because the processing state does not provide
1078
+ # clarity about what has happened with an external
1079
+ # payment processor, so we want to allow the ability
1080
+ # to have someone look at the what happened and determine
1081
+ # to mark the payment as having failed
1082
+ subject.state = 'processing'
1083
+ expect(subject.actions).to include "failure"
1084
+ end
1085
+ end
1086
+ end
1087
+ end