Some checks failed
CI / Frontend Lint (push) Has been cancelled
CI / Frontend Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Frontend E2E Tests (push) Has been cancelled
CI / Orchestrator Build (push) Has been cancelled
CI / Orchestrator Unit Tests (push) Has been cancelled
CI / Orchestrator E2E (Testcontainers) (push) Has been cancelled
CI / Contracts Compile (push) Has been cancelled
CI / Contracts Test (push) Has been cancelled
Security Scan / Dependency Vulnerability Scan (push) Has been cancelled
Security Scan / OWASP ZAP Scan (push) Has been cancelled
199 lines
6.0 KiB
TypeScript
199 lines
6.0 KiB
TypeScript
/**
|
|
* Unit tests for the dbis_core HTTP client adapter.
|
|
*
|
|
* Covers both provider-switch legs:
|
|
* - `createDbisCoreClient()` with DBIS_CORE_URL unset → mock mode.
|
|
* - `createDbisCoreClient({ baseUrl, fetchImpl })` → live mode, with
|
|
* a stub `fetch` so tests never hit the network.
|
|
*/
|
|
|
|
import {
|
|
createDbisCoreClient,
|
|
type DbisCoreClient,
|
|
} from "../../src/services/dbisCore";
|
|
|
|
describe("dbisCore.createDbisCoreClient() — mock mode", () => {
|
|
let client: DbisCoreClient;
|
|
|
|
beforeAll(() => {
|
|
delete process.env.DBIS_CORE_URL;
|
|
delete process.env.DBIS_CORE_API_KEY;
|
|
client = createDbisCoreClient();
|
|
});
|
|
|
|
it("reports mock mode", () => {
|
|
expect(client.mode).toBe("mock");
|
|
});
|
|
|
|
it("returns a balance shaped like upstream", async () => {
|
|
const b = await client.getAccountBalance("acct-1");
|
|
expect(b.accountId).toBe("acct-1");
|
|
expect(typeof b.available).toBe("string");
|
|
expect(typeof b.held).toBe("string");
|
|
expect(b.currency).toBeDefined();
|
|
});
|
|
|
|
it("returns a plausible route", async () => {
|
|
const r = await client.findSettlementRoute({
|
|
sourceBankId: "src",
|
|
destinationBankId: "dst",
|
|
amount: "100",
|
|
currencyCode: "USD",
|
|
});
|
|
expect(r.routeId).toContain("src");
|
|
expect(r.hops.length).toBeGreaterThan(0);
|
|
expect(r.estimatedFeeBps).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
it("settles atomically with a deterministic id", async () => {
|
|
const s = await client.atomicSettle({
|
|
routeId: "r1",
|
|
sourceAccountId: "a",
|
|
destinationAccountId: "b",
|
|
amount: "1",
|
|
currencyCode: "USD",
|
|
reference: "ref-1",
|
|
});
|
|
expect(s.status).toBe("settled");
|
|
expect(s.settlementId).toContain("ref-1");
|
|
expect(s.completedAt).toBeDefined();
|
|
});
|
|
|
|
it("returns an allow decision by default from ARI", async () => {
|
|
const d = await client.requestAriDecision({
|
|
txId: "tx-1",
|
|
amount: "1",
|
|
currencyCode: "USD",
|
|
creator: "0xdead",
|
|
});
|
|
expect(d.outcome).toBe("allow");
|
|
expect(d.txId).toBe("tx-1");
|
|
expect(d.riskScore).toBeLessThan(1);
|
|
});
|
|
|
|
it("accepts a pacs008 dispatch and echoes the messageId", async () => {
|
|
const r = await client.dispatchPacs008({
|
|
messageId: "msg-1",
|
|
creationDateTime: "2026-01-01T00:00:00Z",
|
|
debtor: { name: "Acme", bic: "ACMEUS33", account: "1" },
|
|
creditor: { name: "Widget", bic: "WDGTGB22", account: "2" },
|
|
amount: "100",
|
|
currencyCode: "USD",
|
|
});
|
|
expect(r.status).toBe("accepted");
|
|
expect(r.messageId).toBe("msg-1");
|
|
});
|
|
|
|
it("returns a settled status from a synthetic settlementId", async () => {
|
|
const s = await client.getSettlementStatus("stlm-99");
|
|
expect(s.status).toBe("settled");
|
|
expect(s.legs.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
describe("dbisCore.createDbisCoreClient() — live mode (stubbed fetch)", () => {
|
|
function makeFetch(
|
|
record: (url: string, init: RequestInit) => void,
|
|
responseBody: unknown,
|
|
status = 200,
|
|
): typeof fetch {
|
|
return (async (input: string | URL | Request, init?: RequestInit) => {
|
|
record(String(input), init ?? {});
|
|
return new Response(JSON.stringify(responseBody), {
|
|
status,
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
}) as typeof fetch;
|
|
}
|
|
|
|
it("reports live mode when baseUrl is set", () => {
|
|
const client = createDbisCoreClient({
|
|
baseUrl: "http://dbis.example.test",
|
|
fetchImpl: makeFetch(
|
|
() => undefined,
|
|
{ accountId: "a", currency: "USD", available: "0", held: "0", asOf: "" },
|
|
),
|
|
});
|
|
expect(client.mode).toBe("live");
|
|
});
|
|
|
|
it("hits GET /api/accounts/:id/balance with the API key header", async () => {
|
|
const calls: { url: string; headers: Record<string, string>; method?: string }[] = [];
|
|
const client = createDbisCoreClient({
|
|
baseUrl: "http://dbis.example.test",
|
|
apiKey: "k-secret",
|
|
fetchImpl: makeFetch(
|
|
(url, init) => {
|
|
calls.push({
|
|
url,
|
|
method: init.method,
|
|
headers: (init.headers ?? {}) as Record<string, string>,
|
|
});
|
|
},
|
|
{
|
|
accountId: "a42",
|
|
currency: "USD",
|
|
available: "500",
|
|
held: "10",
|
|
asOf: "2026-01-01T00:00:00Z",
|
|
},
|
|
),
|
|
});
|
|
|
|
const b = await client.getAccountBalance("a42");
|
|
expect(b.available).toBe("500");
|
|
expect(calls).toHaveLength(1);
|
|
expect(calls[0].url).toBe("http://dbis.example.test/api/accounts/a42/balance");
|
|
expect(calls[0].method).toBe("GET");
|
|
expect(calls[0].headers["X-API-Key"]).toBe("k-secret");
|
|
});
|
|
|
|
it("posts a route request and parses the structured response", async () => {
|
|
const client = createDbisCoreClient({
|
|
baseUrl: "http://dbis.example.test/",
|
|
fetchImpl: makeFetch(
|
|
() => undefined,
|
|
{
|
|
routeId: "R1",
|
|
hops: [{ bankId: "A", latencyMs: 1, feeBps: 2 }],
|
|
estimatedLatencyMs: 10,
|
|
estimatedFeeBps: 2,
|
|
},
|
|
),
|
|
});
|
|
const r = await client.findSettlementRoute({
|
|
sourceBankId: "A",
|
|
destinationBankId: "B",
|
|
amount: "1",
|
|
currencyCode: "USD",
|
|
});
|
|
expect(r.routeId).toBe("R1");
|
|
expect(r.estimatedFeeBps).toBe(2);
|
|
});
|
|
|
|
it("throws a descriptive error on non-2xx", async () => {
|
|
const client = createDbisCoreClient({
|
|
baseUrl: "http://dbis.example.test",
|
|
fetchImpl: makeFetch(() => undefined, { error: "denied" }, 403),
|
|
});
|
|
await expect(client.getAccountBalance("a1")).rejects.toThrow(/HTTP 403/);
|
|
});
|
|
|
|
it("encodes path parameters safely", async () => {
|
|
const calls: string[] = [];
|
|
const client = createDbisCoreClient({
|
|
baseUrl: "http://dbis.example.test",
|
|
fetchImpl: makeFetch(
|
|
(url) => {
|
|
calls.push(url);
|
|
},
|
|
{ settlementId: "x", status: "settled", legs: [], lastUpdated: "" },
|
|
),
|
|
});
|
|
await client.getSettlementStatus("weird/id with space");
|
|
expect(calls[0]).toBe(
|
|
"http://dbis.example.test/api/isn/settlements/weird%2Fid%20with%20space",
|
|
);
|
|
});
|
|
});
|