From 1d5ec6b8d2b5697d875c022fe24c74c9949c14a2 Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 20 Oct 2023 13:41:21 +1100 Subject: [PATCH] Spec for updating products with variants Trying to cover it more comprehensively, and revealing we have a lot of behaviour to update. Products and their variants should always get saved (or not saved) together. This is considered the most intuitive behaviour. There's still duplication with the "variant has error" context, but I try to avoid nesting shared_examples, it starts to get ugly. Happy to discuss though. --- spec/services/sets/product_set_spec.rb | 110 ++++++++++++++++++++----- 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/spec/services/sets/product_set_spec.rb b/spec/services/sets/product_set_spec.rb index bfdc8db97f..cbb71f6271 100644 --- a/spec/services/sets/product_set_spec.rb +++ b/spec/services/sets/product_set_spec.rb @@ -129,32 +129,102 @@ describe Sets::ProductSet do end end - describe "updating variants" do - let!(:product) { create(:simple_product) } - let(:collection_hash) { { 0 => { id: product.id } } } + describe "updating a product's variants" do + let(:product) { create(:simple_product) } + let(:variant) { product.variants.first } + let(:product_attributes) { {} } + let(:variant_attributes) { { sku: "var_sku" } } + let(:variants_attributes) { [{ **variant_attributes, id: product.variants.first.id.to_s }] } + let(:collection_hash) { + { + 0 => { id: product.id, **product_attributes, variants_attributes: } + } + } - context 'when :variants_attributes are passed' do - let(:variants_attributes) { [{ sku: '123', id: product.variants.first.id.to_s }] } + it "updates the variant" do + expect { + product_set.save + variant.reload + }.to change { variant.sku }.to("var_sku") + end - before { collection_hash[0][:variants_attributes] = variants_attributes } - - it 'updates the attributes of the variant' do + shared_examples "nothing saved" do + it "doesn't update product" do expect { - expect(product_set.save).to eq true - }.to change { product.variants.first.sku }.to("123") - - expect(product_set.invalid.count).to eq 0 + product_set.save + product.reload + }.to_not change { product.sku } end - context 'and when product attributes are also passed' do - it 'updates product and variant attributes' do - collection_hash[0][:sku] = "test_sku" + it "doesn't update variant" do + expect { + product_set.save + variant.reload + }.to_not change { variant.sku } + end - expect { - product_set.save - product.reload - }.to change { product.sku }.to("test_sku") - .and change { product.variants.first.sku }.to("123") + it 'assigns the in-memory attributes of the variant' do + pending + expect { + product_set.save + }.to change { variant.sku }.to("123") + end + end + + xcontext "variant has error" do + let(:variant_attributes) { { sku: "var_sku", display_name: "A" * 256 } } # maximum length + + include_examples "nothing saved" + end + + context "when products attributes are also updated" do + let(:product_attributes) { + { sku: "prod_sku" } + } + + it "updates product and variant" do + expect { + product_set.save + product.reload + }.to change { product.sku }.to("prod_sku") + .and change { product.variants.first.sku }.to("var_sku") + end + + xcontext "variant has error" do + let(:variant_attributes) { { sku: "var_sku", display_name: "A" * 256 } } # maximum length + + include_examples "nothing saved" + end + + context "product has error" do + before { collection_hash[0][:name] = "" } # product.name can't be blank + + include_examples "nothing saved" + end + end + + context "when multiple variants are updated" do + let(:variant2) { create(:variant, product:) } + let(:variants_attributes) { + [ + { **variant_attributes, id: product.variants.first.id.to_s }, + { sku: "var_sku2", id: variant2.id.to_s }, + ] + } + + it "updates each variant" do + expect { + product_set.save + variant2.reload + }.to change { product.variants.first.sku }.to("var_sku") + .and change { variant2.sku }.to("var_sku2") + end + + xcontext "variant has error" do + let(:variant_attributes) { { sku: "var_sku", display_name: "A" * 256 } } # maximum length + + include_examples "nothing saved" do + after { expect(variant2.reload.sku).to_not eq "var_sku2" } end end end