"""Pengujian jalur independen validate_checkout (V(G) = 7). Satu test per jalur basis. Nomor P1..P7 sama dengan tabel di docs/laporan.md. Kebutuhan: FR-ORD-02, FR-ORD-03, FR-ORD-08. """ import pytest from umkm.catalog import ClothingProduct from umkm.checkout import ( CartItem, CheckoutSummary, InsufficientStockError, InvalidQuantityError, MultiShopError, ProductNotFoundError, validate_checkout, ) @pytest.fixture def products(): return { "p1": ClothingProduct("p1", "shop-A", "Kaos", price=50_000, on_hand=10, size="M"), "p2": ClothingProduct("p2", "shop-A", "Kemeja", price=120_000, on_hand=5, size="L"), "p3": ClothingProduct("p3", "shop-B", "Jaket", price=200_000, on_hand=5, size="XL"), "p4": ClothingProduct("p4", "shop-A", "Topi", price=30_000, on_hand=3, size="S", reserved=3), } def test_p1_keranjang_kosong_total_nol(products): """P1: loop tidak dimasuki.""" assert validate_checkout([], products) == CheckoutSummary(None, 0) def test_p2_produk_tidak_ada(products): """P2: product is None -> ProductNotFoundError.""" with pytest.raises(ProductNotFoundError): validate_checkout([CartItem("tidak-ada", 1)], products) @pytest.mark.parametrize("qty", [0, -1]) def test_p3_kuantitas_tidak_valid(products, qty): """P3: quantity <= 0 -> InvalidQuantityError (batas 0 dan negatif).""" with pytest.raises(InvalidQuantityError): validate_checkout([CartItem("p1", qty)], products) def test_p4_stok_tidak_cukup_pada_item_pertama(products): """P4: available < quantity pada iterasi pertama.""" with pytest.raises(InsufficientStockError): validate_checkout([CartItem("p4", 1)], products) def test_p5_satu_item_valid(products): """P5: jalur baseline, satu item lolos semua cek.""" assert validate_checkout([CartItem("p1", 2)], products) == CheckoutSummary("shop-A", 100_000) def test_p6_dua_item_satu_toko(products): """P6: iterasi kedua, toko sama -> shop_id tidak berubah, total dijumlahkan.""" result = validate_checkout([CartItem("p1", 2), CartItem("p2", 1)], products) assert result == CheckoutSummary("shop-A", 2 * 50_000 + 120_000) def test_p7_dua_item_beda_toko(products): """P7: iterasi kedua, toko berbeda -> MultiShopError (FR-ORD-08).""" with pytest.raises(MultiShopError): validate_checkout([CartItem("p1", 1), CartItem("p3", 1)], products) def test_batas_stok_tepat_sama_lolos(products): """Batas available == quantity harus lolos (cabang stok false).""" assert validate_checkout([CartItem("p2", 5)], products).total_amount == 600_000