import { env } from "cloudflare:workers"; import { expect } from "vitest"; import { createControlPlaneDb } from "@/worker/db/d1/client"; import { getSubjectById } from "@/worker/db/d1/repository"; import { createDavFixture, davRequest } from "@tests/worker/helpers/dav"; import { fetchWorker } from "@tests/worker/helpers/http"; type DavFixture = Awaited>; export function uid(): string { return `${crypto.randomUUID()}@example.test`; } export function vcard(input: { uid: string; fn: string; email?: string; tel?: string }): string { return [ "BEGIN:VCARD", "VERSION:4.0", `UID:${input.uid}`, `FN:${input.fn}`, `N:${input.fn.split(" ").at(-1) ?? input.fn};${input.fn.split(" ")[0] ?? ""};;;`, input.email ? `EMAIL:${input.email}` : null, input.tel ? `TEL:${input.tel}` : null, "END:VCARD", "", ] .filter((line): line is string => line !== null) .join("\r\n"); } export async function storageIdFor(subjectId: string): Promise { const subject = await getSubjectById(createControlPlaneDb(env.DAV_CONTROL_PLANE), subjectId); if (!subject) throw new Error(`Missing subject ${subjectId}`); return subject.storageId; } export function propfindBody(props: string): string { return `${props}`; } export function reportBody(name: string, body: string): string { return name === "sync-collection" ? `${body}` : `${body}`; } export function syncCollectionBody(prevToken: string, props = ""): string { return reportBody( "sync-collection", `${prevToken}1${props}`, ); } export async function syncToken(fixture: DavFixture): Promise { const response = await fetchWorker( davRequest(fixture, "/addressbooks/default/", { method: "REPORT", headers: { "content-type": "application/xml" }, body: syncCollectionBody(""), }), ); expect(response.status).toBe(207); const token = /([^<]+)<\/D:sync-token>/.exec(await response.text())?.[1]; if (!token) throw new Error("Missing sync-token in baseline sync-collection response"); return token; } export async function propfindSyncToken(fixture: DavFixture, href = "/addressbooks/default/") { const response = await fetchWorker( davRequest(fixture, href, { method: "PROPFIND", headers: { depth: "0", "content-type": "application/xml" }, body: propfindBody(""), }), ); expect(response.status).toBe(207); const token = /([^<]+)<\/D:sync-token>/.exec(await response.text())?.[1]; if (!token) throw new Error("Missing sync-token in PROPFIND response"); return token; }