spree_core 3.3.0.rc1 → 3.3.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/base_helper.rb +1 -1
  3. data/app/mailers/spree/base_mailer.rb +5 -0
  4. data/app/models/spree/ability.rb +4 -1
  5. data/app/models/spree/image.rb +6 -2
  6. data/app/models/spree/order.rb +10 -9
  7. data/app/models/spree/order/payments.rb +1 -1
  8. data/app/models/spree/payment_method/store_credit.rb +4 -0
  9. data/app/models/spree/shipment.rb +2 -0
  10. data/app/views/spree/shared/_base_mailer_header.html.erb +5 -1
  11. data/app/views/spree/shared/_mailer_line_item.html.erb +5 -1
  12. data/config/routes.rb +0 -3
  13. data/lib/spree/core/components.rb +17 -0
  14. data/lib/spree/core/controller_helpers/auth.rb +3 -1
  15. data/lib/spree/core/engine.rb +1 -0
  16. data/lib/spree/core/validators/email.rb +1 -5
  17. data/lib/spree/core/version.rb +1 -1
  18. data/spree_core.gemspec +1 -1
  19. metadata +4 -204
  20. data/lib/spree/testing_support/shoulda_matcher_configuration.rb +0 -6
  21. data/spec/fixtures/thinking-cat.jpg +0 -0
  22. data/spec/helpers/base_helper_spec.rb +0 -200
  23. data/spec/helpers/products_helper_spec.rb +0 -289
  24. data/spec/lib/calculated_adjustments_spec.rb +0 -7
  25. data/spec/lib/i18n_spec.rb +0 -123
  26. data/spec/lib/search/base_spec.rb +0 -86
  27. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +0 -103
  28. data/spec/lib/spree/core/controller_helpers/order_spec.rb +0 -110
  29. data/spec/lib/spree/core/controller_helpers/search_spec.rb +0 -17
  30. data/spec/lib/spree/core/controller_helpers/store_spec.rb +0 -72
  31. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +0 -39
  32. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +0 -22
  33. data/spec/lib/spree/core/importer/order_spec.rb +0 -607
  34. data/spec/lib/spree/core/number_generator_spec.rb +0 -139
  35. data/spec/lib/spree/core/token_generator_spec.rb +0 -24
  36. data/spec/lib/spree/core/validators/email_spec.rb +0 -54
  37. data/spec/lib/spree/core_spec.rb +0 -23
  38. data/spec/lib/spree/localized_number_spec.rb +0 -54
  39. data/spec/lib/spree/migrations_spec.rb +0 -36
  40. data/spec/lib/spree/money_spec.rb +0 -122
  41. data/spec/lib/tasks/exchanges_spec.rb +0 -136
  42. data/spec/mailers/order_mailer_spec.rb +0 -122
  43. data/spec/mailers/reimbursement_mailer_spec.rb +0 -52
  44. data/spec/mailers/shipment_mailer_spec.rb +0 -81
  45. data/spec/mailers/test_mailer_spec.rb +0 -38
  46. data/spec/models/spree/ability_spec.rb +0 -251
  47. data/spec/models/spree/address_spec.rb +0 -402
  48. data/spec/models/spree/adjustable/adjuster/base_spec.rb +0 -10
  49. data/spec/models/spree/adjustable/adjuster/promotion_spec.rb +0 -211
  50. data/spec/models/spree/adjustable/adjuster/tax_spec.rb +0 -86
  51. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +0 -26
  52. data/spec/models/spree/adjustment_spec.rb +0 -189
  53. data/spec/models/spree/app_configuration_spec.rb +0 -26
  54. data/spec/models/spree/asset_spec.rb +0 -28
  55. data/spec/models/spree/calculator/default_tax_spec.rb +0 -152
  56. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +0 -25
  57. data/spec/models/spree/calculator/flat_rate_spec.rb +0 -47
  58. data/spec/models/spree/calculator/flexi_rate_spec.rb +0 -41
  59. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +0 -15
  60. data/spec/models/spree/calculator/price_sack_spec.rb +0 -30
  61. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +0 -47
  62. data/spec/models/spree/calculator/shipping.rb +0 -8
  63. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +0 -23
  64. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +0 -13
  65. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +0 -52
  66. data/spec/models/spree/calculator/shipping/per_item_spec.rb +0 -20
  67. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +0 -29
  68. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +0 -40
  69. data/spec/models/spree/calculator/tiered_percent_spec.rb +0 -51
  70. data/spec/models/spree/calculator_spec.rb +0 -69
  71. data/spec/models/spree/classification_spec.rb +0 -93
  72. data/spec/models/spree/concerns/display_money_spec.rb +0 -43
  73. data/spec/models/spree/concerns/user_methods_spec.rb +0 -82
  74. data/spec/models/spree/concerns/vat_price_calculation_spec.rb +0 -66
  75. data/spec/models/spree/country_spec.rb +0 -55
  76. data/spec/models/spree/credit_card_spec.rb +0 -328
  77. data/spec/models/spree/customer_return_spec.rb +0 -240
  78. data/spec/models/spree/exchange_spec.rb +0 -75
  79. data/spec/models/spree/gateway/bogus_simple.rb +0 -20
  80. data/spec/models/spree/gateway/bogus_spec.rb +0 -13
  81. data/spec/models/spree/gateway_spec.rb +0 -61
  82. data/spec/models/spree/image_spec.rb +0 -8
  83. data/spec/models/spree/inventory_unit_spec.rb +0 -256
  84. data/spec/models/spree/line_item_spec.rb +0 -348
  85. data/spec/models/spree/option_type_prototype_spec.rb +0 -9
  86. data/spec/models/spree/option_type_spec.rb +0 -14
  87. data/spec/models/spree/option_value_spec.rb +0 -18
  88. data/spec/models/spree/order/address_spec.rb +0 -50
  89. data/spec/models/spree/order/adjustments_spec.rb +0 -29
  90. data/spec/models/spree/order/callbacks_spec.rb +0 -42
  91. data/spec/models/spree/order/checkout_spec.rb +0 -770
  92. data/spec/models/spree/order/currency_updater_spec.rb +0 -32
  93. data/spec/models/spree/order/finalizing_spec.rb +0 -114
  94. data/spec/models/spree/order/helpers_spec.rb +0 -5
  95. data/spec/models/spree/order/payment_spec.rb +0 -214
  96. data/spec/models/spree/order/risk_assessment_spec.rb +0 -84
  97. data/spec/models/spree/order/shipments_spec.rb +0 -43
  98. data/spec/models/spree/order/state_machine_spec.rb +0 -212
  99. data/spec/models/spree/order/store_credit_spec.rb +0 -457
  100. data/spec/models/spree/order/tax_spec.rb +0 -84
  101. data/spec/models/spree/order/totals_spec.rb +0 -24
  102. data/spec/models/spree/order/updating_spec.rb +0 -18
  103. data/spec/models/spree/order/validations_spec.rb +0 -15
  104. data/spec/models/spree/order_contents_spec.rb +0 -332
  105. data/spec/models/spree/order_inventory_spec.rb +0 -247
  106. data/spec/models/spree/order_merger_spec.rb +0 -135
  107. data/spec/models/spree/order_spec.rb +0 -1067
  108. data/spec/models/spree/order_updater_spec.rb +0 -305
  109. data/spec/models/spree/payment/gateway_options_spec.rb +0 -127
  110. data/spec/models/spree/payment/store_credit_spec.rb +0 -60
  111. data/spec/models/spree/payment_method/store_credit_spec.rb +0 -291
  112. data/spec/models/spree/payment_method_spec.rb +0 -108
  113. data/spec/models/spree/payment_spec.rb +0 -922
  114. data/spec/models/spree/preference_spec.rb +0 -80
  115. data/spec/models/spree/preferences/configuration_spec.rb +0 -30
  116. data/spec/models/spree/preferences/preferable_spec.rb +0 -344
  117. data/spec/models/spree/preferences/scoped_store_spec.rb +0 -58
  118. data/spec/models/spree/preferences/store_spec.rb +0 -46
  119. data/spec/models/spree/price_spec.rb +0 -128
  120. data/spec/models/spree/product/scopes_spec.rb +0 -174
  121. data/spec/models/spree/product_duplicator_spec.rb +0 -102
  122. data/spec/models/spree/product_filter_spec.rb +0 -26
  123. data/spec/models/spree/product_option_type_spec.rb +0 -9
  124. data/spec/models/spree/product_promotion_rule_spec.rb +0 -9
  125. data/spec/models/spree/product_property_spec.rb +0 -26
  126. data/spec/models/spree/product_spec.rb +0 -626
  127. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +0 -113
  128. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +0 -148
  129. data/spec/models/spree/promotion/actions/create_line_items_spec.rb +0 -86
  130. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +0 -36
  131. data/spec/models/spree/promotion/rules/country_spec.rb +0 -36
  132. data/spec/models/spree/promotion/rules/first_order_spec.rb +0 -75
  133. data/spec/models/spree/promotion/rules/item_total_spec.rb +0 -282
  134. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +0 -42
  135. data/spec/models/spree/promotion/rules/option_value_spec.rb +0 -90
  136. data/spec/models/spree/promotion/rules/product_spec.rb +0 -143
  137. data/spec/models/spree/promotion/rules/taxon_spec.rb +0 -102
  138. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +0 -27
  139. data/spec/models/spree/promotion/rules/user_spec.rb +0 -45
  140. data/spec/models/spree/promotion_action_spec.rb +0 -10
  141. data/spec/models/spree/promotion_category_spec.rb +0 -17
  142. data/spec/models/spree/promotion_handler/cart_spec.rb +0 -102
  143. data/spec/models/spree/promotion_handler/coupon_spec.rb +0 -323
  144. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +0 -48
  145. data/spec/models/spree/promotion_handler/page_spec.rb +0 -44
  146. data/spec/models/spree/promotion_rule_spec.rb +0 -29
  147. data/spec/models/spree/promotion_rule_taxon_spec.rb +0 -9
  148. data/spec/models/spree/promotion_rule_user_spec.rb +0 -9
  149. data/spec/models/spree/promotion_spec.rb +0 -674
  150. data/spec/models/spree/property_prototype_spec.rb +0 -9
  151. data/spec/models/spree/property_spec.rb +0 -5
  152. data/spec/models/spree/prototype_spec.rb +0 -5
  153. data/spec/models/spree/prototype_taxon_spec.rb +0 -9
  154. data/spec/models/spree/refund_reason_spec.rb +0 -20
  155. data/spec/models/spree/refund_spec.rb +0 -195
  156. data/spec/models/spree/reimbursement/credit_spec.rb +0 -36
  157. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +0 -140
  158. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +0 -83
  159. data/spec/models/spree/reimbursement_performer_spec.rb +0 -30
  160. data/spec/models/spree/reimbursement_spec.rb +0 -188
  161. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +0 -63
  162. data/spec/models/spree/reimbursement_type/credit_spec.rb +0 -53
  163. data/spec/models/spree/reimbursement_type/exchange_spec.rb +0 -46
  164. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +0 -55
  165. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +0 -101
  166. data/spec/models/spree/return_authorization_reason_spec.rb +0 -7
  167. data/spec/models/spree/return_authorization_spec.rb +0 -230
  168. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +0 -77
  169. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +0 -58
  170. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +0 -61
  171. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +0 -32
  172. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +0 -29
  173. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +0 -35
  174. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +0 -65
  175. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +0 -43
  176. data/spec/models/spree/return_item_spec.rb +0 -734
  177. data/spec/models/spree/returns_calculator_spec.rb +0 -14
  178. data/spec/models/spree/role_spec.rb +0 -7
  179. data/spec/models/spree/shipment_spec.rb +0 -744
  180. data/spec/models/spree/shipping_calculator_spec.rb +0 -45
  181. data/spec/models/spree/shipping_category_spec.rb +0 -19
  182. data/spec/models/spree/shipping_method_spec.rb +0 -125
  183. data/spec/models/spree/shipping_rate_spec.rb +0 -140
  184. data/spec/models/spree/state_spec.rb +0 -29
  185. data/spec/models/spree/stock/availability_validator_spec.rb +0 -42
  186. data/spec/models/spree/stock/content_item_spec.rb +0 -31
  187. data/spec/models/spree/stock/coordinator_spec.rb +0 -61
  188. data/spec/models/spree/stock/differentiator_spec.rb +0 -39
  189. data/spec/models/spree/stock/estimator_spec.rb +0 -202
  190. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +0 -37
  191. data/spec/models/spree/stock/package_spec.rb +0 -182
  192. data/spec/models/spree/stock/packer_spec.rb +0 -70
  193. data/spec/models/spree/stock/prioritizer_spec.rb +0 -125
  194. data/spec/models/spree/stock/quantifier_spec.rb +0 -126
  195. data/spec/models/spree/stock/splitter/backordered_spec.rb +0 -29
  196. data/spec/models/spree/stock/splitter/base_spec.rb +0 -21
  197. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +0 -47
  198. data/spec/models/spree/stock/splitter/weight_spec.rb +0 -32
  199. data/spec/models/spree/stock_item_spec.rb +0 -465
  200. data/spec/models/spree/stock_location_spec.rb +0 -243
  201. data/spec/models/spree/stock_movement_spec.rb +0 -120
  202. data/spec/models/spree/stock_transfer_spec.rb +0 -50
  203. data/spec/models/spree/store_credit_event_spec.rb +0 -101
  204. data/spec/models/spree/store_credit_spec.rb +0 -798
  205. data/spec/models/spree/store_spec.rb +0 -78
  206. data/spec/models/spree/tax_category_spec.rb +0 -32
  207. data/spec/models/spree/tax_rate_spec.rb +0 -561
  208. data/spec/models/spree/taxon_spec.rb +0 -93
  209. data/spec/models/spree/taxonomy_spec.rb +0 -18
  210. data/spec/models/spree/tracker_spec.rb +0 -21
  211. data/spec/models/spree/user_spec.rb +0 -203
  212. data/spec/models/spree/variant_spec.rb +0 -818
  213. data/spec/models/spree/zone_member_spec.rb +0 -38
  214. data/spec/models/spree/zone_spec.rb +0 -472
  215. data/spec/spec_helper.rb +0 -82
  216. data/spec/support/big_decimal.rb +0 -5
  217. data/spec/support/concerns/adjustment_source.rb +0 -23
  218. data/spec/support/concerns/default_price.rb +0 -37
  219. data/spec/support/rake.rb +0 -13
  220. data/spec/support/test_gateway.rb +0 -2
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
- require 'spree/core/product_filters'
3
-
4
- describe 'product filters', type: :model do
5
- # Regression test for #1709
6
- context 'finds products filtered by brand' do
7
- let(:product) { create(:product) }
8
- before do
9
- property = Spree::Property.create!(name: "brand", presentation: "brand")
10
- product.set_property("brand", "Nike")
11
- end
12
-
13
- it "does not attempt to call value method on Arel::Table" do
14
- expect { Spree::Core::ProductFilters.brand_filter }.not_to raise_error
15
- end
16
-
17
- it "can find products in the 'Nike' brand" do
18
- expect(Spree::Product.brand_any("Nike")).to include(product)
19
- end
20
- it "sorts products without brand specified" do
21
- product.set_property("brand", "Nike")
22
- create(:product).set_property("brand", nil)
23
- expect { Spree::Core::ProductFilters.brand_filter[:labels] }.not_to raise_error
24
- end
25
- end
26
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Spree::ProductOptionType do
4
- describe 'Validations' do
5
- it { is_expected.to validate_presence_of(:product) }
6
- it { is_expected.to validate_presence_of(:option_type) }
7
- it { is_expected.to validate_uniqueness_of(:product_id).scoped_to(:option_type_id).allow_nil }
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Spree::ProductPromotionRule do
4
- describe 'Validations' do
5
- it { is_expected.to validate_presence_of(:product) }
6
- it { is_expected.to validate_presence_of(:promotion_rule) }
7
- it { is_expected.to validate_uniqueness_of(:product_id).scoped_to(:promotion_rule_id).allow_nil }
8
- end
9
- end
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Spree::ProductProperty, type: :model do
4
- context "touching" do
5
- it "should update product" do
6
- pp = create(:product_property)
7
- expect(pp.product).to receive(:touch)
8
- pp.touch
9
- end
10
- end
11
-
12
- context 'property_name=' do
13
- before do
14
- @pp = create(:product_property)
15
- end
16
-
17
- it "should assign property" do
18
- @pp.property_name = "Size"
19
- expect(@pp.property.name).to eq('Size')
20
- end
21
- end
22
-
23
- context 'ransackable_associations' do
24
- it { expect(Spree::ProductProperty.whitelisted_ransackable_associations).to include('property') }
25
- end
26
- end
@@ -1,626 +0,0 @@
1
- # coding: UTF-8
2
-
3
- require 'spec_helper'
4
-
5
- module ThirdParty
6
- class Extension < Spree::Base
7
- # nasty hack so we don't have to create a table to back this fake model
8
- self.table_name = 'spree_products'
9
- end
10
- end
11
-
12
- describe Spree::Product, type: :model do
13
-
14
- describe 'Associations' do
15
- it 'should have many promotions' do
16
- is_expected.to have_many(:promotions).
17
- class_name('Spree::Promotion').through(:promotion_rules)
18
- end
19
-
20
- it 'should have many possible_promotions' do
21
- is_expected.to have_many(:possible_promotions).
22
- class_name('Spree::Promotion').through(:promotion_rules).source(:promotion)
23
- end
24
-
25
- it do
26
- is_expected.to have_many(:variants).
27
- class_name('Spree::Variant').
28
- inverse_of(:product).
29
- conditions(is_master: false).
30
- order(:position)
31
- end
32
-
33
- it do
34
- is_expected.to have_many(:variants_including_master).
35
- class_name('Spree::Variant').
36
- inverse_of(:product).
37
- order(:position)
38
- end
39
- end
40
-
41
- context 'product instance' do
42
- let(:product) { create(:product) }
43
- let(:variant) { create(:variant, product: product) }
44
-
45
- context '#duplicate' do
46
- before do
47
- allow(product).to receive_messages taxons: [create(:taxon)]
48
- end
49
-
50
- it 'duplicates product' do
51
- clone = product.duplicate
52
- expect(clone.name).to eq('COPY OF ' + product.name)
53
- expect(clone.master.sku).to eq('COPY OF ' + product.master.sku)
54
- expect(clone.taxons).to eq(product.taxons)
55
- expect(clone.images.size).to eq(product.images.size)
56
- end
57
-
58
- it 'calls #duplicate_extra' do
59
- expect_any_instance_of(Spree::Product).to receive(:duplicate_extra)
60
- .with(product)
61
- expect(product).to_not receive(:duplicate_extra)
62
- product.duplicate
63
- end
64
- end
65
-
66
- context "master variant" do
67
-
68
- context "when master variant changed" do
69
- before do
70
- product.master.sku = "Something changed"
71
- end
72
-
73
- it "saves the master" do
74
- expect(product.master).to receive(:save!)
75
- product.save
76
- end
77
- end
78
-
79
- context "when master default price changed" do
80
- before do
81
- master = product.master
82
- master.default_price.price = 11
83
- master.save!
84
- product.master.default_price.price = 12
85
- end
86
-
87
- it "saves the master" do
88
- expect(product.master).to receive(:save!)
89
- product.save
90
- end
91
-
92
- it "saves the default price" do
93
- expect(product.master.default_price).to receive(:save)
94
- product.save
95
- end
96
- end
97
-
98
- context "when master variant and price haven't changed" do
99
- it "does not save the master" do
100
- expect(product.master).not_to receive(:save!)
101
- product.save
102
- end
103
- end
104
- end
105
-
106
- context "product has no variants" do
107
- context "#destroy" do
108
- it "should set deleted_at value" do
109
- product.destroy
110
- expect(product.deleted_at).not_to be_nil
111
- expect(product.master.reload.deleted_at).not_to be_nil
112
- end
113
- end
114
- end
115
-
116
- context "product has variants" do
117
- before do
118
- create(:variant, product: product)
119
- end
120
-
121
- context "#destroy" do
122
- it "should set deleted_at value" do
123
- product.destroy
124
- expect(product.deleted_at).not_to be_nil
125
- expect(product.variants_including_master.all? { |v| !v.deleted_at.nil? }).to be true
126
- end
127
- end
128
- end
129
-
130
- context "#price" do
131
- # Regression test for #1173
132
- it 'strips non-price characters' do
133
- product.price = "$10"
134
- expect(product.price).to eq(10.0)
135
- end
136
- end
137
-
138
- context "#display_price" do
139
- before { product.price = 10.55 }
140
-
141
- it "shows the amount" do
142
- expect(product.display_price.to_s).to eq("$10.55")
143
- end
144
-
145
- context "with currency set to JPY" do
146
- before do
147
- product.master.default_price.currency = 'JPY'
148
- product.master.default_price.save!
149
- Spree::Config[:currency] = 'JPY'
150
- end
151
-
152
- it "displays the currency in yen" do
153
- expect(product.display_price.to_s).to eq("¥11")
154
- end
155
- end
156
- end
157
-
158
- context "#available?" do
159
- it "should be available if date is in the past" do
160
- product.available_on = 1.day.ago
161
- expect(product).to be_available
162
- end
163
-
164
- it "should not be available if date is nil or in the future" do
165
- product.available_on = nil
166
- expect(product).not_to be_available
167
-
168
- product.available_on = 1.day.from_now
169
- expect(product).not_to be_available
170
- end
171
-
172
- it "should not be available if destroyed" do
173
- product.destroy
174
- expect(product).not_to be_available
175
- end
176
- end
177
-
178
- context "#can_supply?" do
179
- it "should be true" do
180
- expect(product.can_supply?).to be(true)
181
- end
182
-
183
- it "should be false" do
184
- product.variants_including_master.each { |v| v.stock_items.update_all count_on_hand: 0, backorderable: false }
185
- expect(product.can_supply?).to be(false)
186
- end
187
- end
188
-
189
- context "variants_and_option_values" do
190
- let!(:high) { create(:variant, product: product) }
191
- let!(:low) { create(:variant, product: product) }
192
-
193
- before { high.option_values.destroy_all }
194
-
195
- it "returns only variants with option values" do
196
- expect(product.variants_and_option_values).to eq([low])
197
- end
198
- end
199
-
200
- context "has stock movements" do
201
- let(:variant) { product.master }
202
- let(:stock_item) { variant.stock_items.first }
203
-
204
- it "doesnt raise ReadOnlyRecord error" do
205
- Spree::StockMovement.create!(stock_item: stock_item, quantity: 1)
206
- expect { product.destroy }.not_to raise_error
207
- end
208
- end
209
-
210
- # Regression test for #3737
211
- context "has stock items" do
212
- it "can retrieve stock items" do
213
- expect(product.master.stock_items.first).not_to be_nil
214
- expect(product.stock_items.first).not_to be_nil
215
- end
216
- end
217
-
218
- context "slugs" do
219
-
220
- it "normalizes slug on update validation" do
221
- product.slug = "hey//joe"
222
- product.valid?
223
- expect(product.slug).not_to match "/"
224
- end
225
-
226
- it "stores old slugs in FriendlyIds history" do
227
- expect(product).to receive(:create_slug)
228
- # Set it, otherwise the create_slug method avoids writing a new one
229
- product.slug = "custom-slug"
230
- product.run_callbacks :save
231
- end
232
-
233
- context "when product destroyed" do
234
-
235
- it "renames slug" do
236
- expect { product.destroy }.to change { product.slug }
237
- end
238
-
239
- context "when slug is already at or near max length" do
240
-
241
- before do
242
- product.slug = "x" * 255
243
- product.save!
244
- end
245
-
246
- it "truncates renamed slug to ensure it remains within length limit" do
247
- product.destroy
248
- expect(product.slug.length).to eq 255
249
- end
250
-
251
- end
252
-
253
- end
254
-
255
- it "validates slug uniqueness" do
256
- existing_product = product
257
- new_product = create(:product)
258
- new_product.slug = existing_product.slug
259
-
260
- expect(new_product.valid?).to eq false
261
- end
262
-
263
- it "falls back to 'name-sku' for slug if regular name-based slug already in use" do
264
- product1 = build(:product)
265
- product1.name = "test"
266
- product1.sku = "123"
267
- product1.save!
268
-
269
- product2 = build(:product)
270
- product2.name = "test"
271
- product2.sku = "456"
272
- product2.save!
273
-
274
- expect(product2.slug).to eq 'test-456'
275
- end
276
- end
277
-
278
- describe "#discontinue_on_must_be_later_than_available_on" do
279
- before { product.available_on = Date.today }
280
-
281
- context "available_on is a date earlier than discontinue_on" do
282
- before { product.discontinue_on = 5.days.from_now }
283
-
284
- it "is valid" do
285
- expect(product).to be_valid
286
- end
287
- end
288
-
289
- context "available_on is a date earlier than discontinue_on" do
290
- before { product.discontinue_on = 5.days.ago }
291
-
292
- context "is not valid" do
293
- before { product.valid? }
294
-
295
- it { expect(product).not_to be_valid }
296
- it { expect(product.errors[:discontinue_on]).to include(I18n.t(:invalid_date_range, scope: 'activerecord.errors.models.spree/product.attributes.discontinue_on')) }
297
- end
298
- end
299
-
300
- context "available_on and discontinue_on are nil" do
301
- before do
302
- product.discontinue_on = nil
303
- product.available_on = nil
304
- end
305
-
306
- it "is valid" do
307
- expect(product).to be_valid
308
- end
309
- end
310
- end
311
-
312
- context "hard deletion" do
313
- it "doesnt raise ActiveRecordError error" do
314
- expect { product.really_destroy! }.to_not raise_error
315
- end
316
- end
317
-
318
- context 'history' do
319
- before(:each) do
320
- @product = create(:product)
321
- end
322
-
323
- it 'should keep the history when the product is destroyed' do
324
- @product.destroy
325
-
326
- expect(@product.slugs.with_deleted).to_not be_empty
327
- end
328
-
329
- it 'should update the history when the product is restored' do
330
- @product.destroy
331
-
332
- @product.restore(recursive: true)
333
-
334
- latest_slug = @product.slugs.find_by slug: @product.slug
335
- expect(latest_slug).to_not be_nil
336
- end
337
- end
338
- end
339
-
340
- context "properties" do
341
- let(:product) { create(:product) }
342
-
343
- it "should properly assign properties" do
344
- product.set_property('the_prop', 'value1')
345
- expect(product.property('the_prop')).to eq('value1')
346
-
347
- product.set_property('the_prop', 'value2')
348
- expect(product.property('the_prop')).to eq('value2')
349
- end
350
-
351
- it "should not create duplicate properties when set_property is called" do
352
- expect {
353
- product.set_property('the_prop', 'value2')
354
- product.save
355
- product.reload
356
- }.not_to change(product.properties, :length)
357
-
358
- expect {
359
- product.set_property('the_prop_new', 'value')
360
- product.save
361
- product.reload
362
- expect(product.property('the_prop_new')).to eq('value')
363
- }.to change { product.properties.length }.by(1)
364
- end
365
-
366
- context 'optional property_presentation' do
367
- subject { Spree::Property.where(name: 'foo').first.presentation }
368
- let(:name) { 'foo' }
369
- let(:presentation) { 'baz' }
370
-
371
- describe 'is not used' do
372
- before { product.set_property(name, 'bar') }
373
- it { is_expected.to eq name }
374
- end
375
-
376
- describe 'is used' do
377
- before { product.set_property(name, 'bar', presentation) }
378
- it { is_expected.to eq presentation }
379
- end
380
- end
381
-
382
- # Regression test for #2455
383
- it "should not overwrite properties' presentation names" do
384
- Spree::Property.where(name: 'foo').first_or_create!(presentation: "Foo's Presentation Name")
385
- product.set_property('foo', 'value1')
386
- product.set_property('bar', 'value2')
387
- expect(Spree::Property.where(name: 'foo').first.presentation).to eq("Foo's Presentation Name")
388
- expect(Spree::Property.where(name: 'bar').first.presentation).to eq("bar")
389
- end
390
-
391
- # Regression test for #4416
392
- context "#possible_promotions" do
393
- let!(:possible_promotion) { create(:promotion, advertise: true, starts_at: 1.day.ago) }
394
- let!(:unadvertised_promotion) { create(:promotion, advertise: false, starts_at: 1.day.ago) }
395
- let!(:inactive_promotion) { create(:promotion, advertise: true, starts_at: 1.day.since) }
396
-
397
- before do
398
- product.promotion_rules.create!(promotion: possible_promotion)
399
- product.promotion_rules.create!(promotion: unadvertised_promotion)
400
- product.promotion_rules.create!(promotion: inactive_promotion)
401
- end
402
-
403
- it "lists the promotion as a possible promotion" do
404
- expect(product.possible_promotions).to include(possible_promotion)
405
- expect(product.possible_promotions).to_not include(unadvertised_promotion)
406
- expect(product.possible_promotions).to_not include(inactive_promotion)
407
- end
408
- end
409
- end
410
-
411
- context '#create' do
412
- let!(:prototype) { create(:prototype) }
413
- let!(:product) { Spree::Product.new(name: "Foo", price: 1.99, shipping_category_id: create(:shipping_category).id) }
414
-
415
- before { product.prototype_id = prototype.id }
416
-
417
- context "when prototype is supplied" do
418
- it "should create properties based on the prototype" do
419
- product.save
420
- expect(product.properties.count).to eq(1)
421
- end
422
- end
423
-
424
- context "when prototype with option types is supplied" do
425
- def build_option_type_with_values(name, values)
426
- values.each_with_object(create :option_type, name: name) do |val, ot|
427
- ot.option_values.create(name: val.downcase, presentation: val)
428
- end
429
- end
430
-
431
- let(:prototype) do
432
- size = build_option_type_with_values("size", %w(Small Medium Large))
433
- create(:prototype, name: "Size", option_types: [ size ])
434
- end
435
-
436
- let(:option_values_hash) do
437
- hash = {}
438
- prototype.option_types.each do |i|
439
- hash[i.id.to_s] = i.option_value_ids
440
- end
441
- hash
442
- end
443
-
444
- it "should create option types based on the prototype" do
445
- product.save
446
- expect(product.option_type_ids.length).to eq(1)
447
- expect(product.option_type_ids).to eq(prototype.option_type_ids)
448
- end
449
-
450
- it "should create product option types based on the prototype" do
451
- product.save
452
- expect(product.product_option_types.pluck(:option_type_id)).to eq(prototype.option_type_ids)
453
- end
454
-
455
- it "should create variants from an option values hash with one option type" do
456
- product.option_values_hash = option_values_hash
457
- product.save
458
- expect(product.variants.length).to eq(3)
459
- end
460
-
461
- it "should still create variants when option_values_hash is given but prototype id is nil" do
462
- product.option_values_hash = option_values_hash
463
- product.prototype_id = nil
464
- product.save
465
- product.reload
466
- expect(product.option_type_ids.length).to eq(1)
467
- expect(product.option_type_ids).to eq(prototype.option_type_ids)
468
- expect(product.variants.length).to eq(3)
469
- end
470
-
471
- it "should create variants from an option values hash with multiple option types" do
472
- color = build_option_type_with_values("color", %w(Red Green Blue))
473
- logo = build_option_type_with_values("logo", %w(Ruby Rails Nginx))
474
- option_values_hash[color.id.to_s] = color.option_value_ids
475
- option_values_hash[logo.id.to_s] = logo.option_value_ids
476
- product.option_values_hash = option_values_hash
477
- product.save
478
- product.reload
479
- expect(product.option_type_ids.length).to eq(3)
480
- expect(product.variants.length).to eq(27)
481
- end
482
- end
483
- end
484
-
485
- context "#images" do
486
- let(:product) { create(:product) }
487
- let(:image) { File.open(File.expand_path('../../../fixtures/thinking-cat.jpg', __FILE__)) }
488
- let(:params) { {viewable_id: product.master.id, viewable_type: 'Spree::Variant', attachment: image, alt: "position 2", position: 2} }
489
-
490
- before do
491
- Spree::Image.create(params)
492
- Spree::Image.create(params.merge({alt: "position 1", position: 1}))
493
- Spree::Image.create(params.merge({viewable_type: 'ThirdParty::Extension', alt: "position 1", position: 2}))
494
- end
495
-
496
- it "only looks for variant images" do
497
- expect(product.images.size).to eq(2)
498
- end
499
-
500
- it "should be sorted by position" do
501
- expect(product.images.pluck(:alt)).to eq(["position 1", "position 2"])
502
- end
503
- end
504
-
505
- # Regression tests for #2352
506
- context "classifications and taxons" do
507
- it "is joined through classifications" do
508
- reflection = Spree::Product.reflect_on_association(:taxons)
509
- expect(reflection.options[:through]).to eq(:classifications)
510
- end
511
-
512
- it "will delete all classifications" do
513
- reflection = Spree::Product.reflect_on_association(:classifications)
514
- expect(reflection.options[:dependent]).to eq(:delete_all)
515
- end
516
- end
517
-
518
- context '#total_on_hand' do
519
- let(:product) { create(:product) }
520
-
521
- it 'should be infinite if track_inventory_levels is false' do
522
- Spree::Config[:track_inventory_levels] = false
523
- expect(build(:product, variants_including_master: [build(:master_variant)]).total_on_hand).to eql(Float::INFINITY)
524
- end
525
-
526
- it 'should be infinite if variant is on demand' do
527
- Spree::Config[:track_inventory_levels] = true
528
- expect(build(:product, variants_including_master: [build(:on_demand_master_variant)]).total_on_hand).to eql(Float::INFINITY)
529
- end
530
-
531
- it 'should return sum of stock items count_on_hand' do
532
- product.stock_items.first.set_count_on_hand 5
533
- product.variants_including_master.reload # force load association
534
- expect(product.total_on_hand).to eql(5)
535
- end
536
-
537
- it 'should return sum of stock items count_on_hand when variants_including_master is not loaded' do
538
- product.stock_items.first.set_count_on_hand 5
539
- expect(product.reload.total_on_hand).to eql(5)
540
- end
541
- end
542
-
543
- # Regression spec for https://github.com/spree/spree/issues/5588
544
- context '#validate_master when duplicate SKUs entered' do
545
- let!(:first_product) { create(:product, sku: 'a-sku') }
546
- let(:second_product) { build(:product, sku: 'a-sku') }
547
-
548
- subject { second_product }
549
- it { is_expected.to be_invalid }
550
- end
551
-
552
- it "initializes a master variant when building a product" do
553
- product = Spree::Product.new
554
- expect(product.master.is_master).to be true
555
- end
556
-
557
- context "#discontinue!" do
558
- let(:product) { create(:product, sku: 'a-sku') }
559
-
560
- it "sets the discontinued" do
561
- product.discontinue!
562
- product.reload
563
- expect(product.discontinued?).to be(true)
564
- end
565
-
566
- it "changes updated_at" do
567
- Timecop.scale(1000) do
568
- expect { product.discontinue! }.to change { product.updated_at }
569
- end
570
- end
571
- end
572
-
573
- context "#discontinued?" do
574
- let(:product_live) { build(:product, sku: "a-sku") }
575
- it "should be false" do
576
- expect(product_live.discontinued?).to be(false)
577
- end
578
-
579
- let(:product_discontinued) { build(:product, sku: "a-sku", discontinue_on: Time.now - 1.day) }
580
- it "should be true" do
581
- expect(product_discontinued.discontinued?).to be(true)
582
- end
583
- end
584
-
585
- context "acts_as_taggable" do
586
- let(:product) { create(:product) }
587
-
588
- it "should add tags" do
589
- product.tag_list.add("awesome")
590
- expect(product.tag_list).to include("awesome")
591
- end
592
-
593
- it "should remove tags" do
594
- product.tag_list.remove("awesome")
595
- expect(product.tag_list).to_not include("awesome")
596
- end
597
- end
598
-
599
- context "#brand" do
600
- let(:taxonomy) { create(:taxonomy, name: I18n.t('spree.taxonomy_brands_name')) }
601
- let(:product) { create(:product, taxons: [taxonomy.taxons.first]) }
602
-
603
- it 'should fetch Brand Taxon' do
604
- expect(product.brand).to eql(taxonomy.taxons.first)
605
- end
606
- end
607
-
608
- context "#category" do
609
- let(:taxonomy) { create(:taxonomy, name: I18n.t('spree.taxonomy_categories_name')) }
610
- let(:product) { create(:product, taxons: [taxonomy.taxons.first]) }
611
-
612
- it 'should fetch Category Taxon' do
613
- expect(product.category).to eql(taxonomy.taxons.first)
614
- end
615
- end
616
-
617
- describe '#ensure_no_line_items' do
618
- let(:product) { create(:product) }
619
- let!(:line_item) { create(:line_item, variant: product.master) }
620
-
621
- it 'should add error on product destroy' do
622
- expect(product.destroy).to eq false
623
- expect(product.errors[:base]).to include Spree.t(:cannot_destroy_if_attached_to_line_items)
624
- end
625
- end
626
- end