Something went wrong. Try again.
CLI for FastMail via JMAP
Something went wrong. Try again.
5.4 kB · 182 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183import { afterEach, describe, expect, spyOn, test } from "bun:test";import { JmapClient } from "./client.ts";import { getThreads } from "./thread.ts";import { JMAP_MAIL_CAPABILITY } from "./types.ts";
// Mock session based on JMAP specconst mockSession = { username: "test@fastmail.com", apiUrl: "https://api.fastmail.com/jmap/api/", downloadUrl: "https://api.fastmail.com/jmap/download/{accountId}/{blobId}/{name}", uploadUrl: "https://api.fastmail.com/jmap/upload/{accountId}/", eventSourceUrl: "https://api.fastmail.com/jmap/eventsource/", state: "session-state-123", accounts: { "account-123": { name: "test@fastmail.com", isPersonal: true, isReadOnly: false, accountCapabilities: { [JMAP_MAIL_CAPABILITY]: {}, }, }, }, primaryAccounts: { [JMAP_MAIL_CAPABILITY]: "account-123", }, capabilities: { [JMAP_MAIL_CAPABILITY]: {}, },};
function createMockResponse(data: unknown, status = 200): Response { return new Response(JSON.stringify(data), { status, headers: { "Content-Type": "application/json" }, });}
describe("Thread methods", () => { let fetchSpy: ReturnType<typeof spyOn>;
afterEach(() => { if (fetchSpy) { fetchSpy.mockRestore(); } });
describe("getThreads", () => { test("gets thread with emailIds", async () => { let callCount = 0; fetchSpy = spyOn(globalThis, "fetch").mockImplementation((async ( _url: unknown, options: RequestInit | undefined, ) => { callCount++; if (callCount === 1) { return createMockResponse(mockSession); } const body = JSON.parse(options?.body as string); const callId = body.methodCalls[0][2]; return createMockResponse({ methodResponses: [ [ "Thread/get", { accountId: "account-123", state: "thread-state-1", list: [ { id: "thread-1", emailIds: ["email-1", "email-2", "email-3"], }, ], notFound: [], }, callId, ], ], sessionState: "session-state-123", }); }) as unknown as typeof fetch);
const client = new JmapClient({ token: "test-token" }); const result = await getThreads(client, { ids: ["thread-1"] });
expect(result.accountId).toBe("account-123"); expect(result.list).toHaveLength(1); expect(result.list[0]?.id).toBe("thread-1"); expect(result.list[0]?.emailIds).toEqual([ "email-1", "email-2", "email-3", ]); expect(result.notFound).toEqual([]); });
test("handles notFound for missing threads", async () => { let callCount = 0; fetchSpy = spyOn(globalThis, "fetch").mockImplementation((async ( _url: unknown, options: RequestInit | undefined, ) => { callCount++; if (callCount === 1) { return createMockResponse(mockSession); } const body = JSON.parse(options?.body as string); const callId = body.methodCalls[0][2]; return createMockResponse({ methodResponses: [ [ "Thread/get", { accountId: "account-123", state: "thread-state-2", list: [], notFound: ["thread-999"], }, callId, ], ], sessionState: "session-state-123", }); }) as unknown as typeof fetch);
const client = new JmapClient({ token: "test-token" }); const result = await getThreads(client, { ids: ["thread-999"] });
expect(result.list).toHaveLength(0); expect(result.notFound).toEqual(["thread-999"]); });
test("gets multiple threads", async () => { let callCount = 0; fetchSpy = spyOn(globalThis, "fetch").mockImplementation((async ( _url: unknown, options: RequestInit | undefined, ) => { callCount++; if (callCount === 1) { return createMockResponse(mockSession); } const body = JSON.parse(options?.body as string); const callId = body.methodCalls[0][2]; return createMockResponse({ methodResponses: [ [ "Thread/get", { accountId: "account-123", state: "thread-state-3", list: [ { id: "thread-1", emailIds: ["email-1"], }, { id: "thread-2", emailIds: ["email-2", "email-3"], }, ], notFound: [], }, callId, ], ], sessionState: "session-state-123", }); }) as unknown as typeof fetch);
const client = new JmapClient({ token: "test-token" }); const result = await getThreads(client, { ids: ["thread-1", "thread-2"], });
expect(result.list).toHaveLength(2); expect(result.list[0]?.emailIds).toHaveLength(1); expect(result.list[1]?.emailIds).toHaveLength(2); }); });});