82 lines
2.9 KiB
TypeScript
82 lines
2.9 KiB
TypeScript
import { describe, expect, mock, test } from "bun:test";
|
|
import { KeePassDatabase } from "../../src/keepass";
|
|
|
|
const spawnMock = mock(() => {
|
|
throw new Error("spawn should be mocked per test");
|
|
});
|
|
|
|
mock.module("node:child_process", () => ({
|
|
spawn: spawnMock,
|
|
}));
|
|
|
|
function mockSuccessfulBridgeResponse(data: unknown) {
|
|
spawnMock.mockImplementation(() => {
|
|
const child = {
|
|
stdin: { write: () => undefined, end: () => undefined },
|
|
stdout: { on: (_event: string, cb: (chunk: Buffer | string) => void) => cb(JSON.stringify({ ok: true, data })) },
|
|
stderr: { on: () => undefined },
|
|
on: (event: string, cb: (code?: number | null) => void) => {
|
|
if (event === "close") queueMicrotask(() => cb(0));
|
|
},
|
|
};
|
|
return child as never;
|
|
});
|
|
}
|
|
|
|
describe("KeePassDatabase", () => {
|
|
test("listEntries parses successful bridge response", async () => {
|
|
mockSuccessfulBridgeResponse([{ title: "Entry" }]);
|
|
|
|
const db = new KeePassDatabase("db.kdbx", { password: "secret" }, "python3", new URL("file:///tmp/bridge.py"));
|
|
const entries = await db.listEntries();
|
|
|
|
expect(entries).toEqual([{ title: "Entry" }]);
|
|
expect(spawnMock).toHaveBeenCalled();
|
|
});
|
|
|
|
test("throws on bridge error payload", async () => {
|
|
spawnMock.mockImplementation(() => {
|
|
const child = {
|
|
stdin: { write: () => undefined, end: () => undefined },
|
|
stdout: { on: (_event: string, cb: (chunk: Buffer | string) => void) => cb('{"ok":false,"error":"boom"}') },
|
|
stderr: { on: () => undefined },
|
|
on: (event: string, cb: (code?: number | null) => void) => {
|
|
if (event === "close") queueMicrotask(() => cb(1));
|
|
},
|
|
};
|
|
return child as never;
|
|
});
|
|
|
|
const db = new KeePassDatabase("db.kdbx", { password: "secret" }, "python3", new URL("file:///tmp/bridge.py"));
|
|
await expect(db.listEntries()).rejects.toThrow("boom");
|
|
});
|
|
|
|
test("createEntry forwards the create-entry command", async () => {
|
|
mockSuccessfulBridgeResponse({ title: "New" });
|
|
|
|
const db = new KeePassDatabase("db.kdbx", { password: "secret" }, "python3", new URL("file:///tmp/bridge.py"));
|
|
const created = await db.createEntry({ title: "New" });
|
|
|
|
expect(created).toEqual({ title: "New" });
|
|
expect(spawnMock).toHaveBeenCalled();
|
|
});
|
|
|
|
test("createGroup forwards the create-group command", async () => {
|
|
mockSuccessfulBridgeResponse({ name: "Folder", path: "" });
|
|
|
|
const db = new KeePassDatabase("db.kdbx", { password: "secret" }, "python3", new URL("file:///tmp/bridge.py"));
|
|
const created = await db.createGroup({ name: "Folder" });
|
|
|
|
expect(created).toEqual({ name: "Folder", path: "" });
|
|
expect(spawnMock).toHaveBeenCalled();
|
|
});
|
|
|
|
test("save forwards the save command", async () => {
|
|
mockSuccessfulBridgeResponse(null);
|
|
|
|
const db = new KeePassDatabase("db.kdbx", { password: "secret" }, "python3", new URL("file:///tmp/bridge.py"));
|
|
await expect(db.save()).resolves.toBeUndefined();
|
|
expect(spawnMock).toHaveBeenCalled();
|
|
});
|
|
});
|