Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
import { OpenAPIHono } from "@hono/zod-openapi";
import { createOpenAPIRegistry } from "@suaveplan/api-openapi";
import { createPluginContext } from "@suaveplan/api-plugin";
import { EventBus } from "@suaveplan/events";
import { beforeEach, describe, expect, it } from "@suaveplan/testing/runner";
import {
createPaymentPlugin,
resetPaymentInstruments,
} from "../../src/index.js";
import type { PaymentPluginConfig } from "../../src/types/types.js";
import { FakePaymentProvider } from "../setup/fake-provider.js";
const noopLogger = {
debug: () => undefined,
info: () => undefined,
warn: () => undefined,
error: () => undefined,
};
const SECRET = "shared-webhook-secret-32-chars-or-more";
async function boot() {
resetPaymentInstruments();
const app = new OpenAPIHono();
app.use("*", async (c, next) => {
c.set("user", { id: "u1", emailVerified: true, roles: [] });
await next();
});
const provider = new FakePaymentProvider();
const services = new Map<string, unknown>();
services.set("app", app);
const registry = createOpenAPIRegistry({
info: { title: "test", version: "0.1" },
});
services.set("openAPIRegistry", registry);
const plugin = createPaymentPlugin({ provider, webhookSecret: SECRET });
await plugin.onInit?.(
createPluginContext<PaymentPluginConfig>({
logger: noopLogger,
eventBus: new EventBus(),
signal: new AbortController().signal,
config: plugin.defaults as PaymentPluginConfig,
services,
})
);
return { app, provider };
}
beforeEach(() => {
resetPaymentInstruments();
});
describe("payment plugin — idempotency", () => {
it("second create with same key returns same intent (no duplicate)", {
timeout: 60_000,
}, async () => {
const { app, provider } = await boot();
const headers = {
"content-type": "application/json",
"Idempotency-Key": "order-1",
};
const a = await app.request("/payments/intents", {
method: "POST",
headers,
body: JSON.stringify({
amount: { amount: "100", currency: "USD" },
}),
});
const b = await app.request("/payments/intents", {
method: "POST",
headers,
body: JSON.stringify({
amount: { amount: "100", currency: "USD" },
}),
});
const aBody = (await a.json()) as { intent: { id: string } };
const bBody = (await b.json()) as { intent: { id: string } };
expect(bBody.intent.id).toBe(aBody.intent.id);
// Provider should have been called once.
const list = await provider.getIntent(aBody.intent.id);
expect(list.id).toBe(aBody.intent.id);
});
it("different body under same key returns 409", {
timeout: 60_000,
}, async () => {
const { app } = await boot();
const headers = {
"content-type": "application/json",
"Idempotency-Key": "order-2",
};
await app.request("/payments/intents", {
method: "POST",
headers,
body: JSON.stringify({
amount: { amount: "100", currency: "USD" },
}),
});
const second = await app.request("/payments/intents", {
method: "POST",
headers,
body: JSON.stringify({
amount: { amount: "200", currency: "USD" },
}),
});
expect(second.status).toBe(409);
});
});