CI (SIAX Cloud) / integration (push) Has been skipped
masterplan-lock / check (push) Successful in 4s
CI (SIAX Cloud) / security (push) Successful in 14s
masterplan-lock / check (pull_request) Successful in 4s
CI (SIAX Cloud) / security (pull_request) Successful in 14s
Security Scan (SIAX Cloud) / security (push) Successful in 30s
CI (SIAX Cloud) / quality (push) Successful in 35s
CI (SIAX Cloud) / integration (pull_request) Successful in 25s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 54s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m31s
46 lines
2.5 KiB
TypeScript
46 lines
2.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
createOrder, getOwnedOrder, listOwnedOrders, setOwnedStatusIfCurrent,
|
|
IdempotencyKeyConflictError,
|
|
} from "@/lib/orders-store";
|
|
|
|
const alpha = { tenantId: "tenant-alpha", subject: "buyer-alpha" };
|
|
const beta = { tenantId: "tenant-beta", subject: "buyer-beta" };
|
|
const config = { markets: ["SE"], volume: 1000 };
|
|
|
|
describe("payment-order ownership (in-memory contract)", () => {
|
|
it("binds a new order to the verified tenant and buyer, never to client config", async () => {
|
|
const result = await createOrder("custom", config, undefined, alpha);
|
|
expect(result.order.tenant_id).toBe(alpha.tenantId);
|
|
expect(result.order.buyer_subject).toBe(alpha.subject);
|
|
expect(await getOwnedOrder(result.order.order_id, alpha.tenantId)).not.toBeNull();
|
|
expect(await getOwnedOrder(result.order.order_id, beta.tenantId)).toBeNull();
|
|
expect((await listOwnedOrders(beta.tenantId)).some((o) => o.order_id === result.order.order_id)).toBe(false);
|
|
});
|
|
|
|
it("legacy anonymous rows remain invisible and cannot be mutated by a buyer", async () => {
|
|
const legacy = (await createOrder("custom", config)).order;
|
|
expect(await getOwnedOrder(legacy.order_id, alpha.tenantId)).toBeNull();
|
|
expect(await setOwnedStatusIfCurrent(legacy.order_id, alpha.tenantId, "draft", "quoted")).toBeNull();
|
|
});
|
|
|
|
it("an owner cannot change another tenant's status even at the same valid state", async () => {
|
|
const order = (await createOrder("custom", config, undefined, alpha)).order;
|
|
expect(await setOwnedStatusIfCurrent(order.order_id, beta.tenantId, "draft", "quoted")).toBeNull();
|
|
expect((await getOwnedOrder(order.order_id, alpha.tenantId))?.status).toBe("draft");
|
|
expect((await setOwnedStatusIfCurrent(order.order_id, alpha.tenantId, "draft", "quoted"))?.status).toBe("quoted");
|
|
});
|
|
|
|
it("idempotency keys are tenant-namespaced, and another buyer in the same tenant cannot replay", async () => {
|
|
const key = `ownership-${crypto.randomUUID()}`;
|
|
const a1 = await createOrder("custom", config, key, alpha);
|
|
const a2 = await createOrder("custom", config, key, alpha);
|
|
const b1 = await createOrder("custom", config, key, beta);
|
|
expect(a2.replayed).toBe(true);
|
|
expect(a1.order.order_id).toBe(a2.order.order_id);
|
|
expect(a1.order.order_id).not.toBe(b1.order.order_id);
|
|
await expect(createOrder("custom", config, key, { ...alpha, subject: "other-buyer" }))
|
|
.rejects.toBeInstanceOf(IdempotencyKeyConflictError);
|
|
});
|
|
});
|