solidus_core 1.0.2 → 1.0.3

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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/Gemfile +3 -0
  4. data/Rakefile +16 -0
  5. data/script/rails +9 -0
  6. data/solidus_core.gemspec +48 -0
  7. data/spec/fixtures/thinking-cat.jpg +0 -0
  8. data/spec/helpers/base_helper_spec.rb +173 -0
  9. data/spec/helpers/order_helper_spec.rb +12 -0
  10. data/spec/helpers/products_helper_spec.rb +220 -0
  11. data/spec/helpers/taxons_helper_spec.rb +17 -0
  12. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  13. data/spec/lib/i18n_spec.rb +123 -0
  14. data/spec/lib/search/base_spec.rb +86 -0
  15. data/spec/lib/search/variant_spec.rb +92 -0
  16. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
  17. data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -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 +22 -0
  23. data/spec/lib/spree/core/importer/order_spec.rb +431 -0
  24. data/spec/lib/spree/core/role_configuration_spec.rb +138 -0
  25. data/spec/lib/spree/core/validators/email_spec.rb +48 -0
  26. data/spec/lib/spree/localized_number_spec.rb +38 -0
  27. data/spec/lib/spree/migrations_spec.rb +36 -0
  28. data/spec/lib/spree/money_spec.rb +127 -0
  29. data/spec/lib/tasks/exchanges_spec.rb +231 -0
  30. data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
  31. data/spec/lib/tasks/order_capturing_spec.rb +56 -0
  32. data/spec/mailers/carton_mailer_spec.rb +43 -0
  33. data/spec/mailers/order_mailer_spec.rb +122 -0
  34. data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
  35. data/spec/mailers/test_mailer_spec.rb +15 -0
  36. data/spec/models/spree/ability_spec.rb +276 -0
  37. data/spec/models/spree/address_spec.rb +250 -0
  38. data/spec/models/spree/adjustment_reason_spec.rb +13 -0
  39. data/spec/models/spree/adjustment_spec.rb +177 -0
  40. data/spec/models/spree/app_configuration_spec.rb +20 -0
  41. data/spec/models/spree/asset_spec.rb +24 -0
  42. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  43. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  44. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  45. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  46. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  47. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  48. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
  49. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  50. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  51. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  52. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  53. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
  54. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
  55. data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
  56. data/spec/models/spree/calculator_spec.rb +36 -0
  57. data/spec/models/spree/carton_spec.rb +133 -0
  58. data/spec/models/spree/classification_spec.rb +15 -0
  59. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  60. data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
  61. data/spec/models/spree/credit_card_spec.rb +334 -0
  62. data/spec/models/spree/customer_return_spec.rb +276 -0
  63. data/spec/models/spree/exchange_spec.rb +79 -0
  64. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  65. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  66. data/spec/models/spree/gateway_spec.rb +82 -0
  67. data/spec/models/spree/inventory_unit_spec.rb +307 -0
  68. data/spec/models/spree/item_adjustments_spec.rb +256 -0
  69. data/spec/models/spree/line_item_spec.rb +191 -0
  70. data/spec/models/spree/option_type_spec.rb +14 -0
  71. data/spec/models/spree/option_value_spec.rb +22 -0
  72. data/spec/models/spree/order/address_spec.rb +50 -0
  73. data/spec/models/spree/order/adjustments_spec.rb +39 -0
  74. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  75. data/spec/models/spree/order/checkout_spec.rb +902 -0
  76. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  77. data/spec/models/spree/order/finalizing_spec.rb +111 -0
  78. data/spec/models/spree/order/payment_spec.rb +210 -0
  79. data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
  80. data/spec/models/spree/order/state_machine_spec.rb +221 -0
  81. data/spec/models/spree/order/tax_spec.rb +84 -0
  82. data/spec/models/spree/order/totals_spec.rb +24 -0
  83. data/spec/models/spree/order/updating_spec.rb +18 -0
  84. data/spec/models/spree/order/validations_spec.rb +15 -0
  85. data/spec/models/spree/order_cancellations_spec.rb +120 -0
  86. data/spec/models/spree/order_capturing_spec.rb +116 -0
  87. data/spec/models/spree/order_contents_spec.rb +265 -0
  88. data/spec/models/spree/order_inventory_spec.rb +228 -0
  89. data/spec/models/spree/order_mutex_spec.rb +85 -0
  90. data/spec/models/spree/order_promotion_spec.rb +31 -0
  91. data/spec/models/spree/order_shipping_spec.rb +247 -0
  92. data/spec/models/spree/order_spec.rb +1412 -0
  93. data/spec/models/spree/order_stock_location_spec.rb +18 -0
  94. data/spec/models/spree/order_updater_spec.rb +299 -0
  95. data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
  96. data/spec/models/spree/payment_method_spec.rb +96 -0
  97. data/spec/models/spree/payment_spec.rb +1044 -0
  98. data/spec/models/spree/permission_sets/base_spec.rb +12 -0
  99. data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
  100. data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
  101. data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
  102. data/spec/models/spree/permission_sets/order_display_spec.rb +49 -0
  103. data/spec/models/spree/permission_sets/order_management_spec.rb +36 -0
  104. data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
  105. data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
  106. data/spec/models/spree/permission_sets/promotion_display_spec.rb +34 -0
  107. data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
  108. data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
  109. data/spec/models/spree/permission_sets/restricted_transfer_management_spec.rb +132 -0
  110. data/spec/models/spree/permission_sets/stock_display_spec.rb +26 -0
  111. data/spec/models/spree/permission_sets/stock_management_spec.rb +24 -0
  112. data/spec/models/spree/permission_sets/user_display_spec.rb +36 -0
  113. data/spec/models/spree/permission_sets/user_management_spec.rb +28 -0
  114. data/spec/models/spree/preference_spec.rb +80 -0
  115. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  116. data/spec/models/spree/preferences/preferable_spec.rb +294 -0
  117. data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
  118. data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
  119. data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
  120. data/spec/models/spree/preferences/store_spec.rb +39 -0
  121. data/spec/models/spree/price_spec.rb +42 -0
  122. data/spec/models/spree/product/scopes_spec.rb +148 -0
  123. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  124. data/spec/models/spree/product_filter_spec.rb +26 -0
  125. data/spec/models/spree/product_property_spec.rb +20 -0
  126. data/spec/models/spree/product_spec.rb +437 -0
  127. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
  128. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
  129. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
  130. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
  131. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  132. data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
  133. data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
  134. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  135. data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
  136. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  137. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  138. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  139. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  140. data/spec/models/spree/promotion_builder_spec.rb +118 -0
  141. data/spec/models/spree/promotion_category_spec.rb +17 -0
  142. data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
  143. data/spec/models/spree/promotion_code_spec.rb +187 -0
  144. data/spec/models/spree/promotion_handler/cart_spec.rb +114 -0
  145. data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
  146. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
  147. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  148. data/spec/models/spree/promotion_rule_spec.rb +28 -0
  149. data/spec/models/spree/promotion_spec.rb +767 -0
  150. data/spec/models/spree/refund_spec.rb +204 -0
  151. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  152. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  153. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  154. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  155. data/spec/models/spree/reimbursement_spec.rb +231 -0
  156. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  157. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  158. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  159. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
  160. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
  161. data/spec/models/spree/return_authorization_spec.rb +290 -0
  162. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  163. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  164. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
  165. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  166. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  167. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  168. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  169. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  170. data/spec/models/spree/return_item_spec.rb +775 -0
  171. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  172. data/spec/models/spree/shipment_spec.rb +709 -0
  173. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  174. data/spec/models/spree/shipping_method_spec.rb +88 -0
  175. data/spec/models/spree/shipping_rate_spec.rb +142 -0
  176. data/spec/models/spree/state_spec.rb +14 -0
  177. data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
  178. data/spec/models/spree/stock/coordinator_spec.rb +116 -0
  179. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  180. data/spec/models/spree/stock/estimator_spec.rb +146 -0
  181. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  182. data/spec/models/spree/stock/package_spec.rb +163 -0
  183. data/spec/models/spree/stock/packer_spec.rb +91 -0
  184. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  185. data/spec/models/spree/stock/quantifier_spec.rb +115 -0
  186. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  187. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  188. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
  189. data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
  190. data/spec/models/spree/stock_item_spec.rb +426 -0
  191. data/spec/models/spree/stock_location_spec.rb +279 -0
  192. data/spec/models/spree/stock_movement_spec.rb +56 -0
  193. data/spec/models/spree/stock_transfer_spec.rb +290 -0
  194. data/spec/models/spree/store_credit_category_spec.rb +17 -0
  195. data/spec/models/spree/store_credit_event_spec.rb +314 -0
  196. data/spec/models/spree/store_credit_spec.rb +876 -0
  197. data/spec/models/spree/store_spec.rb +55 -0
  198. data/spec/models/spree/tax_category_spec.rb +27 -0
  199. data/spec/models/spree/tax_rate_spec.rb +378 -0
  200. data/spec/models/spree/taxon_spec.rb +74 -0
  201. data/spec/models/spree/taxonomy_spec.rb +18 -0
  202. data/spec/models/spree/tracker_spec.rb +21 -0
  203. data/spec/models/spree/transfer_item_spec.rb +264 -0
  204. data/spec/models/spree/unit_cancel_spec.rb +148 -0
  205. data/spec/models/spree/user_spec.rb +223 -0
  206. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
  207. data/spec/models/spree/variant/scopes_spec.rb +55 -0
  208. data/spec/models/spree/variant_spec.rb +546 -0
  209. data/spec/models/spree/zone_spec.rb +305 -0
  210. data/spec/spec_helper.rb +78 -0
  211. data/spec/support/big_decimal.rb +5 -0
  212. data/spec/support/concerns/default_price.rb +34 -0
  213. data/spec/support/dummy_ability.rb +4 -0
  214. data/spec/support/test_gateway.rb +2 -0
  215. metadata +229 -3
  216. data/lib/spree/testing_support/rspec-activemodel-mocks_patch.rb +0 -8
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::StoreCreditCategory, :type => :model do
4
+ describe "#non_expiring?" do
5
+ let(:store_credit_category) { build(:store_credit_category, name: category_name) }
6
+
7
+ context "non-expiring type store credit" do
8
+ let(:category_name) { "Non-expiring" }
9
+ it { expect(store_credit_category).to be_non_expiring }
10
+ end
11
+
12
+ context "expiring type store credit" do
13
+ let(:category_name) { "Expiring" }
14
+ it { expect(store_credit_category).not_to be_non_expiring }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,314 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::StoreCreditEvent do
4
+
5
+ describe ".exposed_events" do
6
+
7
+ [
8
+ Spree::StoreCredit::ELIGIBLE_ACTION,
9
+ Spree::StoreCredit::AUTHORIZE_ACTION,
10
+ ].each do |action|
11
+ let(:action) { action }
12
+ it "excludes #{action} actions" do
13
+ event = create(:store_credit_event, action: action)
14
+ expect(described_class.exposed_events).not_to include event
15
+ end
16
+ end
17
+
18
+ [
19
+ Spree::StoreCredit::VOID_ACTION,
20
+ Spree::StoreCredit::CREDIT_ACTION,
21
+ Spree::StoreCredit::CAPTURE_ACTION,
22
+ Spree::StoreCredit::ALLOCATION_ACTION,
23
+ ].each do |action|
24
+ it "includes #{action} actions" do
25
+ event = create(:store_credit_event, action: action)
26
+ expect(described_class.exposed_events).to include event
27
+ end
28
+ end
29
+
30
+ it "excludes invalidated store credit events" do
31
+ invalidated_store_credit = create(:store_credit, invalidated_at: Time.now)
32
+ event = create(:store_credit_event, action: Spree::StoreCredit::VOID_ACTION, store_credit: invalidated_store_credit)
33
+ expect(described_class.exposed_events).not_to include event
34
+ end
35
+ end
36
+
37
+ describe "update reason validation" do
38
+ subject { event.valid? }
39
+
40
+ context "adjustment event" do
41
+ context "has an update reason" do
42
+ let(:event) { build(:store_credit_adjustment_event) }
43
+
44
+ it "returns true" do
45
+ expect(subject).to eq true
46
+ end
47
+ end
48
+
49
+ context "doesn't have an update reason" do
50
+ let(:event) { build(:store_credit_adjustment_event, update_reason: nil) }
51
+
52
+ it "returns false" do
53
+ expect(subject).to eq false
54
+ end
55
+
56
+ it "adds an error message indicating the update reason is missing" do
57
+ subject
58
+ expect(event.errors.full_messages).to match ["Update reason can't be blank"]
59
+ end
60
+ end
61
+ end
62
+
63
+ context "invalidate event" do
64
+ context "has an update reason" do
65
+ let(:event) { build(:store_credit_invalidate_event) }
66
+
67
+ it "returns true" do
68
+ expect(subject).to eq true
69
+ end
70
+ end
71
+
72
+ context "doesn't have an update reason" do
73
+ let(:event) { build(:store_credit_invalidate_event, update_reason: nil) }
74
+
75
+ it "returns false" do
76
+ expect(subject).to eq false
77
+ end
78
+
79
+ it "adds an error message indicating the update reason is missing" do
80
+ subject
81
+ expect(event.errors.full_messages).to match ["Update reason can't be blank"]
82
+ end
83
+ end
84
+ end
85
+
86
+ context "event doesn't require an update reason" do
87
+ let(:event) { build(:store_credit_auth_event) }
88
+
89
+ it "returns true" do
90
+ expect(subject).to eq true
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "#capture_action?" do
96
+ subject { event.capture_action? }
97
+
98
+ context "for capture events" do
99
+ let(:event) { create(:store_credit_capture_event) }
100
+
101
+ it "returns true" do
102
+ expect(subject).to eq true
103
+ end
104
+ end
105
+
106
+ context "for non-capture events" do
107
+ let(:event) { create(:store_credit_auth_event) }
108
+
109
+ it "returns false" do
110
+ expect(subject).to eq false
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "#authorization_action?" do
116
+ subject { event.authorization_action? }
117
+
118
+ context "for auth events" do
119
+ let(:event) { create(:store_credit_auth_event) }
120
+
121
+ it "returns true" do
122
+ expect(subject).to eq true
123
+ end
124
+ end
125
+
126
+ context "for non-auth events" do
127
+ let(:event) { create(:store_credit_capture_event) }
128
+
129
+ it "returns false" do
130
+ expect(subject).to eq false
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "#action_requires_reason?" do
136
+ subject { event.action_requires_reason? }
137
+
138
+ context "for adjustment events" do
139
+ let(:event) { create(:store_credit_adjustment_event) }
140
+
141
+ it "returns true" do
142
+ expect(subject).to eq true
143
+ end
144
+ end
145
+
146
+ context "for invalidate events" do
147
+ let(:event) { create(:store_credit_invalidate_event) }
148
+
149
+ it "returns true" do
150
+ expect(subject).to eq true
151
+ end
152
+ end
153
+
154
+ context "for capture events" do
155
+ let(:event) { create(:store_credit_capture_event) }
156
+
157
+ it "returns false" do
158
+ expect(subject).to eq false
159
+ end
160
+ end
161
+
162
+ context "for authorize events" do
163
+ let(:event) { create(:store_credit_auth_event) }
164
+
165
+ it "returns false" do
166
+ expect(subject).to eq false
167
+ end
168
+ end
169
+
170
+ context "for allocation events" do
171
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::ALLOCATION_ACTION) }
172
+
173
+ it "returns false" do
174
+ expect(subject).to eq false
175
+ end
176
+ end
177
+
178
+ context "for void events" do
179
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::VOID_ACTION) }
180
+
181
+ it "returns false" do
182
+ expect(subject).to eq false
183
+ end
184
+ end
185
+
186
+ context "for credit events" do
187
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::CREDIT_ACTION) }
188
+
189
+ it "returns false" do
190
+ expect(subject).to eq false
191
+ end
192
+ end
193
+ end
194
+
195
+ describe "#display_amount" do
196
+ let(:event_amount) { 120.0 }
197
+
198
+ subject { create(:store_credit_auth_event, amount: event_amount) }
199
+
200
+ it "returns a Spree::Money instance" do
201
+ expect(subject.display_amount).to be_instance_of(Spree::Money)
202
+ end
203
+
204
+ it "uses the events amount attribute" do
205
+ expect(subject.display_amount).to eq Spree::Money.new(event_amount, { currency: subject.currency })
206
+ end
207
+ end
208
+
209
+ describe "#display_user_total_amount" do
210
+ let(:user_total_amount) { 300.0 }
211
+
212
+ subject { create(:store_credit_auth_event, user_total_amount: user_total_amount) }
213
+
214
+ it "returns a Spree::Money instance" do
215
+ expect(subject.display_user_total_amount).to be_instance_of(Spree::Money)
216
+ end
217
+
218
+ it "uses the events user_total_amount attribute" do
219
+ expect(subject.display_user_total_amount).to eq Spree::Money.new(user_total_amount, { currency: subject.currency })
220
+ end
221
+ end
222
+
223
+ describe "#display_event_date" do
224
+ let(:date) { DateTime.new(2014, 06, 1) }
225
+
226
+ subject { create(:store_credit_auth_event, created_at: date) }
227
+
228
+ it "returns the date the event was created with the format month/date/year" do
229
+ expect(subject.display_event_date).to eq "June 01, 2014"
230
+ end
231
+ end
232
+
233
+ describe "#display_action" do
234
+ subject { event.display_action }
235
+
236
+ context "capture event" do
237
+ let(:event) { create(:store_credit_capture_event) }
238
+
239
+ it "returns the action's display text" do
240
+ expect(subject).to eq "Used"
241
+ end
242
+ end
243
+
244
+ context "allocation event" do
245
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::ALLOCATION_ACTION) }
246
+
247
+ it "returns the action's display text" do
248
+ expect(subject).to eq "Added"
249
+ end
250
+ end
251
+
252
+ context "void event" do
253
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::VOID_ACTION) }
254
+
255
+ it "returns the action's display text" do
256
+ expect(subject).to eq "Credit"
257
+ end
258
+ end
259
+
260
+ context "credit event" do
261
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::CREDIT_ACTION) }
262
+
263
+ it "returns the action's display text" do
264
+ expect(subject).to eq "Credit"
265
+ end
266
+ end
267
+
268
+ context "adjustment event" do
269
+ let(:event) { create(:store_credit_adjustment_event) }
270
+
271
+ it "returns the action's display text" do
272
+ expect(subject).to eq "Adjustment"
273
+ end
274
+ end
275
+
276
+ context "authorize event" do
277
+ let(:event) { create(:store_credit_auth_event) }
278
+
279
+ it "returns nil" do
280
+ expect(subject).to be_nil
281
+ end
282
+ end
283
+
284
+ context "eligible event" do
285
+ let(:event) { create(:store_credit_event, action: Spree::StoreCredit::ELIGIBLE_ACTION) }
286
+
287
+ it "returns nil" do
288
+ expect(subject).to be_nil
289
+ end
290
+ end
291
+ end
292
+
293
+ describe "#order" do
294
+ context "there is no associated payment with the event" do
295
+ subject { create(:store_credit_auth_event) }
296
+
297
+ it "returns nil" do
298
+ expect(subject.order).to be_nil
299
+ end
300
+ end
301
+
302
+ context "there is an associated payment with the event" do
303
+ let(:authorization_code) { "1-SC-TEST" }
304
+ let(:order) { create(:order) }
305
+ let!(:payment) { create(:store_credit_payment, order: order, response_code: authorization_code) }
306
+
307
+ subject { create(:store_credit_auth_event, action: Spree::StoreCredit::CAPTURE_ACTION, authorization_code: authorization_code) }
308
+
309
+ it "returns the order associated with the payment" do
310
+ expect(subject.order).to eq order
311
+ end
312
+ end
313
+ end
314
+ end
@@ -0,0 +1,876 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::StoreCredit do
4
+
5
+ let(:currency) { "TEST" }
6
+ let(:store_credit) { build(:store_credit, store_credit_attrs) }
7
+ let(:store_credit_attrs) { {} }
8
+
9
+
10
+ describe "callbacks" do
11
+ subject { store_credit.save }
12
+
13
+ context "amount used is greater than zero" do
14
+ let(:store_credit) { create(:store_credit, amount: 100, amount_used: 1) }
15
+ subject { store_credit.destroy }
16
+
17
+ it 'can not delete the store credit' do
18
+ subject
19
+ expect(store_credit.reload).to eq store_credit
20
+ expect(store_credit.errors[:amount_used]).to include("is greater than zero. Can not delete store credit")
21
+ end
22
+ end
23
+
24
+ context "category is a non-expiring type" do
25
+ let!(:secondary_credit_type) { create(:secondary_credit_type) }
26
+ let(:store_credit) { build(:store_credit, credit_type: nil)}
27
+
28
+ before do
29
+ allow(store_credit.category).to receive(:non_expiring?).and_return(true)
30
+ end
31
+
32
+ it "sets the credit type to non-expiring" do
33
+ subject
34
+ expect(store_credit.credit_type.name).to eq secondary_credit_type.name
35
+ end
36
+ end
37
+
38
+ context "category is an expiring type" do
39
+ before do
40
+ allow(store_credit.category).to receive(:non_expiring?).and_return(false)
41
+ end
42
+
43
+ it "sets the credit type to non-expiring" do
44
+ subject
45
+ expect(store_credit.credit_type.name).to eq "Expiring"
46
+ end
47
+ end
48
+
49
+ context "the type is set" do
50
+ let!(:secondary_credit_type) { create(:secondary_credit_type)}
51
+ let(:store_credit) { build(:store_credit, credit_type: secondary_credit_type)}
52
+
53
+ before do
54
+ allow(store_credit.category).to receive(:non_expiring?).and_return(false)
55
+ end
56
+
57
+ it "doesn't overwrite the type" do
58
+ expect{ subject }.to_not change{ store_credit.credit_type }
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "validations" do
64
+ describe "used amount should not be greater than the credited amount" do
65
+ context "the used amount is defined" do
66
+ let(:invalid_store_credit) { build(:store_credit, amount: 100, amount_used: 150) }
67
+
68
+ it "should not be valid" do
69
+ expect(invalid_store_credit).not_to be_valid
70
+ end
71
+
72
+ it "should set the correct error message" do
73
+ invalid_store_credit.valid?
74
+ expect(invalid_store_credit.errors.full_messages).to include("Amount used cannot be greater than the credited amount")
75
+ end
76
+ end
77
+
78
+ context "the used amount is not defined yet" do
79
+ let(:store_credit) { build(:store_credit, amount: 100) }
80
+
81
+ it "should be valid" do
82
+ expect(store_credit).to be_valid
83
+ end
84
+
85
+ end
86
+ end
87
+
88
+ describe "amount used less than or equal to amount" do
89
+ subject { build(:store_credit, amount_used: 101.0, amount: 100.0) }
90
+
91
+ it "is not valid" do
92
+ expect(subject).not_to be_valid
93
+ end
94
+
95
+ it "adds an error message about the invalid amount used" do
96
+ subject.valid?
97
+ expect(subject.errors[:amount_used]).to include("cannot be greater than the credited amount")
98
+ end
99
+ end
100
+
101
+ describe "amount authorized less than or equal to amount" do
102
+ subject { build(:store_credit, amount_authorized: 101.0, amount: 100.0) }
103
+
104
+ it "is not valid" do
105
+ expect(subject).not_to be_valid
106
+ end
107
+
108
+ it "adds an error message about the invalid authorized amount" do
109
+ subject.valid?
110
+ expect(subject.errors[:amount_authorized]).to include(" exceeds the available credit")
111
+ end
112
+ end
113
+
114
+ describe "editing category" do
115
+ let!(:store_credit) { create(:store_credit) }
116
+ let!(:test_category) { create(:store_credit_category, name: "Testing") }
117
+
118
+ subject { store_credit.update_attributes(category: test_category) }
119
+
120
+ it "returns false" do
121
+ expect(subject).to eq false
122
+ end
123
+
124
+ it "category doesn't change" do
125
+ expect { subject }.not_to change { store_credit.reload.category }
126
+ end
127
+
128
+ it "adds an error message about not being able to edit the category" do
129
+ subject
130
+ expect(store_credit.errors[:category]).to include("cannot be modified")
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "#display_amount" do
136
+ it "returns a Spree::Money instance" do
137
+ expect(store_credit.display_amount).to be_instance_of(Spree::Money)
138
+ end
139
+ end
140
+
141
+ describe "#display_amount_used" do
142
+ it "returns a Spree::Money instance" do
143
+ expect(store_credit.display_amount_used).to be_instance_of(Spree::Money)
144
+ end
145
+ end
146
+
147
+ describe "#display_amount_authorized" do
148
+ it "returns a Spree::Money instance" do
149
+ expect(store_credit.display_amount_authorized).to be_instance_of(Spree::Money)
150
+ end
151
+ end
152
+
153
+ describe "#amount_remaining" do
154
+ context "invalidated" do
155
+ before { allow(store_credit).to receive(:invalidated?) { true } }
156
+ it { expect(store_credit.amount_remaining).to eq 0.0 }
157
+ end
158
+
159
+ context "the amount_used is not defined" do
160
+ context "the authorized amount is not defined" do
161
+ it "returns the credited amount" do
162
+ expect(store_credit.amount_remaining).to eq store_credit.amount
163
+ end
164
+ end
165
+ context "the authorized amount is defined" do
166
+ let(:authorized_amount) { 15.00 }
167
+
168
+ before { store_credit.update_attributes(amount_authorized: authorized_amount) }
169
+
170
+ it "subtracts the authorized amount from the credited amount" do
171
+ expect(store_credit.amount_remaining).to eq (store_credit.amount - authorized_amount)
172
+ end
173
+ end
174
+ end
175
+
176
+ context "the amount_used is defined" do
177
+ let(:amount_used) { 10.0 }
178
+
179
+ before { store_credit.update_attributes(amount_used: amount_used) }
180
+
181
+ context "the authorized amount is not defined" do
182
+ it "subtracts the amount used from the credited amount" do
183
+ expect(store_credit.amount_remaining).to eq (store_credit.amount - amount_used)
184
+ end
185
+ end
186
+
187
+ context "the authorized amount is defined" do
188
+ let(:authorized_amount) { 15.00 }
189
+
190
+ before { store_credit.update_attributes(amount_authorized: authorized_amount) }
191
+
192
+ it "subtracts the amount used and the authorized amount from the credited amount" do
193
+ expect(store_credit.amount_remaining).to eq (store_credit.amount - amount_used - authorized_amount)
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ describe "#authorize" do
200
+ context "amount is valid" do
201
+ let(:authorization_amount) { 1.0 }
202
+ let(:added_authorization_amount) { 3.0 }
203
+ let(:originator) { nil }
204
+
205
+ context "amount has not been authorized yet" do
206
+
207
+ before { store_credit.update_attributes(amount_authorized: authorization_amount) }
208
+
209
+ it "returns true" do
210
+ expect(store_credit.authorize(store_credit.amount - authorization_amount, store_credit.currency)).to be_truthy
211
+ end
212
+
213
+ it "adds the new amount to authorized amount" do
214
+ store_credit.authorize(added_authorization_amount, store_credit.currency)
215
+ expect(store_credit.reload.amount_authorized).to eq (authorization_amount + added_authorization_amount)
216
+ end
217
+
218
+ context "originator is present" do
219
+ let(:originator) { create(:user) } # won't actually be a user. just giving it a valid model here
220
+
221
+ subject { store_credit.authorize(added_authorization_amount, store_credit.currency, action_originator: originator) }
222
+
223
+ it "records the originator" do
224
+ expect { subject }.to change { Spree::StoreCreditEvent.count }.by(1)
225
+ expect(Spree::StoreCreditEvent.last.originator).to eq originator
226
+ end
227
+ end
228
+ end
229
+
230
+ context "authorization has already happened" do
231
+ let!(:auth_event) { create(:store_credit_auth_event, store_credit: store_credit) }
232
+
233
+ before { store_credit.update_attributes(amount_authorized: store_credit.amount) }
234
+
235
+ it "returns true" do
236
+ expect(store_credit.authorize(store_credit.amount, store_credit.currency, action_authorization_code: auth_event.authorization_code)).to be true
237
+ end
238
+ end
239
+ end
240
+
241
+ context "amount is invalid" do
242
+ it "returns false" do
243
+ expect(store_credit.authorize(store_credit.amount * 2, store_credit.currency)).to be false
244
+ end
245
+ end
246
+ end
247
+
248
+ describe "#validate_authorization" do
249
+ context "insufficient funds" do
250
+ subject { store_credit.validate_authorization(store_credit.amount * 2, store_credit.currency) }
251
+
252
+ it "returns false" do
253
+ expect(subject).to be false
254
+ end
255
+
256
+ it "adds an error to the model" do
257
+ subject
258
+ expect(store_credit.errors.full_messages).to include("Store credit amount remaining is not sufficient")
259
+ end
260
+ end
261
+
262
+ context "currency mismatch" do
263
+ subject { store_credit.validate_authorization(store_credit.amount, "EUR") }
264
+
265
+ it "returns false" do
266
+ expect(subject).to be false
267
+ end
268
+
269
+ it "adds an error to the model" do
270
+ subject
271
+ expect(store_credit.errors.full_messages).to include("Store credit currency does not match order currency")
272
+ end
273
+ end
274
+
275
+ context "valid authorization" do
276
+ subject { store_credit.validate_authorization(store_credit.amount, store_credit.currency) }
277
+
278
+ it "returns true" do
279
+ expect(subject).to be true
280
+ end
281
+ end
282
+
283
+ context 'troublesome floats' do
284
+ # 8.21.to_d < 8.21 => true
285
+ let(:store_credit_attrs) { {amount: 8.21} }
286
+
287
+ subject { store_credit.validate_authorization(store_credit_attrs[:amount], store_credit.currency) }
288
+
289
+ it { is_expected.to be_truthy }
290
+ end
291
+ end
292
+
293
+ describe "#capture" do
294
+ let(:authorized_amount) { 10.00 }
295
+ let(:auth_code) { "23-SC-20140602164814476128" }
296
+
297
+ before do
298
+ @original_authed_amount = store_credit.amount_authorized
299
+ @auth_code = store_credit.authorize(authorized_amount, store_credit.currency)
300
+ end
301
+
302
+ context "insufficient funds" do
303
+ subject { store_credit.capture(authorized_amount * 2, @auth_code, store_credit.currency) }
304
+
305
+ it "returns false" do
306
+ expect(subject).to be false
307
+ end
308
+
309
+ it "adds an error to the model" do
310
+ subject
311
+ expect(store_credit.errors.full_messages).to include("Unable to capture more than authorized amount")
312
+ end
313
+
314
+ it "does not update the store credit model" do
315
+ expect { subject }.to_not change { store_credit }
316
+ end
317
+ end
318
+
319
+ context "currency mismatch" do
320
+ subject { store_credit.capture(authorized_amount, @auth_code, "EUR") }
321
+
322
+ it "returns false" do
323
+ expect(subject).to be false
324
+ end
325
+
326
+ it "adds an error to the model" do
327
+ subject
328
+ expect(store_credit.errors.full_messages).to include("Store credit currency does not match order currency")
329
+ end
330
+
331
+ it "does not update the store credit model" do
332
+ expect { subject }.to_not change { store_credit }
333
+ end
334
+ end
335
+
336
+ context "valid capture" do
337
+ let(:remaining_authorized_amount) { 1 }
338
+ let(:originator) { nil }
339
+
340
+ subject { store_credit.capture(authorized_amount - remaining_authorized_amount, @auth_code, store_credit.currency, action_originator: originator) }
341
+
342
+ it "returns true" do
343
+ expect(subject).to be_truthy
344
+ end
345
+
346
+ it "updates the authorized amount to the difference between the store credits total authed amount and the authorized amount for this event" do
347
+ subject
348
+ expect(store_credit.reload.amount_authorized).to eq(@original_authed_amount)
349
+ end
350
+
351
+ it "updates the used amount to the current used amount plus the captured amount" do
352
+ subject
353
+ expect(store_credit.reload.amount_used).to eq authorized_amount - remaining_authorized_amount
354
+ end
355
+
356
+ context "originator is present" do
357
+ let(:originator) { create(:user) } # won't actually be a user. just giving it a valid model here
358
+
359
+ it "records the originator" do
360
+ expect { subject }.to change { Spree::StoreCreditEvent.count }.by(1)
361
+ expect(Spree::StoreCreditEvent.last.originator).to eq originator
362
+ end
363
+ end
364
+ end
365
+ end
366
+
367
+ describe "#void" do
368
+ let(:auth_code) { "1-SC-20141111111111" }
369
+ let(:store_credit) { create(:store_credit, amount_used: 150.0) }
370
+ let(:originator) { nil }
371
+
372
+ subject do
373
+ store_credit.void(auth_code, action_originator: originator)
374
+ end
375
+
376
+ context "no event found for auth_code" do
377
+
378
+ it "returns false" do
379
+ expect(subject).to be false
380
+ end
381
+
382
+ it "adds an error to the model" do
383
+ subject
384
+ expect(store_credit.errors.full_messages).to include("Unable to void code: #{auth_code}")
385
+ end
386
+ end
387
+
388
+ context "capture event found for auth_code" do
389
+ let(:captured_amount) { 10.0 }
390
+ let!(:capture_event) { create(:store_credit_auth_event,
391
+ action: Spree::StoreCredit::CAPTURE_ACTION,
392
+ authorization_code: auth_code,
393
+ amount: captured_amount,
394
+ store_credit: store_credit) }
395
+
396
+ it "returns false" do
397
+ expect(subject).to be false
398
+ end
399
+
400
+ it "does not change the amount used on the store credit" do
401
+ expect { subject }.to_not change{ store_credit.amount_used.to_f }
402
+ end
403
+ end
404
+
405
+ context "auth event found for auth_code" do
406
+ let(:auth_event) { create(:store_credit_auth_event) }
407
+
408
+ let(:authorized_amount) { 10.0 }
409
+ let!(:auth_event) { create(:store_credit_auth_event,
410
+ authorization_code: auth_code,
411
+ amount: authorized_amount,
412
+ store_credit: store_credit) }
413
+
414
+ it "returns true" do
415
+ expect(subject).to be true
416
+ end
417
+
418
+ it "returns the capture amount to the store credit" do
419
+ expect { subject }.to change{ store_credit.amount_authorized.to_f }.by(-authorized_amount)
420
+ end
421
+
422
+ context "originator is present" do
423
+ let(:originator) { create(:user) } # won't actually be a user. just giving it a valid model here
424
+
425
+ it "records the originator" do
426
+ expect { subject }.to change { Spree::StoreCreditEvent.count }.by(1)
427
+ expect(Spree::StoreCreditEvent.last.originator).to eq originator
428
+ end
429
+ end
430
+ end
431
+ end
432
+
433
+ describe "#credit" do
434
+ let(:event_auth_code) { "1-SC-20141111111111" }
435
+ let(:amount_used) { 10.0 }
436
+ let(:store_credit) { create(:store_credit, amount_used: amount_used) }
437
+ let!(:capture_event) { create(:store_credit_auth_event,
438
+ action: Spree::StoreCredit::CAPTURE_ACTION,
439
+ authorization_code: event_auth_code,
440
+ amount: captured_amount,
441
+ store_credit: store_credit) }
442
+ let(:originator) { nil }
443
+
444
+ subject { store_credit.credit(credit_amount, auth_code, currency, action_originator: originator) }
445
+
446
+ context "currency does not match" do
447
+ let(:currency) { "AUD" }
448
+ let(:credit_amount) { 5.0 }
449
+ let(:captured_amount) { 100.0 }
450
+ let(:auth_code) { event_auth_code }
451
+
452
+ it "returns false" do
453
+ expect(subject).to be false
454
+ end
455
+
456
+ it "adds an error message about the currency mismatch" do
457
+ subject
458
+ expect(store_credit.errors.full_messages).to include("Store credit currency does not match order currency")
459
+ end
460
+ end
461
+
462
+ context "unable to find capture event" do
463
+ let(:currency) { "USD" }
464
+ let(:credit_amount) { 5.0 }
465
+ let(:captured_amount) { 100.0 }
466
+ let(:auth_code) { "UNKNOWN_CODE" }
467
+
468
+ it "returns false" do
469
+ expect(subject).to be false
470
+ end
471
+
472
+ it "adds an error message about the currency mismatch" do
473
+ subject
474
+ expect(store_credit.errors.full_messages).to include("Unable to credit code: #{auth_code}")
475
+ end
476
+ end
477
+
478
+ context "amount is more than what is captured" do
479
+ let(:currency) { "USD" }
480
+ let(:credit_amount) { 100.0 }
481
+ let(:captured_amount) { 5.0 }
482
+ let(:auth_code) { event_auth_code }
483
+
484
+ it "returns false" do
485
+ expect(subject).to be false
486
+ end
487
+
488
+ it "adds an error message about the currency mismatch" do
489
+ subject
490
+ expect(store_credit.errors.full_messages).to include("Unable to credit code: #{auth_code}")
491
+ end
492
+ end
493
+
494
+ context "amount is successfully credited" do
495
+ let(:currency) { "USD" }
496
+ let(:credit_amount) { 5.0 }
497
+ let(:captured_amount) { 100.0 }
498
+ let(:auth_code) { event_auth_code }
499
+
500
+ context "credit_to_new_allocation is set" do
501
+ before { Spree::Config[:credit_to_new_allocation] = true }
502
+
503
+ it "returns true" do
504
+ expect(subject).to be true
505
+ end
506
+
507
+ it "creates a new store credit record" do
508
+ expect { subject }.to change { Spree::StoreCredit.count }.by(1)
509
+ end
510
+
511
+ it "does not create a new store credit event on the parent store credit" do
512
+ expect { subject }.to_not change { store_credit.store_credit_events.count }
513
+ end
514
+
515
+ context "credits the passed amount to a new store credit record" do
516
+ before do
517
+ subject
518
+ @new_store_credit = Spree::StoreCredit.last
519
+ end
520
+
521
+ it "does not set the amount used on hte originating store credit" do
522
+ expect(store_credit.reload.amount_used).to eq amount_used
523
+ end
524
+
525
+ it "sets the correct amount on the new store credit" do
526
+ expect(@new_store_credit.amount).to eq credit_amount
527
+ end
528
+
529
+ [:user_id, :category_id, :created_by_id, :currency, :type_id].each do |attr|
530
+ it "sets attribute #{attr} inherited from the originating store credit" do
531
+ expect(@new_store_credit.send(attr)).to eq store_credit.send(attr)
532
+ end
533
+ end
534
+
535
+ it "sets a memo" do
536
+ expect(@new_store_credit.memo).to eq "This is a credit from store credit ID #{store_credit.id}"
537
+ end
538
+ end
539
+
540
+ context "originator is present" do
541
+ let(:originator) { create(:user) } # won't actually be a user. just giving it a valid model here
542
+
543
+ it "records the originator" do
544
+ expect { subject }.to change { Spree::StoreCreditEvent.count }.by(1)
545
+ expect(Spree::StoreCreditEvent.last.originator).to eq originator
546
+ end
547
+ end
548
+ end
549
+
550
+ context "credit_to_new_allocation is not set" do
551
+ it "returns true" do
552
+ expect(subject).to be true
553
+ end
554
+
555
+ it "credits the passed amount to the store credit amount used" do
556
+ subject
557
+ expect(store_credit.reload.amount_used).to eq (amount_used - credit_amount)
558
+ end
559
+
560
+ it "creates a new store credit event" do
561
+ expect { subject }.to change { store_credit.store_credit_events.count }.by(1)
562
+ end
563
+ end
564
+ end
565
+ end
566
+
567
+ describe "#amount_used" do
568
+ context "amount used is not defined" do
569
+ subject { Spree::StoreCredit.new }
570
+
571
+ it "returns zero" do
572
+ expect(subject.amount_used).to be_zero
573
+ end
574
+ end
575
+
576
+ context "amount used is defined" do
577
+ let(:amount_used) { 100.0 }
578
+
579
+ subject { create(:store_credit, amount_used: amount_used) }
580
+
581
+ it "returns the attribute value" do
582
+ expect(subject.amount_used).to eq amount_used
583
+ end
584
+ end
585
+ end
586
+
587
+ describe "#amount_authorized" do
588
+ context "amount authorized is not defined" do
589
+ subject { Spree::StoreCredit.new }
590
+
591
+ it "returns zero" do
592
+ expect(subject.amount_authorized).to be_zero
593
+ end
594
+ end
595
+
596
+ context "amount authorized is defined" do
597
+ let(:amount_authorized) { 100.0 }
598
+
599
+ subject { create(:store_credit, amount_authorized: amount_authorized) }
600
+
601
+ it "returns the attribute value" do
602
+ expect(subject.amount_authorized).to eq amount_authorized
603
+ end
604
+ end
605
+ end
606
+
607
+ describe "#can_capture?" do
608
+ let(:store_credit) { create(:store_credit) }
609
+ let(:payment) { create(:payment, state: payment_state) }
610
+
611
+ subject { store_credit.can_capture?(payment) }
612
+
613
+ context "pending payment" do
614
+ let(:payment_state) { 'pending' }
615
+
616
+ it "returns true" do
617
+ expect(subject).to be true
618
+ end
619
+ end
620
+
621
+ context "checkout payment" do
622
+ let(:payment_state) { 'checkout' }
623
+
624
+ it "returns true" do
625
+ expect(subject).to be true
626
+ end
627
+ end
628
+
629
+ context "void payment" do
630
+ let(:payment_state) { Spree::StoreCredit::VOID_ACTION }
631
+
632
+ it "returns false" do
633
+ expect(subject).to be false
634
+ end
635
+ end
636
+
637
+ context "invalid payment" do
638
+ let(:payment_state) { 'invalid' }
639
+
640
+ it "returns false" do
641
+ expect(subject).to be false
642
+ end
643
+ end
644
+
645
+ context "complete payment" do
646
+ let(:payment_state) { 'completed' }
647
+
648
+ it "returns false" do
649
+ expect(subject).to be false
650
+ end
651
+ end
652
+ end
653
+
654
+ describe "#can_void?" do
655
+ let(:store_credit) { create(:store_credit) }
656
+ let(:payment) { create(:payment, state: payment_state) }
657
+
658
+ subject { store_credit.can_void?(payment) }
659
+
660
+ context "pending payment" do
661
+ let(:payment_state) { 'pending' }
662
+
663
+ it "returns true" do
664
+ expect(subject).to be true
665
+ end
666
+ end
667
+
668
+ context "checkout payment" do
669
+ let(:payment_state) { 'checkout' }
670
+
671
+ it "returns false" do
672
+ expect(subject).to be false
673
+ end
674
+ end
675
+
676
+ context "void payment" do
677
+ let(:payment_state) { Spree::StoreCredit::VOID_ACTION }
678
+
679
+ it "returns false" do
680
+ expect(subject).to be false
681
+ end
682
+ end
683
+
684
+ context "invalid payment" do
685
+ let(:payment_state) { 'invalid' }
686
+
687
+ it "returns false" do
688
+ expect(subject).to be false
689
+ end
690
+ end
691
+
692
+ context "complete payment" do
693
+ let(:payment_state) { 'completed' }
694
+
695
+ it "returns false" do
696
+ expect(subject).to be false
697
+ end
698
+ end
699
+ end
700
+
701
+ describe "#can_credit?" do
702
+ let(:store_credit) { create(:store_credit) }
703
+ let(:payment) { create(:payment, state: payment_state) }
704
+
705
+ subject { store_credit.can_credit?(payment) }
706
+
707
+ context "payment is not completed" do
708
+ let(:payment_state) { "pending" }
709
+
710
+ it "returns false" do
711
+ expect(subject).to be false
712
+ end
713
+ end
714
+
715
+ context "payment is completed" do
716
+ let(:payment_state) { "completed" }
717
+
718
+ context "credit is owed on the order" do
719
+ before { allow(payment.order).to receive_messages(payment_state: 'credit_owed') }
720
+
721
+ context "payment doesn't have allowed credit" do
722
+ before { allow(payment).to receive_messages(credit_allowed: 0.0) }
723
+
724
+ it "returns false" do
725
+ expect(subject).to be false
726
+ end
727
+ end
728
+
729
+ context "payment has allowed credit" do
730
+ before { allow(payment).to receive_messages(credit_allowed: 5.0) }
731
+
732
+ it "returns true" do
733
+ expect(subject).to be true
734
+ end
735
+ end
736
+ end
737
+ end
738
+
739
+ describe "#store_events" do
740
+ context "create" do
741
+ context "user has one store credit" do
742
+ let(:store_credit_amount) { 100.0 }
743
+
744
+ subject { create(:store_credit, amount: store_credit_amount) }
745
+
746
+ it "creates a store credit event" do
747
+ expect { subject }.to change { Spree::StoreCreditEvent.count }.by(1)
748
+ end
749
+
750
+ it "makes the store credit event an allocation event" do
751
+ expect(subject.store_credit_events.first.action).to eq Spree::StoreCredit::ALLOCATION_ACTION
752
+ end
753
+
754
+ it "saves the user's total store credit in the event" do
755
+ expect(subject.store_credit_events.first.user_total_amount).to eq store_credit_amount
756
+ end
757
+ end
758
+
759
+ context "user has multiple store credits" do
760
+ let(:store_credit_amount) { 100.0 }
761
+ let(:additional_store_credit_amount) { 200.0 }
762
+
763
+ let(:user) { create(:user) }
764
+ let!(:store_credit) { create(:store_credit, user: user, amount: store_credit_amount) }
765
+
766
+ subject { create(:store_credit, user: user, amount: additional_store_credit_amount) }
767
+
768
+ it "saves the user's total store credit in the event" do
769
+ expect(subject.store_credit_events.first.user_total_amount).to eq (store_credit_amount + additional_store_credit_amount)
770
+ end
771
+ end
772
+
773
+ context "an action is specified" do
774
+ it "creates an event with the set action" do
775
+ store_credit = build(:store_credit)
776
+ store_credit.action = Spree::StoreCredit::VOID_ACTION
777
+ store_credit.action_authorization_code = "1-SC-TEST"
778
+
779
+ expect { store_credit.save! }.to change { Spree::StoreCreditEvent.where(action: Spree::StoreCredit::VOID_ACTION).count }.by(1)
780
+ end
781
+ end
782
+ end
783
+ end
784
+ end
785
+
786
+ describe "#update_amount" do
787
+ let(:invalidation_user) { create(:user) }
788
+ let(:invalidation_reason) { create(:store_credit_update_reason) }
789
+
790
+ subject { store_credit.update_amount(amount, invalidation_reason, invalidation_user) }
791
+
792
+ context "amount is valid" do
793
+ let(:amount) { 10.0 }
794
+
795
+ before { store_credit.update_attributes!(amount: 30.0) }
796
+
797
+ it "returns true" do
798
+ expect(subject).to eq true
799
+ end
800
+
801
+ it "creates an adjustment store credit event" do
802
+ expect { subject }.to change { store_credit.store_credit_events.where(action: Spree::StoreCredit::ADJUSTMENT_ACTION).count }.from(0).to(1)
803
+ end
804
+
805
+ it "sets the adjustment amount on the store credit event correctly" do
806
+ subject
807
+ expect(store_credit.store_credit_events.find_by(action: Spree::StoreCredit::ADJUSTMENT_ACTION).amount).to eq -20
808
+ end
809
+
810
+ it "sets the originator on the store credit event correctly" do
811
+ subject
812
+ expect(store_credit.store_credit_events.find_by(action: Spree::StoreCredit::ADJUSTMENT_ACTION).originator).to eq invalidation_user
813
+ end
814
+ end
815
+
816
+ context "amount is invalid" do
817
+ let(:amount) { -10.0 }
818
+
819
+ it "returns false" do
820
+ expect(subject).to eq false
821
+ end
822
+
823
+ it "doesn't create an adjustment store credit event" do
824
+ expect { subject }.to_not change { store_credit.store_credit_events.where(action: Spree::StoreCredit::ADJUSTMENT_ACTION).count }
825
+ end
826
+ end
827
+ end
828
+
829
+ describe "#invalidate" do
830
+ let(:invalidation_user) { create(:user) }
831
+ let(:invalidation_reason) { create(:store_credit_update_reason) }
832
+
833
+ before do
834
+ store_credit.save!
835
+ end
836
+
837
+ subject { store_credit.invalidate(invalidation_reason, invalidation_user) }
838
+
839
+ it "sets the invalidated_at field to the current time" do
840
+ invalidated_at = Time.now
841
+ Timecop.freeze(invalidated_at) do
842
+ subject
843
+ expect(store_credit.invalidated_at).to eq invalidated_at
844
+ end
845
+ end
846
+
847
+ context "there is an uncaptured authorization" do
848
+ before { store_credit.authorize(5.0, "USD") }
849
+ it "prevents invalidation" do
850
+ expect { subject }.to_not change { store_credit.reload.invalidated_at }
851
+ expect(store_credit.errors[:invalidated_at].join).to match /uncaptured authorization/
852
+ end
853
+ end
854
+
855
+ context "there is a captured authorization" do
856
+ before do
857
+ auth_code = store_credit.authorize(5.0, "USD")
858
+ store_credit.capture(5.0, auth_code, "USD")
859
+ end
860
+
861
+ it "can invalidate the rest of the store credit" do
862
+ expect { subject }.to change { store_credit.reload.invalidated_at }
863
+ expect(store_credit.errors).to be_blank
864
+ end
865
+
866
+ it "creates a store credit event for the invalidation" do
867
+ expect { subject }.to change { store_credit.store_credit_events.where(action: Spree::StoreCredit::INVALIDATE_ACTION).count }.from(0).to(1)
868
+ end
869
+
870
+ it "assigns the originator as the user that is performing the invalidation" do
871
+ subject
872
+ expect(store_credit.store_credit_events.find_by(action: Spree::StoreCredit::INVALIDATE_ACTION).originator).to eq invalidation_user
873
+ end
874
+ end
875
+ end
876
+ end