Reimplement checkout item removal. All existing tests now pass
This commit is contained in:
+29
-4
@@ -13,10 +13,21 @@ class Checkout
|
|||||||
|
|
||||||
raise InvalidItem unless product
|
raise InvalidItem unless product
|
||||||
|
|
||||||
product_in_checkout = new_or_existing_product_in_checkout(product)
|
new_or_existing_product_in_checkout(product).add_quantity(quantity)
|
||||||
product_in_checkout.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
|
end
|
||||||
|
|
||||||
def items
|
def items
|
||||||
@@ -37,7 +48,21 @@ class Checkout
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def existing_product_in_checkout(product)
|
||||||
|
@items.find { |item| item.product_id == product.id }
|
||||||
|
end
|
||||||
|
|
||||||
def new_or_existing_product_in_checkout(product)
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ class ProductInCheckout
|
|||||||
@quantity += quantity
|
@quantity += quantity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_quantity(quantity)
|
||||||
|
@quantity = [@quantity - quantity, 0].max
|
||||||
|
end
|
||||||
|
|
||||||
def total
|
def total
|
||||||
(@product.price * quantity) - @product.discount.discount_for_quantity(@quantity)
|
(@product.price * quantity) - @product.discount.discount_for_quantity(@quantity)
|
||||||
end
|
end
|
||||||
|
|||||||
+17
-35
@@ -127,72 +127,54 @@ class CheckoutTest < Minitest::Test
|
|||||||
# Item removal
|
# Item removal
|
||||||
|
|
||||||
def test_that_removing_an_item_not_in_the_checkout_removes_nothing
|
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)
|
assert_equal({ 'PICO2' => 1 }, @checkout.item_quantities)
|
||||||
@checkout.remove(:PI5)
|
|
||||||
|
|
||||||
assert_equal [:PICO2], @checkout.items
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_that_items_are_removed_one_by_one
|
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
|
assert_equal({ 'ZERO2W' => 4, 'PICO2' => 3 }.sort, @checkout.item_quantities.sort)
|
||||||
@checkout.add(:ZERO2W)
|
|
||||||
end
|
|
||||||
|
|
||||||
3.times do
|
@checkout.remove(product_id: 'ZERO2W')
|
||||||
@checkout.add(:PICO2)
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
assert_equal({ 'ZERO2W' => 3 }.sort, @checkout.item_quantities.sort)
|
||||||
@checkout.remove(:PICO2)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_equal [:ZERO2W, :ZERO2W, :ZERO2W].sort, @checkout.items.sort
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_that_total_is_correctly_recalculated_when_items_are_added
|
def test_that_total_is_correctly_recalculated_when_items_are_added
|
||||||
skip
|
|
||||||
|
|
||||||
2.times do
|
@checkout.add(product_id: 'PICO2', quantity: 2)
|
||||||
@checkout.add(:PICO2)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_equal 8.00, @checkout.total
|
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
|
assert_equal 10.50, @checkout.total
|
||||||
|
|
||||||
4.times do
|
@checkout.add(product_id: 'ZERO2W', quantity: 4)
|
||||||
@checkout.add(:ZERO2W) # 30.00 with BOGOF
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_equal 40.50, @checkout.total
|
assert_equal 40.50, @checkout.total
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_that_total_is_correctly_recalculated_when_items_are_removed
|
def test_that_total_is_correctly_recalculated_when_items_are_removed
|
||||||
skip
|
|
||||||
|
|
||||||
3.times do
|
@checkout.add(product_id: 'PICO2', quantity: 3)
|
||||||
@checkout.add(:PICO2) # Bulk discount applies
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_equal 10.50, @checkout.total
|
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
|
assert_equal 8.00, @checkout.total
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user