200 lines
4.8 KiB
Ruby
200 lines
4.8 KiB
Ruby
require "minitest/autorun"
|
|
|
|
require "checkout.rb"
|
|
require "buy_x_get_one_free_discount.rb"
|
|
require "bulk_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,
|
|
discount: BuyXGetOneFreeDiscount.new(unit_price: 15.00, trigger_quantity: 2)
|
|
)
|
|
)
|
|
@shop.add_product(
|
|
Product.new(
|
|
id: 'PICO2',
|
|
price: 4.00,
|
|
discount: BulkDiscount.new(unit_discount: 0.50, trigger_quantity: 3)
|
|
)
|
|
)
|
|
@checkout = Checkout.new(shop: @shop)
|
|
end
|
|
|
|
def test_that_unknown_items_cannot_be_added
|
|
assert_raises Checkout::InvalidItem do
|
|
@checkout.add(product_id: 'PI5000')
|
|
end
|
|
end
|
|
|
|
def test_that_nil_is_not_allowed_to_be_added
|
|
assert_raises Checkout::InvalidItem do
|
|
@checkout.add(product_id: nil)
|
|
end
|
|
end
|
|
|
|
def test_that_allowed_items_are_added
|
|
@checkout.add(product_id: 'PI5')
|
|
@checkout.add(product_id: 'ZERO2W')
|
|
@checkout.add(product_id: 'PICO2')
|
|
|
|
assert_equal({ 'PI5' => 1, 'ZERO2W' => 1, 'PICO2' => 1 }.sort, @checkout.item_quantities.sort)
|
|
end
|
|
|
|
def test_that_multiples_can_be_added_at_once
|
|
@checkout.add(product_id: 'PI5', quantity: 5)
|
|
assert_equal({ 'PI5' => 5 }.sort, @checkout.item_quantities.sort)
|
|
|
|
@checkout.add(product_id: 'PI5', quantity: 5)
|
|
assert_equal({ 'PI5' => 10 }.sort, @checkout.item_quantities.sort)
|
|
end
|
|
|
|
def test_that_total_is_the_sum_of_all_items_when_no_discounts_apply
|
|
@checkout.add(product_id: 'PI5') # 60.00
|
|
@checkout.add(product_id: 'ZERO2W') # 15.00
|
|
@checkout.add(product_id: 'PICO2') # 4.00
|
|
# -----
|
|
# 79.00 total
|
|
|
|
assert_equal 79.00, @checkout.total
|
|
end
|
|
|
|
def test_that_an_empty_checkout_total_is_zero
|
|
assert_equal 0.00, @checkout.total
|
|
end
|
|
|
|
def test_that_we_can_empty_the_checkout
|
|
@checkout.add(product_id: 'PI5')
|
|
@checkout.add(product_id: 'ZERO2W')
|
|
@checkout.add(product_id: 'PICO2')
|
|
|
|
refute_empty @checkout.items
|
|
|
|
@checkout.clear
|
|
|
|
assert_empty @checkout.items
|
|
|
|
end
|
|
|
|
# Discounts
|
|
|
|
def test_that_bogof_applied
|
|
@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
|
|
@checkout.add(product_id: 'ZERO2W', quantity: 5) # Should still remove 2 Zeros, 5th is full price
|
|
|
|
assert_equal 45.00, @checkout.total
|
|
end
|
|
|
|
def test_that_price_is_reduced_for_3_picos
|
|
@checkout.add(product_id: 'PICO2', quantity: 3) # 3.50 * 3 = 10.50
|
|
|
|
assert_equal 10.50, @checkout.total
|
|
end
|
|
|
|
def test_that_price_is_reduced_for_more_than_3_picos
|
|
@checkout.add(product_id: 'PICO2', quantity: 4) # 3.50 * 4 = 14
|
|
|
|
assert_equal 14.00, @checkout.total
|
|
end
|
|
|
|
def test_that_price_is_not_reduced_for_less_than_3_picos
|
|
@checkout.add(product_id: 'PICO2', quantity: 2) # 4.00 * 2 = 8
|
|
|
|
assert_equal 8.00, @checkout.total
|
|
end
|
|
|
|
def test_that_both_discounts_apply_at_the_same_time
|
|
@checkout.add(product_id: 'ZERO2W', quantity: 4) # 30.00 with BOGOF
|
|
@checkout.add(product_id: 'PICO2', quantity: 3) # 10.50 with bulk discount
|
|
|
|
assert_equal (30.00 + 10.50), @checkout.total
|
|
end
|
|
|
|
# Item removal
|
|
|
|
def test_that_removing_an_item_not_in_the_checkout_removes_nothing
|
|
skip
|
|
|
|
@checkout.add(:PICO2)
|
|
@checkout.remove(:PI5)
|
|
|
|
assert_equal [:PICO2], @checkout.items
|
|
end
|
|
|
|
def test_that_items_are_removed_one_by_one
|
|
skip
|
|
|
|
4.times do
|
|
@checkout.add(:ZERO2W)
|
|
end
|
|
|
|
3.times do
|
|
@checkout.add(:PICO2)
|
|
end
|
|
|
|
assert_equal [:ZERO2W, :ZERO2W, :ZERO2W, :ZERO2W, :PICO2, :PICO2, :PICO2].sort, @checkout.items.sort
|
|
|
|
@checkout.remove(:ZERO2W)
|
|
|
|
assert_equal [:ZERO2W, :ZERO2W, :ZERO2W, :PICO2, :PICO2, :PICO2].sort, @checkout.items.sort
|
|
|
|
@checkout.remove(:PICO2)
|
|
|
|
assert_equal [:ZERO2W, :ZERO2W, :ZERO2W, :PICO2, :PICO2].sort, @checkout.items.sort
|
|
|
|
2.times do
|
|
@checkout.remove(:PICO2)
|
|
end
|
|
|
|
assert_equal [:ZERO2W, :ZERO2W, :ZERO2W].sort, @checkout.items.sort
|
|
end
|
|
|
|
def test_that_total_is_correctly_recalculated_when_items_are_added
|
|
skip
|
|
|
|
2.times do
|
|
@checkout.add(:PICO2)
|
|
end
|
|
|
|
assert_equal 8.00, @checkout.total
|
|
|
|
@checkout.add(:PICO2) # 3 in total now, so discount applies
|
|
|
|
assert_equal 10.50, @checkout.total
|
|
|
|
4.times do
|
|
@checkout.add(:ZERO2W) # 30.00 with BOGOF
|
|
end
|
|
|
|
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
|
|
|
|
assert_equal 10.50, @checkout.total
|
|
|
|
@checkout.remove(:PICO2) # Bulk discount no longer applies
|
|
|
|
assert_equal 8.00, @checkout.total
|
|
end
|
|
end
|