import assert from "node:assert/strict" import { test } from "node:test" import { exportIpsecCertByName, exportIpsecUserCert, type IpsecExistingCertExportOptions } from "./ipsec" const base = "https://fixture.example.test" const options: IpsecExistingCertExportOptions = { privateKeyExport: true, caPrivateKeyExport: false, requestKey: "11111111-1111-4111-8111-111111111111" } const passphrase = " synthetic-passphrase " const bundle = { user: "Renamed label", filename: "fixture.p12", contentB64: "YQ==", passphrase } test("existing exports reject missing/invalid explicit intent before fetch", async () => { const original = globalThis.fetch let calls = 0 globalThis.fetch = async () => { calls++; throw Error("Unexpected fetch") } try { for (const invalid of [undefined, {}, { ...options, privateKeyExport: false }, { ...options, caPrivateKeyExport: undefined }, { ...options, requestKey: "invalid" }, { ...options, requestKey: undefined }, { ...options, extra: true }]) { const intent = invalid as IpsecExistingCertExportOptions await assert.rejects(() => exportIpsecUserCert(base, "1", "identity:*1", passphrase, intent)) await assert.rejects(() => exportIpsecCertByName(base, "1", "cert", passphrase, intent)) } await assert.rejects(() => exportIpsecUserCert(base, "1", "identity:*1", "short", options)) assert.equal(calls, 0) } finally { globalThis.fetch = original } }) test("client export preserves native identity selector, raw passphrase, flags and caller UUID", async () => { const original = globalThis.fetch let calls = 0 globalThis.fetch = async (url, init) => { calls++ assert.equal(new URL(String(url)).pathname.endsWith("/identity%3A*1%2F2/cert"), true) assert.equal(init?.method, "POST") const headers = new Headers(init?.headers), body = JSON.parse(String(init?.body)) assert.equal(headers.get("Idempotency-Key") === options.requestKey, true) assert.equal(headers.get("Content-Type"), "application/json") // Compare as booleans so assertion failures cannot print private material. assert.equal(body.passphrase === passphrase, true) assert.equal(body.privateKeyExport, true); assert.equal(body.caPrivateKeyExport, false) assert.equal(Object.hasOwn(body, "requestKey"), false); assert.equal(Object.hasOwn(body, "name"), false) return new Response(JSON.stringify(bundle)) } try { const result = await exportIpsecUserCert(base, "1", "identity:*1/2", passphrase, options) assert.equal(result.passphrase === passphrase, true); assert.equal(calls, 1) } finally { globalThis.fetch = original } }) test("by-name export supports client/server/foreign/CA targets and explicit CA intent", async () => { const original = globalThis.fetch let expectedName = "", expectedCa = false, calls = 0 globalThis.fetch = async (url, init) => { calls++ assert.equal(new URL(String(url)).pathname, "/api/ipsec/certs/1/export") const body = JSON.parse(String(init?.body)) assert.equal(body.name === expectedName, true); assert.equal(body.passphrase === passphrase, true) assert.equal(body.privateKeyExport, true); assert.equal(body.caPrivateKeyExport, expectedCa) assert.equal(new Headers(init?.headers).get("Idempotency-Key") === options.requestKey, true) return new Response(JSON.stringify(bundle)) } try { for (const [name, ca] of [["client", false], ["server", false], ["foreign", false], ["ca", true]] as const) { expectedName = name; expectedCa = ca await exportIpsecCertByName(base, "1", name, passphrase, { ...options, caPrivateKeyExport: ca }) } assert.equal(calls, 4) } finally { globalThis.fetch = original } }) test("failed, unknown and malformed responses never retry or allocate another request UUID", async () => { const original = globalThis.fetch try { for (const mode of ["network", "unknown", "malformed"] as const) { let calls = 0 globalThis.fetch = async (_url, init) => { calls++ assert.equal(new Headers(init?.headers).get("Idempotency-Key") === options.requestKey, true) if (mode === "network") throw Error("Synthetic transport failure") if (mode === "unknown") return new Response(JSON.stringify({ error: "Результат неизвестен", state: "unknown", needsReview: true }), { status: 502 }) return new Response(JSON.stringify({ ...bundle, contentB64: "invalid!" })) } await assert.rejects(() => exportIpsecUserCert(base, "1", "identity:*1", passphrase, options)) assert.equal(calls, 1) await assert.rejects(() => exportIpsecCertByName(base, "1", "client", passphrase, options)) assert.equal(calls, 2) } } finally { globalThis.fetch = original } }) test("closing an export can abort its one fetch without changing explicit intent", async () => { const original = globalThis.fetch, controller = new AbortController() let calls = 0 globalThis.fetch = async (_url, init) => { calls++ assert.equal(init?.signal === controller.signal, true) assert.equal(new Headers(init?.headers).get("Idempotency-Key") === options.requestKey, true) return new Promise((_resolve, reject) => { init?.signal?.addEventListener("abort", () => reject(new DOMException("Aborted", "AbortError")), { once: true }) }) } try { const pending = exportIpsecUserCert(base, "1", "identity:*1", passphrase, options, { signal: controller.signal }) controller.abort() await assert.rejects(pending, error => error instanceof DOMException && error.name === "AbortError") assert.equal(calls, 1) } finally { globalThis.fetch = original } })