From f220a1691cc1d2053064a36d9dd9100b0c97d90d Mon Sep 17 00:00:00 2001 From: David Underwood Date: Tue, 21 Jul 2026 12:49:57 -0400 Subject: [PATCH] Reimplement checkout item removal. All existing tests now pass --- checkout.rb | 33 +++++++++++++++++++++++---- product_in_checkout.rb | 4 ++++ test/checkout_test.rb | 52 ++++++++++++++---------------------------- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/checkout.rb b/checkout.rb index 53c319c..f4ba0f2 100644 --- a/checkout.rb +++ b/checkout.rb @@ -13,10 +13,21 @@ class Checkout raise InvalidItem unless product - product_in_checkout = new_or_existing_product_in_checkout(product) - product_in_checkout.add_quantity(quantity) + new_or_existing_product_in_checkout(product).add_quantity(quantity) + end - @items.push product_in_checkout + def remove(product_id:, quantity: 1) + product = @shop.product_by_id(product_id) + + raise InvalidItem unless product + + product_in_checkout = existing_product_in_checkout(product) + + return false unless product_in_checkout + + product_in_checkout.remove_quantity(quantity) + + trim_empty_items end def items @@ -37,7 +48,21 @@ class Checkout private + def existing_product_in_checkout(product) + @items.find { |item| item.product_id == product.id } + end + def new_or_existing_product_in_checkout(product) - @items.find { |item| item.product_id == product.id } || ProductInCheckout.new(product: product) + product_in_checkout = existing_product_in_checkout(product) + unless product_in_checkout + product_in_checkout = ProductInCheckout.new(product: product) + @items.push(product_in_checkout) + end + + product_in_checkout + end + + def trim_empty_items + @items = @items.filter { |item| item.quantity > 0 } end end diff --git a/product_in_checkout.rb b/product_in_checkout.rb index 6b2b838..aeaf0d5 100644 --- a/product_in_checkout.rb +++ b/product_in_checkout.rb @@ -16,6 +16,10 @@ class ProductInCheckout @quantity += quantity end + def remove_quantity(quantity) + @quantity = [@quantity - quantity, 0].max + end + def total (@product.price * quantity) - @product.discount.discount_for_quantity(@quantity) end diff --git a/test/checkout_test.rb b/test/checkout_test.rb index 010b53c..c82b7d5 100644 --- a/test/checkout_test.rb +++ b/test/checkout_test.rb @@ -127,72 +127,54 @@ class CheckoutTest < Minitest::Test # Item removal def test_that_removing_an_item_not_in_the_checkout_removes_nothing - skip + @checkout.add(product_id: 'PICO2') + @checkout.remove(product_id: 'PI5') - @checkout.add(:PICO2) - @checkout.remove(:PI5) - - assert_equal [:PICO2], @checkout.items + assert_equal({ 'PICO2' => 1 }, @checkout.item_quantities) end def test_that_items_are_removed_one_by_one - skip + @checkout.add(product_id: 'ZERO2W', quantity: 4) + @checkout.add(product_id: 'PICO2', quantity: 3) - 4.times do - @checkout.add(:ZERO2W) - end + assert_equal({ 'ZERO2W' => 4, 'PICO2' => 3 }.sort, @checkout.item_quantities.sort) - 3.times do - @checkout.add(:PICO2) - end + @checkout.remove(product_id: 'ZERO2W') - assert_equal [:ZERO2W, :ZERO2W, :ZERO2W, :ZERO2W, :PICO2, :PICO2, :PICO2].sort, @checkout.items.sort + assert_equal({ 'ZERO2W' => 3, 'PICO2' => 3 }.sort, @checkout.item_quantities.sort) - @checkout.remove(:ZERO2W) + @checkout.remove(product_id: 'PICO2') - assert_equal [:ZERO2W, :ZERO2W, :ZERO2W, :PICO2, :PICO2, :PICO2].sort, @checkout.items.sort + assert_equal({ 'ZERO2W' => 3, 'PICO2' => 2 }.sort, @checkout.item_quantities.sort) - @checkout.remove(:PICO2) - assert_equal [:ZERO2W, :ZERO2W, :ZERO2W, :PICO2, :PICO2].sort, @checkout.items.sort + @checkout.remove(product_id: 'PICO2', quantity: 2) - 2.times do - @checkout.remove(:PICO2) - end - - assert_equal [:ZERO2W, :ZERO2W, :ZERO2W].sort, @checkout.items.sort + assert_equal({ 'ZERO2W' => 3 }.sort, @checkout.item_quantities.sort) end def test_that_total_is_correctly_recalculated_when_items_are_added - skip - 2.times do - @checkout.add(:PICO2) - end + @checkout.add(product_id: 'PICO2', quantity: 2) assert_equal 8.00, @checkout.total - @checkout.add(:PICO2) # 3 in total now, so discount applies + @checkout.add(product_id: 'PICO2', quantity: 1) # 3 in total now, so discount applies assert_equal 10.50, @checkout.total - 4.times do - @checkout.add(:ZERO2W) # 30.00 with BOGOF - end + @checkout.add(product_id: 'ZERO2W', quantity: 4) assert_equal 40.50, @checkout.total end def test_that_total_is_correctly_recalculated_when_items_are_removed - skip - 3.times do - @checkout.add(:PICO2) # Bulk discount applies - end + @checkout.add(product_id: 'PICO2', quantity: 3) assert_equal 10.50, @checkout.total - @checkout.remove(:PICO2) # Bulk discount no longer applies + @checkout.remove(product_id: 'PICO2', quantity: 1) # Bulk discount no longer applies assert_equal 8.00, @checkout.total end