initial_commit
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
"""Pengujian mesin status Order: transisi valid, tidak valid, dan guard pelaku.
|
||||
|
||||
Kebutuhan: FR-ORD-04, FR-ORD-06, FR-ORD-09, FR-ORD-10.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from umkm.order import (
|
||||
TRANSITIONS,
|
||||
InvalidTransitionError,
|
||||
Order,
|
||||
OrderStatus as S,
|
||||
PermissionDeniedError,
|
||||
)
|
||||
|
||||
BUYER, SELLER = "buyer-1", "seller-1"
|
||||
T0 = datetime(2026, 11, 1, 10, 0)
|
||||
|
||||
|
||||
def new_order():
|
||||
return Order("o-1", BUYER, SELLER)
|
||||
|
||||
|
||||
def order_in(status):
|
||||
"""Bawa order ke status yang diminta lewat transisi sungguhan."""
|
||||
order = new_order()
|
||||
if status in (S.PAID, S.SHIPPED, S.COMPLETED):
|
||||
order.pay()
|
||||
if status in (S.SHIPPED, S.COMPLETED):
|
||||
order.ship(SELLER, T0)
|
||||
if status is S.COMPLETED:
|
||||
order.confirm_received(BUYER)
|
||||
if status is S.CANCELLED:
|
||||
order.cancel(BUYER)
|
||||
if status is S.EXPIRED:
|
||||
order.expire()
|
||||
assert order.status is status
|
||||
return order
|
||||
|
||||
|
||||
# Semua event yang dapat dipicu; auto_complete memakai waktu tepat jatuh tempo.
|
||||
EVENTS = {
|
||||
"pay": lambda o: o.pay(),
|
||||
"cancel": lambda o: o.cancel(BUYER),
|
||||
"expire": lambda o: o.expire(),
|
||||
"ship": lambda o: o.ship(SELLER, T0),
|
||||
"complete": lambda o: o.confirm_received(BUYER),
|
||||
"auto_complete": lambda o: o.auto_complete(T0 + timedelta(days=3)),
|
||||
}
|
||||
VALID = dict(TRANSITIONS)
|
||||
VALID[(S.SHIPPED, "auto_complete")] = S.COMPLETED
|
||||
INVALID = [(s, e) for s in S for e in EVENTS if (s, e) not in VALID]
|
||||
|
||||
|
||||
def test_order_baru_berstatus_pending_payment():
|
||||
assert new_order().status is S.PENDING_PAYMENT
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("src", "event"), list(VALID))
|
||||
def test_transisi_valid(src, event):
|
||||
order = order_in(src)
|
||||
EVENTS[event](order)
|
||||
assert order.status is VALID[(src, event)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("src", "event"), INVALID)
|
||||
def test_transisi_tidak_valid_ditolak_dan_status_tetap(src, event):
|
||||
order = order_in(src)
|
||||
with pytest.raises(InvalidTransitionError):
|
||||
EVENTS[event](order)
|
||||
assert order.status is src
|
||||
|
||||
|
||||
def test_jumlah_kombinasi_lengkap():
|
||||
"""6 status x 6 event = 36 kombinasi: 6 valid + 30 tidak valid."""
|
||||
assert len(VALID) == 6
|
||||
assert len(INVALID) == 30
|
||||
|
||||
|
||||
@pytest.mark.parametrize("final", [S.COMPLETED, S.CANCELLED, S.EXPIRED])
|
||||
def test_status_akhir_tidak_punya_transisi_keluar(final):
|
||||
assert not [key for key in VALID if key[0] is final]
|
||||
|
||||
|
||||
def test_seller_tidak_boleh_menyelesaikan_order():
|
||||
"""FR-ORD-10: hanya pembeli yang mengonfirmasi."""
|
||||
order = order_in(S.SHIPPED)
|
||||
with pytest.raises(PermissionDeniedError):
|
||||
order.confirm_received(SELLER)
|
||||
assert order.status is S.SHIPPED
|
||||
|
||||
|
||||
def test_hanya_seller_pemilik_toko_boleh_mengirim():
|
||||
order = order_in(S.PAID)
|
||||
with pytest.raises(PermissionDeniedError):
|
||||
order.ship("seller-lain", T0)
|
||||
assert order.status is S.PAID
|
||||
|
||||
|
||||
def test_hanya_pembeli_pemilik_order_boleh_membatalkan():
|
||||
order = new_order()
|
||||
with pytest.raises(PermissionDeniedError):
|
||||
order.cancel("buyer-lain")
|
||||
assert order.status is S.PENDING_PAYMENT
|
||||
|
||||
|
||||
def test_auto_complete_ditolak_sebelum_3_hari():
|
||||
order = order_in(S.SHIPPED)
|
||||
with pytest.raises(InvalidTransitionError):
|
||||
order.auto_complete(T0 + timedelta(days=3) - timedelta(seconds=1))
|
||||
assert order.status is S.SHIPPED
|
||||
|
||||
|
||||
def test_auto_complete_tepat_3_hari_berhasil():
|
||||
order = order_in(S.SHIPPED)
|
||||
order.auto_complete(T0 + timedelta(days=3))
|
||||
assert order.status is S.COMPLETED
|
||||
|
||||
|
||||
def test_ship_mencatat_waktu_pengiriman():
|
||||
assert order_in(S.SHIPPED).shipped_at == T0
|
||||
Reference in New Issue
Block a user