solidus_core 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_core might be problematic. Click here for more details.

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