diff --git a/buy_x_get_one_free_discount.rb b/buy_x_get_one_free_discount.rb new file mode 100644 index 0000000..43cd065 --- /dev/null +++ b/buy_x_get_one_free_discount.rb @@ -0,0 +1,10 @@ +class BuyXGetOneFreeDiscount + def initialize(unit_price:, trigger_quantity: 2) + @unit_price = unit_price + @trigger_quantity = trigger_quantity.to_f + end + + def discount_for_quantity(quantity) + return (quantity / @trigger_quantity).floor * @unit_price + end +end diff --git a/no_discount.rb b/no_discount.rb new file mode 100644 index 0000000..de28278 --- /dev/null +++ b/no_discount.rb @@ -0,0 +1,5 @@ +class NoDiscount + def discount_for_quantity(quantity) + return 0.00 + end +end diff --git a/product.rb b/product.rb index d8faac1..fd38efb 100644 --- a/product.rb +++ b/product.rb @@ -1,8 +1,10 @@ +require 'no_discount.rb' class Product - def initialize(price: 0.00, id:, description: '') + def initialize(price: 0.00, id:, discount: nil, description: '') @price = price @id = id @description = description + @discount = discount || NoDiscount.new end def price @@ -13,6 +15,10 @@ class Product @id end + def discount + @discount + end + def description @description end diff --git a/product_in_checkout.rb b/product_in_checkout.rb index ddcc4f8..6b2b838 100644 --- a/product_in_checkout.rb +++ b/product_in_checkout.rb @@ -17,6 +17,6 @@ class ProductInCheckout end def total - @product.price * quantity + (@product.price * quantity) - @product.discount.discount_for_quantity(@quantity) end end diff --git a/test/buy_x_get_one_free_discount_test.rb b/test/buy_x_get_one_free_discount_test.rb new file mode 100644 index 0000000..6e17014 --- /dev/null +++ b/test/buy_x_get_one_free_discount_test.rb @@ -0,0 +1,25 @@ +require "minitest/autorun" + +require 'buy_x_get_one_free_discount.rb' + +class BuyXGetOneFreeDiscountTest < Minitest::Test + def test_appropriate_discount_is_applied + unit_price = 4.00 + (2..4).each do |trigger_quantity| + discount = BuyXGetOneFreeDiscount.new(unit_price: unit_price, trigger_quantity: trigger_quantity) + + # Single discount at and above trigger quantity + assert_equal unit_price, discount.discount_for_quantity(trigger_quantity) + assert_equal unit_price, discount.discount_for_quantity(trigger_quantity + 1) + assert_equal unit_price, discount.discount_for_quantity(trigger_quantity + trigger_quantity - 1) + + + # No discount if less than trigger quantity + assert_equal 0.00, discount.discount_for_quantity(trigger_quantity - 1) + + # Double discount if double trigger quantity + assert_equal unit_price * 2, discount.discount_for_quantity(trigger_quantity * 2) + assert_equal unit_price * 2, discount.discount_for_quantity((trigger_quantity * 2) + 1) + end + end +end diff --git a/test/checkout_test.rb b/test/checkout_test.rb index 7915e90..398db7a 100644 --- a/test/checkout_test.rb +++ b/test/checkout_test.rb @@ -1,13 +1,30 @@ require "minitest/autorun" require "checkout.rb" +require "buy_x_get_one_free_discount.rb" class CheckoutTest < Minitest::Test def setup @shop = Shop.new - @shop.add_product(Product.new(id: 'PI5', price: 60.00)) - @shop.add_product(Product.new(id: 'ZERO2W', price: 15.00)) - @shop.add_product(Product.new(id: 'PICO2', price: 4.00)) + @shop.add_product( + Product.new( + id: 'PI5', + price: 60.00 + ) + ) + @shop.add_product( + Product.new( + id: 'ZERO2W', + price: 15.00, + discount: BuyXGetOneFreeDiscount.new(unit_price: 15.00, trigger_quantity: 2) + ) + ) + @shop.add_product( + Product.new( + id: 'PICO2', + price: 4.00 + ) + ) @checkout = Checkout.new(shop: @shop) end @@ -69,21 +86,13 @@ class CheckoutTest < Minitest::Test # Discounts def test_that_bogof_applied - skip - - 4.times do - @checkout.add(:ZERO2W) # Should remove 2 Zeros - end + @checkout.add(product_id: 'ZERO2W', quantity: 4) # Should remove 2 Zeros assert_equal 30.00, @checkout.total end def test_that_bogof_applied_with_odd_number - skip - - 5.times do - @checkout.add(:ZERO2W) # Should still remove 2 Zeros, 5th is full price - end + @checkout.add(product_id: 'ZERO2W', quantity: 5) # Should still remove 2 Zeros, 5th is full price assert_equal 45.00, @checkout.total end