summaryrefslogtreecommitdiff
path: root/src/lib/pgp/create.test.ts
diff options
context:
space:
mode:
authorJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-24 12:08:41 -0300
committerJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-24 12:50:43 -0300
commitf9a77c5c27aede4e5978eb55d9b7af781b680a1d (patch)
treed545e325ba1ae756fc2eac66fac1001b6753c40d /src/lib/pgp/create.test.ts
feat!: initial commit
Signed-off-by: João Augusto Costa Branco Marado Torres <torres.dev@disroot.org>
Diffstat (limited to 'src/lib/pgp/create.test.ts')
-rw-r--r--src/lib/pgp/create.test.ts130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/lib/pgp/create.test.ts b/src/lib/pgp/create.test.ts
new file mode 100644
index 0000000..e9e9f41
--- /dev/null
+++ b/src/lib/pgp/create.test.ts
@@ -0,0 +1,130 @@
+import { beforeEach, describe, it } from "@std/testing/bdd";
+import {
+ createInMemoryFile,
+ generateKeyPair,
+ startMockFs,
+} from "../../../tests/fixtures/setup.ts";
+import {
+ armored,
+ binary,
+ createKeysFromFs,
+ DEFAULT_KEY_DISCOVERY_RULES,
+} from "./create.ts";
+import { assertEquals, assertRejects } from "@std/assert";
+import { stub } from "@std/testing/mock";
+
+startMockFs();
+
+describe("createKeysFromFs", () => {
+ let keyPair: Awaited<ReturnType<typeof generateKeyPair>>;
+
+ beforeEach(async () => {
+ keyPair = await generateKeyPair("Alice");
+ });
+
+ it("loads a single armored key file", async () => {
+ const url = createInMemoryFile(
+ new URL("file:///mock/alice.asc"),
+ keyPair.privateKey.armor(),
+ );
+
+ const keys = [];
+ for await (const key of createKeysFromFs(url)) {
+ keys.push(key);
+ }
+
+ assertEquals(keys.length, 1);
+ });
+
+ it("loads a single binary key file", async () => {
+ const binaryData = keyPair.privateKey.write();
+ const url = createInMemoryFile(
+ new URL("file:///mock/alice.gpg"),
+ binaryData as Uint8Array<ArrayBuffer>,
+ );
+
+ const keys = [];
+ for await (const key of createKeysFromFs(url)) {
+ keys.push(key);
+ }
+
+ assertEquals(keys.length, 1);
+ });
+
+ it("ignores unsupported file extensions", async () => {
+ const url = createInMemoryFile(
+ new URL("file:///mock/ignored.txt"),
+ "This is not a key",
+ );
+
+ const keys = [];
+ for await (const key of createKeysFromFs(url)) {
+ keys.push(key);
+ }
+
+ assertEquals(keys.length, 0);
+ });
+
+ it("throws on overlapping discovery formats", async () => {
+ const rules = {
+ formats: {
+ [armored]: new Set(["asc", "gpg"]),
+ [binary]: new Set(["gpg"]),
+ },
+ };
+
+ const url = new URL("file:///mock/bogus.gpg");
+
+ await assertRejects(() => createKeysFromFs(url, rules).next());
+ });
+
+ it("handles recursive directory traversal", async () => {
+ const aliceURL = new URL("file:///mock/keys/alice.asc");
+ const bobURL = new URL("file:///mock/keys/sub/bob.asc");
+
+ createInMemoryFile(aliceURL, keyPair.privateKey.armor());
+ createInMemoryFile(bobURL, keyPair.privateKey.armor());
+
+ const mockedDirTree = {
+ "file:///mock/keys/": [
+ { name: "alice.asc", isFile: true, isDirectory: false },
+ { name: "sub", isFile: false, isDirectory: true },
+ ],
+ "file:///mock/keys/sub/": [
+ { name: "bob.asc", isFile: true, isDirectory: false },
+ ],
+ };
+
+ stub(Deno, "stat", (url: URL | string) => {
+ const href = new URL(url).href;
+ return Promise.resolve({
+ isDirectory: href.endsWith("/") || href.includes("/sub"),
+ isFile: href.endsWith(".asc"),
+ isSymlink: false,
+ } as Deno.FileInfo);
+ });
+
+ stub(Deno, "readDir", async function* (url: URL | string) {
+ const href = new URL(url).href;
+ for (
+ const entry of mockedDirTree[href as keyof typeof mockedDirTree] ?? []
+ ) {
+ yield entry as Deno.DirEntry;
+ }
+ });
+
+ const root = new URL("file:///mock/keys/");
+ const keys = [];
+
+ for await (
+ const key of createKeysFromFs(
+ root,
+ { ...DEFAULT_KEY_DISCOVERY_RULES, recursive: true },
+ )
+ ) {
+ keys.push(key);
+ }
+
+ assertEquals(keys.length, 2);
+ });
+});