spree_core 3.3.0.rc1 → 3.3.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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