From bb0a6b7f8d92dc8518a107f2869fcea89778b17b Mon Sep 17 00:00:00 2001 From: cyrillefr Date: Tue, 17 Jun 2025 14:33:15 +0200 Subject: [PATCH] Style Metrics/ModuleLength in spec file --- .rubocop_todo.yml | 1 - spec/lib/reports/all_products_spec.rb | 65 +++ .../products_and_inventory_report_spec.rb | 516 ++++++++---------- 3 files changed, 288 insertions(+), 294 deletions(-) create mode 100644 spec/lib/reports/all_products_spec.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2b4eebbcfd..d344957b08 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -161,7 +161,6 @@ Metrics/ModuleLength: - 'app/models/spree/order/checkout.rb' - 'app/models/spree/payment/processing.rb' - 'lib/open_food_network/column_preference_defaults.rb' - - 'spec/lib/reports/products_and_inventory_report_spec.rb' - 'spec/lib/reports/users_and_enterprises_report_spec.rb' - 'spec/models/spree/adjustment_spec.rb' - 'spec/models/spree/credit_card_spec.rb' diff --git a/spec/lib/reports/all_products_spec.rb b/spec/lib/reports/all_products_spec.rb new file mode 100644 index 0000000000..30ca417496 --- /dev/null +++ b/spec/lib/reports/all_products_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +RSpec.describe Reporting::Reports::ProductsAndInventory::AllProducts do + let(:user) { create(:admin_user) } + let(:report) do + described_class.new user, { fields_to_hide: [] } + end + let(:variant) { create(:variant, supplier:) } + let(:supplier) { create(:supplier_enterprise) } + + it "returns headers" do + expect(report.table_headers).to eq([ + "Supplier", + "Producer Suburb", + "Product", + "Product Properties", + "Taxons", + "Variant Value", + "Price", + "Group Buy Unit Quantity", + "Amount", + "SKU", + "On Demand?", + "On Hand", + "Tax Category" + ]) + end + + it "renders 'On demand' when the product is available on demand" do + variant.on_demand = true + variant.on_hand = 15 + variant.save! + + last_row = report.table_rows.last + on_demand_column = last_row[-3] + on_hand_column = last_row[-2] + + expect(on_demand_column).to eq("Yes") + expect(on_hand_column).to eq("On demand") + end + + it "renders the on hand count when the product is not available on demand" do + variant.on_demand = false + variant.on_hand = 22 + variant.save! + + last_row = report.table_rows.last + on_demand_column = last_row[-3] + on_hand_column = last_row[-2] + + expect(on_demand_column).to eq("No") + expect(on_hand_column).to eq(22) + end + + it "renders tax category if present, otherwise none" do + variant.update!(tax_category: create(:tax_category, name: 'Test Category')) + + table_rows = report.table_rows + first_row = table_rows.first # row for default variant, as result of product creation + last_row = table_rows.last # row for the variant created/updated above + + expect(first_row.last).to eq('none') + expect(last_row.last).to eq('Test Category') + end +end diff --git a/spec/lib/reports/products_and_inventory_report_spec.rb b/spec/lib/reports/products_and_inventory_report_spec.rb index 3eaca20d01..1d819068d0 100644 --- a/spec/lib/reports/products_and_inventory_report_spec.rb +++ b/spec/lib/reports/products_and_inventory_report_spec.rb @@ -2,318 +2,248 @@ require 'spec_helper' -module Reporting - module Reports - module ProductsAndInventory - RSpec.describe Base do - context "As a site admin" do - let(:user) { create(:admin_user) } - subject do - Base.new user, {} - end +RSpec.describe Reporting::Reports::ProductsAndInventory::Base do + context "As a site admin" do + let(:user) { create(:admin_user) } + subject do + described_class.new user, {} + end - it "Should return headers" do - expect(subject.table_headers).to eq([ - "Supplier", - "Producer Suburb", - "Product", - "Product Properties", - "Taxons", - "Variant Value", - "Price", - "Group Buy Unit Quantity", - "Amount", - "SKU" - ]) - end + it "Should return headers" do + expect(subject.table_headers).to eq([ + "Supplier", + "Producer Suburb", + "Product", + "Product Properties", + "Taxons", + "Variant Value", + "Price", + "Group Buy Unit Quantity", + "Amount", + "SKU" + ]) + end - it "should build a table from a list of variants" do - variant = double(:variant, sku: "sku", - full_name: "Variant Name", - count_on_hand: 10, - price: 100) - allow(variant).to receive_message_chain(:supplier, :name).and_return("Supplier") - allow(variant).to receive_message_chain(:supplier, :address, :city).and_return("A city") - allow(variant).to receive_message_chain(:product, :name).and_return("Product Name") - allow(variant).to receive_message_chain(:product, :properties) - .and_return [double(name: "property1"), double(name: "property2")] - allow(variant).to receive_message_chain(:primary_taxon). - and_return double(name: "taxon1") - allow(variant).to receive_message_chain(:product, :group_buy_unit_size).and_return(21) - allow(subject).to receive(:query_result).and_return [variant] + it "should build a table from a list of variants" do + variant = double(:variant, sku: "sku", + full_name: "Variant Name", + count_on_hand: 10, + price: 100) + allow(variant).to receive_message_chain(:supplier, :name).and_return("Supplier") + allow(variant).to receive_message_chain(:supplier, :address, :city).and_return("A city") + allow(variant).to receive_message_chain(:product, :name).and_return("Product Name") + allow(variant).to receive_message_chain(:product, :properties) + .and_return [double(name: "property1"), double(name: "property2")] + allow(variant).to receive_message_chain(:primary_taxon). + and_return double(name: "taxon1") + allow(variant).to receive_message_chain(:product, :group_buy_unit_size).and_return(21) + allow(subject).to receive(:query_result).and_return [variant] - expect(subject.table_rows).to eq([[ - "Supplier", - "A city", - "Product Name", - "property1, property2", - "taxon1", - "Variant Name", - 100, - 21, - "", - "sku" - ]]) - end + expect(subject.table_rows).to eq([[ + "Supplier", + "A city", + "Product Name", + "property1, property2", + "taxon1", + "Variant Name", + 100, + 21, + "", + "sku" + ]]) + end - it "fetches variants for some params" do - expect(subject).to receive(:child_variants).and_return ["children"] - expect(subject).to receive(:filter).with(['children']).and_return ["filter_children"] - expect(subject.query_result).to eq(["filter_children"]) - end - end + it "fetches variants for some params" do + expect(subject).to receive(:child_variants).and_return ["children"] + expect(subject).to receive(:filter).with(['children']).and_return ["filter_children"] + expect(subject.query_result).to eq(["filter_children"]) + end + end - context "As an enterprise user" do - let(:supplier) { create(:supplier_enterprise) } - let(:enterprise_user) do - user = create(:user) - user.enterprise_roles.create(enterprise: supplier) - user.save! - user - end + context "As an enterprise user" do + let(:supplier) { create(:supplier_enterprise) } + let(:enterprise_user) do + user = create(:user) + user.enterprise_roles.create(enterprise: supplier) + user.save! + user + end - subject do - Base.new enterprise_user, {} - end + subject do + described_class.new enterprise_user, {} + end - describe "fetching child variants" do - it "returns some variants" do - product1 = create(:simple_product) - variant1 = create(:variant, product: product1, supplier:) - variant2 = create(:variant, product: product1, supplier:) + describe "fetching child variants" do + it "returns some variants" do + product1 = create(:simple_product) + variant1 = create(:variant, product: product1, supplier:) + variant2 = create(:variant, product: product1, supplier:) - expect(subject.child_variants).to match_array [variant1, variant2] - end + expect(subject.child_variants).to match_array [variant1, variant2] + end - it "should only return variants managed by the user" do - variant1 = create(:variant, supplier: create(:supplier_enterprise)) - variant2 = create(:variant, supplier:) + it "should only return variants managed by the user" do + variant1 = create(:variant, supplier: create(:supplier_enterprise)) + variant2 = create(:variant, supplier:) - expect(subject.child_variants).to match_array([variant2]) - end - end + expect(subject.child_variants).to match_array([variant2]) + end + end - describe "Filtering variants" do - let(:variants) { Spree::Variant.joins(:product) } + describe "Filtering variants" do + let(:variants) { Spree::Variant.joins(:product) } - describe "based on report type" do - it "returns only variants on hand" do - product1 = create(:simple_product, supplier_id: supplier.id, on_hand: 99) - product2 = create(:simple_product, supplier_id: supplier.id, on_hand: 0) + describe "based on report type" do + it "returns only variants on hand" do + product1 = create(:simple_product, supplier_id: supplier.id, on_hand: 99) + product2 = create(:simple_product, supplier_id: supplier.id, on_hand: 0) - subject = Inventory.new enterprise_user - expect(subject.filter(variants)).to eq([product1.variants.first]) - end - end - - it "filters to a specific supplier" do - supplier2 = create(:supplier_enterprise) - variant1 = create(:variant, supplier: ) - variant2 = create(:variant, supplier: supplier2) - - allow(subject).to receive(:params).and_return(supplier_id: supplier.id) - expect(subject.filter(variants)).to eq([variant1]) - end - - it "filters to a specific distributor" do - distributor = create(:distributor_enterprise) - variant1 = create(:variant, supplier:) - variant2 = create(:variant, supplier:) - order_cycle = create(:simple_order_cycle, suppliers: [supplier], - distributors: [distributor], - variants: [variant2]) - - allow(subject).to receive(:params).and_return(distributor_id: distributor.id) - expect(subject.filter(variants)).to eq([variant2]) - end - - it "ignores variant overrides without filter" do - distributor = create(:distributor_enterprise) - product = create(:simple_product, supplier_id: supplier.id, price: 5) - variant = product.variants.first - order_cycle = create(:simple_order_cycle, suppliers: [supplier], - distributors: [distributor], - variants: [variant]) - create(:variant_override, hub: distributor, variant:, price: 2) - - result = subject.filter(variants) - - expect(result.first.price).to eq 5 - end - - it "considers variant overrides with distributor" do - distributor = create(:distributor_enterprise) - product = create(:simple_product, supplier_id: supplier.id, price: 5) - variant = product.variants.first - order_cycle = create(:simple_order_cycle, suppliers: [supplier], - distributors: [distributor], - variants: [variant]) - create(:variant_override, hub: distributor, variant:, price: 2) - - allow(subject).to receive(:params).and_return(distributor_id: distributor.id) - result = subject.filter(variants) - - expect(result.first.price).to eq 2 - end - - it "filters to a specific order cycle" do - distributor = create(:distributor_enterprise) - variant1 = create(:variant, supplier:) - variant2 = create(:variant, supplier:) - order_cycle = create(:simple_order_cycle, suppliers: [supplier], - distributors: [distributor], - variants: [variant1]) - - allow(subject).to receive(:params).and_return(order_cycle_id: order_cycle.id) - expect(subject.filter(variants)).to eq([variant1]) - end - - it "should do all the filters at once" do - # The following data ensures that this spec fails if any of the - # filters fail. It's testing the filters are not impacting each other. - distributor = create(:distributor_enterprise) - other_distributor = create(:distributor_enterprise) - other_supplier = create(:supplier_enterprise) - not_filtered_variant = create(:variant, supplier:) - variant_filtered_by_order_cycle = create(:variant, supplier:) - variant_filtered_by_distributor = create(:variant, supplier:) - variant_filtered_by_supplier = create(:variant, supplier: other_supplier) - variant_filtered_by_stock = create(:variant, supplier:, on_hand: 0) - - # This OC contains all products except the one that should be filtered - # by order cycle. We create a separate OC further down to proof that - # the product is passing all other filters. - order_cycle = create( - :simple_order_cycle, - suppliers: [supplier, other_supplier], - distributors: [distributor, other_distributor], - variants: [ - not_filtered_variant, - variant_filtered_by_distributor, - variant_filtered_by_supplier, - variant_filtered_by_stock - ] - ) - - # Remove the distribution of one product for one distributor but still - # sell it through the other distributor. - order_cycle.exchanges.outgoing.find_by(receiver_id: distributor.id). - exchange_variants. - find_by(variant_id: variant_filtered_by_distributor). - destroy - - # Make product available to be filtered later. See OC comment above. - create( - :simple_order_cycle, - suppliers: [supplier], - distributors: [distributor, other_distributor], - variants: [ - variant_filtered_by_order_cycle - ] - ) - - subject = Inventory.new enterprise_user - allow(subject).to receive(:params).and_return( - order_cycle_id: order_cycle.id, - supplier_id: supplier.id, - distributor_id: distributor.id - ) - - expect(subject.filter(variants)).to match_array [not_filtered_variant] - - # And it integrates with the ordering of the `variants` method. - expect(subject.query_result).to match_array [not_filtered_variant] - end - end - - describe "fetching SKU for a variant" do - let(:variant) { create(:variant) } - let(:product) { variant.product } - - before { - product.update_attribute(:sku, "Product SKU") - allow(subject).to receive(:query_result).and_return([variant]) - } - - context "when the variant has an SKU set" do - before { variant.update_attribute(:sku, "Variant SKU") } - it "returns it" do - expect(subject.rows.first.sku).to eq "Variant SKU" - end - end - - context "when the variant has bo SKU set" do - before { variant.update_attribute(:sku, "") } - - it "returns the product's SKU" do - expect(subject.rows.first.sku).to eq "Product SKU" - end - end - end + subject = Reporting::Reports::ProductsAndInventory::Inventory.new enterprise_user + expect(subject.filter(variants)).to eq([product1.variants.first]) end end - RSpec.describe AllProducts do - let(:user) { create(:admin_user) } - let(:report) do - AllProducts.new user, { fields_to_hide: [] } + it "filters to a specific supplier" do + supplier2 = create(:supplier_enterprise) + variant1 = create(:variant, supplier: ) + variant2 = create(:variant, supplier: supplier2) + + allow(subject).to receive(:params).and_return(supplier_id: supplier.id) + expect(subject.filter(variants)).to eq([variant1]) + end + + it "filters to a specific distributor" do + distributor = create(:distributor_enterprise) + variant1 = create(:variant, supplier:) + variant2 = create(:variant, supplier:) + order_cycle = create(:simple_order_cycle, suppliers: [supplier], + distributors: [distributor], + variants: [variant2]) + + allow(subject).to receive(:params).and_return(distributor_id: distributor.id) + expect(subject.filter(variants)).to eq([variant2]) + end + + it "ignores variant overrides without filter" do + distributor = create(:distributor_enterprise) + product = create(:simple_product, supplier_id: supplier.id, price: 5) + variant = product.variants.first + order_cycle = create(:simple_order_cycle, suppliers: [supplier], + distributors: [distributor], + variants: [variant]) + create(:variant_override, hub: distributor, variant:, price: 2) + + result = subject.filter(variants) + + expect(result.first.price).to eq 5 + end + + it "considers variant overrides with distributor" do + distributor = create(:distributor_enterprise) + product = create(:simple_product, supplier_id: supplier.id, price: 5) + variant = product.variants.first + order_cycle = create(:simple_order_cycle, suppliers: [supplier], + distributors: [distributor], + variants: [variant]) + create(:variant_override, hub: distributor, variant:, price: 2) + + allow(subject).to receive(:params).and_return(distributor_id: distributor.id) + result = subject.filter(variants) + + expect(result.first.price).to eq 2 + end + + it "filters to a specific order cycle" do + distributor = create(:distributor_enterprise) + variant1 = create(:variant, supplier:) + variant2 = create(:variant, supplier:) + order_cycle = create(:simple_order_cycle, suppliers: [supplier], + distributors: [distributor], + variants: [variant1]) + + allow(subject).to receive(:params).and_return(order_cycle_id: order_cycle.id) + expect(subject.filter(variants)).to eq([variant1]) + end + + it "should do all the filters at once" do + # The following data ensures that this spec fails if any of the + # filters fail. It's testing the filters are not impacting each other. + distributor = create(:distributor_enterprise) + other_distributor = create(:distributor_enterprise) + other_supplier = create(:supplier_enterprise) + not_filtered_variant = create(:variant, supplier:) + variant_filtered_by_order_cycle = create(:variant, supplier:) + variant_filtered_by_distributor = create(:variant, supplier:) + variant_filtered_by_supplier = create(:variant, supplier: other_supplier) + variant_filtered_by_stock = create(:variant, supplier:, on_hand: 0) + + # This OC contains all products except the one that should be filtered + # by order cycle. We create a separate OC further down to proof that + # the product is passing all other filters. + order_cycle = create( + :simple_order_cycle, + suppliers: [supplier, other_supplier], + distributors: [distributor, other_distributor], + variants: [ + not_filtered_variant, + variant_filtered_by_distributor, + variant_filtered_by_supplier, + variant_filtered_by_stock + ] + ) + + # Remove the distribution of one product for one distributor but still + # sell it through the other distributor. + order_cycle.exchanges.outgoing.find_by(receiver_id: distributor.id). + exchange_variants. + find_by(variant_id: variant_filtered_by_distributor). + destroy + + # Make product available to be filtered later. See OC comment above. + create( + :simple_order_cycle, + suppliers: [supplier], + distributors: [distributor, other_distributor], + variants: [ + variant_filtered_by_order_cycle + ] + ) + + subject = Reporting::Reports::ProductsAndInventory::Inventory.new enterprise_user + allow(subject).to receive(:params).and_return( + order_cycle_id: order_cycle.id, + supplier_id: supplier.id, + distributor_id: distributor.id + ) + + expect(subject.filter(variants)).to match_array [not_filtered_variant] + + # And it integrates with the ordering of the `variants` method. + expect(subject.query_result).to match_array [not_filtered_variant] + end + end + + describe "fetching SKU for a variant" do + let(:variant) { create(:variant) } + let(:product) { variant.product } + + before { + product.update_attribute(:sku, "Product SKU") + allow(subject).to receive(:query_result).and_return([variant]) + } + + context "when the variant has an SKU set" do + before { variant.update_attribute(:sku, "Variant SKU") } + it "returns it" do + expect(subject.rows.first.sku).to eq "Variant SKU" end - let(:variant) { create(:variant, supplier:) } - let(:supplier) { create(:supplier_enterprise) } + end - it "returns headers" do - expect(report.table_headers).to eq([ - "Supplier", - "Producer Suburb", - "Product", - "Product Properties", - "Taxons", - "Variant Value", - "Price", - "Group Buy Unit Quantity", - "Amount", - "SKU", - "On Demand?", - "On Hand", - "Tax Category" - ]) - end + context "when the variant has bo SKU set" do + before { variant.update_attribute(:sku, "") } - it "renders 'On demand' when the product is available on demand" do - variant.on_demand = true - variant.on_hand = 15 - variant.save! - - last_row = report.table_rows.last - on_demand_column = last_row[-3] - on_hand_column = last_row[-2] - - expect(on_demand_column).to eq("Yes") - expect(on_hand_column).to eq("On demand") - end - - it "renders the on hand count when the product is not available on demand" do - variant.on_demand = false - variant.on_hand = 22 - variant.save! - - last_row = report.table_rows.last - on_demand_column = last_row[-3] - on_hand_column = last_row[-2] - - expect(on_demand_column).to eq("No") - expect(on_hand_column).to eq(22) - end - - it "renders tax category if present, otherwise none" do - variant.update!(tax_category: create(:tax_category, name: 'Test Category')) - - table_rows = report.table_rows - first_row = table_rows.first # row for default variant, as result of product creation - last_row = table_rows.last # row for the variant created/updated above - - expect(first_row.last).to eq('none') - expect(last_row.last).to eq('Test Category') + it "returns the product's SKU" do + expect(subject.rows.first.sku).to eq "Product SKU" end end end