mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import {
|
|||
|
|
isSafeMessageError,
|
||
|
|
isToolInputError,
|
||
|
|
markToolInputError,
|
||
|
|
SafeError,
|
||
|
|
ToolInputError,
|
||
|
|
} from "@snapotter/shared";
|
||
|
|
import { describe, expect, it } from "vitest";
|
||
|
|
|
||
|
|
describe("SafeError", () => {
|
||
|
|
it("carries a constant message, kind, and code", () => {
|
||
|
|
const err = new SafeError("Storage directory is not writable", {
|
||
|
|
kind: "operational",
|
||
|
|
code: "EACCES",
|
||
|
|
statusCode: 503,
|
||
|
|
});
|
||
|
|
expect(err.message).toBe("Storage directory is not writable");
|
||
|
|
expect(err.kind).toBe("operational");
|
||
|
|
expect(err.code).toBe("EACCES");
|
||
|
|
expect(err.statusCode).toBe(503);
|
||
|
|
expect(isSafeMessageError(err)).toBe(true);
|
||
|
|
});
|
||
|
|
it("defaults kind to operational and detects via marker not instanceof", () => {
|
||
|
|
const copy = Object.assign(new Error("x"), { isSafeMessage: true, message: "x" });
|
||
|
|
expect(new SafeError("m").kind).toBe("operational");
|
||
|
|
expect(isSafeMessageError(copy)).toBe(true);
|
||
|
|
expect(isSafeMessageError(new Error("m"))).toBe(false);
|
||
|
|
expect(isSafeMessageError(null)).toBe(false);
|
||
|
|
});
|
||
|
|
it("rejects a marked plain object that is not an Error", () => {
|
||
|
|
expect(isSafeMessageError({ isSafeMessage: true })).toBe(false);
|
||
|
|
});
|
||
|
|
it("leaves code and statusCode undefined by default", () => {
|
||
|
|
const s = new SafeError("m");
|
||
|
|
expect(s.code).toBeUndefined();
|
||
|
|
expect(s.statusCode).toBeUndefined();
|
||
|
|
});
|
||
|
|
it("threads cause through to the Error constructor", () => {
|
||
|
|
const inner = new Error("inner");
|
||
|
|
expect(new SafeError("m", { cause: inner }).cause).toBe(inner);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("ToolInputError", () => {
|
||
|
|
it("is marked and 400-shaped", () => {
|
||
|
|
const err = new ToolInputError("Column 2 must be numeric");
|
||
|
|
expect(err.statusCode).toBe(400);
|
||
|
|
expect(isToolInputError(err)).toBe(true);
|
||
|
|
});
|
||
|
|
it("markToolInputError flags a foreign error without changing its class", () => {
|
||
|
|
const raw = new Error("ffmpeg: received no packets");
|
||
|
|
expect(isToolInputError(raw)).toBe(false);
|
||
|
|
markToolInputError(raw);
|
||
|
|
expect(isToolInputError(raw)).toBe(true);
|
||
|
|
expect(raw).toBeInstanceOf(Error);
|
||
|
|
});
|
||
|
|
it("rejects non-Error values", () => {
|
||
|
|
expect(isToolInputError(null)).toBe(false);
|
||
|
|
expect(isToolInputError("x")).toBe(false);
|
||
|
|
});
|
||
|
|
it("markToolInputError returns the same reference", () => {
|
||
|
|
const e = new Error("y");
|
||
|
|
expect(markToolInputError(e)).toBe(e);
|
||
|
|
});
|
||
|
|
});
|