import type { Actor } from "@/lib/actor" import { evaluateOrderTransition } from "@/lib/domain/order-machine" import type { UserRole } from "@/lib/types" import { describe, expect, it } from "vitest" function actor(role: UserRole, userId = "u1"): Actor { return { role, userId } } describe("evaluateOrderTransition", () => { it("allows valid transition for pay", () => { const result = evaluateOrderTransition({ actor: actor("consumer"), order: { status: "pending_payment" }, action: "PAY", }) expect(result.decision.ok).toBe(true) expect(result.nextStatus).toBe("pending_accept") expect(result.sideEffects).toContainEqual({ type: "SCHEDULE_TIMEOUT", status: "pending_accept", }) }) it("denies invalid status transition", () => { const result = evaluateOrderTransition({ actor: actor("consumer"), order: { status: "completed" }, action: "PAY", }) expect(result.decision).toMatchObject({ ok: false, error: { code: 400 }, }) expect(result.nextStatus).toBeUndefined() }) it("denies role forbidden actions", () => { const result = evaluateOrderTransition({ actor: actor("consumer"), order: { status: "pending_accept" }, action: "ACCEPT", }) expect(result.decision).toMatchObject({ ok: false, error: { code: 403 }, }) }) it("allows accept for player", () => { const result = evaluateOrderTransition({ actor: actor("player"), order: { status: "pending_accept" }, action: "ACCEPT", }) expect(result.decision.ok).toBe(true) expect(result.nextStatus).toBe("in_progress") }) it("allows close confirmation to pending_review", () => { const result = evaluateOrderTransition({ actor: actor("consumer"), order: { status: "pending_close" }, action: "CONFIRM_CLOSE", }) expect(result.decision.ok).toBe(true) expect(result.nextStatus).toBe("pending_review") expect(result.sideEffects).toContainEqual({ type: "SCHEDULE_TIMEOUT", status: "pending_review", }) }) it("allows auto timeout actions without actor", () => { const result = evaluateOrderTransition({ order: { status: "pending_close" }, action: "AUTO_TIMEOUT_PENDING_CLOSE", }) expect(result.decision.ok).toBe(true) expect(result.nextStatus).toBe("pending_review") }) it("adds payout side effect when entering completed", () => { const result = evaluateOrderTransition({ order: { status: "pending_review" }, action: "AUTO_TIMEOUT_PENDING_REVIEW", }) expect(result.decision.ok).toBe(true) expect(result.nextStatus).toBe("completed") expect(result.sideEffects).toContainEqual({ type: "PAYOUT_INCOME" }) }) it("supports resolving dispute by owner", () => { const result = evaluateOrderTransition({ actor: actor("owner"), order: { status: "disputed" }, action: "RESOLVE_DISPUTE", }) expect(result.decision.ok).toBe(true) expect(result.nextStatus).toBe("pending_review") }) it("rejects dispute resolution by non-owner", () => { const result = evaluateOrderTransition({ actor: actor("player"), order: { status: "disputed" }, action: "RESOLVE_DISPUTE", }) expect(result.decision).toMatchObject({ ok: false, error: { code: 403 }, }) }) })