import { describe, it, expect } from "vitest"; import { PdsHttpError, PdsSessionMissingError } from "../automations/errors.js"; import { classifyPdsError, isRecordAlreadyExists } from "./pds-errors.js"; const NSID = "com.atproto.repo.createRecord"; describe("classifyPdsError", () => { it("maps a missing session to auth", () => { expect(classifyPdsError(new PdsSessionMissingError("did:plc:x")).kind).toBe("auth"); }); it("maps an HTTP 401 to auth, both typed and untyped", () => { expect(classifyPdsError(new PdsHttpError(NSID, 401, "nope", null)).kind).toBe("auth"); expect(classifyPdsError(new Error("PDS x failed (401): nope")).kind).toBe("auth"); }); it("maps a 429 to rate-limited with the reset time in milliseconds", () => { expect(classifyPdsError(new PdsHttpError(NSID, 429, "slow down", 1_800_000_000))).toEqual({ kind: "rate-limited", resetAt: 1_800_000_000_000, message: expect.stringContaining("(429)"), }); }); it("maps a 5xx and a thrown network error to retryable", () => { expect(classifyPdsError(new PdsHttpError(NSID, 503, "down", null)).kind).toBe("retryable"); expect(classifyPdsError(new Error("fetch failed: ECONNRESET")).kind).toBe("retryable"); }); it("maps any other 4xx to terminal", () => { expect(classifyPdsError(new PdsHttpError(NSID, 400, "InvalidRecord", null))).toEqual({ kind: "terminal", status: 400, message: expect.any(String), }); }); }); describe("isRecordAlreadyExists", () => { it("recognizes a create conflict for an existing record key", () => { expect( isRecordAlreadyExists( new PdsHttpError(NSID, 400, '{"message":"Record already exists"}', null), ), ).toBe(true); expect(isRecordAlreadyExists(new PdsHttpError(NSID, 400, "InvalidRecord", null))).toBe(false); expect(isRecordAlreadyExists(new Error("Record already exists"))).toBe(false); }); });