spree_core 3.2.1 → 3.2.2

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