@zerothrow/expect
Version:
Shared test matcher logic for ZeroThrow Result types
142 lines • 4.92 kB
JavaScript
// src/index.ts
function isResult(value) {
return value !== null && typeof value === "object" && "ok" in value && typeof value.ok === "boolean" && (value.ok === true ? "value" in value : "error" in value);
}
function formatError(error) {
if (!error) return "undefined";
if (error instanceof Error) {
const parts = [`${error.name}: ${error.message}`];
if ("code" in error) parts.push(`(code: ${error.code})`);
return parts.join(" ");
}
if (typeof error === "object" && error !== null) {
const obj = error;
if ("code" in obj || "message" in obj) {
const parts = [];
if (obj["code"]) parts.push(`code: ${obj["code"]}`);
if (obj["message"]) parts.push(`message: ${obj["message"]}`);
return `{ ${parts.join(", ")} }`;
}
}
return JSON.stringify(error);
}
function toBeOkMatcher(received, _context) {
const pass = isResult(received) && received.ok === true;
if (pass) {
return {
message: () => `expected Result not to be Ok, but it was Ok with value: ${JSON.stringify(received.value)}`,
pass: true
};
} else {
const error = isResult(received) && !received.ok ? received.error : received;
return {
message: () => `expected Result to be Ok, but it was Err with error: ${formatError(error)}`,
pass: false
};
}
}
function toBeOkWithMatcher(received, expected, context) {
if (!isResult(received)) {
return {
message: () => `expected Result type, but received ${typeof received}`,
pass: false
};
}
if (!received.ok) {
return {
message: () => `expected Result to be Ok with value ${JSON.stringify(expected)}, but it was Err with error: ${formatError(received.error)}`,
pass: false
};
}
const actual = received.value;
const pass = context.equals(actual, expected);
return {
message: () => pass ? `expected Result not to be Ok with value ${JSON.stringify(expected)}` : `expected Result to be Ok with value ${JSON.stringify(expected)}, but was Ok with value ${JSON.stringify(actual)}`,
pass
};
}
function toBeErrMatcher(received, _context) {
const pass = isResult(received) && received.ok === false;
if (pass) {
return {
message: () => `expected Result not to be Err, but it was Err with error: ${formatError(received.error)}`,
pass: true
};
} else {
const value = isResult(received) && received.ok ? received.value : received;
return {
message: () => `expected Result to be Err, but it was Ok with value: ${JSON.stringify(value)}`,
pass: false
};
}
}
function toBeErrWithMatcher(received, expected, context) {
if (!isResult(received)) {
return {
message: () => `expected Result type, but received ${typeof received}`,
pass: false
};
}
if (received.ok) {
return {
message: () => `expected Result to be Err, but it was Ok with value: ${JSON.stringify(received.value)}`,
pass: false
};
}
const actualError = received.error;
let pass = false;
if (expected instanceof Error) {
pass = context.equals(actualError, expected);
} else {
pass = true;
if (expected.code !== void 0 && actualError.code !== expected.code) {
pass = false;
}
if (expected.message !== void 0 && actualError.message !== expected.message) {
pass = false;
}
}
return {
message: () => pass ? `expected Result not to be Err with ${formatError(expected)}` : `expected Result to be Err with ${formatError(expected)}, but was Err with ${formatError(actualError)}`,
pass
};
}
function toHaveErrorCodeMatcher(received, code) {
if (!isResult(received) || received.ok) {
return {
message: () => `expected Result to be Err with code "${code}", but it was ${isResult(received) && received.ok ? "Ok" : "not a Result"}`,
pass: false
};
}
const actualCode = received.error.code;
const pass = actualCode === code;
return {
message: () => pass ? `expected Result not to have error code "${code}"` : `expected Result to have error code "${code}", but had "${actualCode}"`,
pass
};
}
function toHaveErrorMessageMatcher(received, message) {
if (!isResult(received) || received.ok) {
return {
message: () => `expected Result to be Err with message ${message}, but it was ${isResult(received) && received.ok ? "Ok" : "not a Result"}`,
pass: false
};
}
const actualMessage = received.error.message;
const pass = typeof message === "string" ? actualMessage === message : message.test(actualMessage);
return {
message: () => pass ? `expected Result not to have error message ${message}` : `expected Result to have error message ${message}, but had "${actualMessage}"`,
pass
};
}
export {
formatError,
isResult,
toBeErrMatcher,
toBeErrWithMatcher,
toBeOkMatcher,
toBeOkWithMatcher,
toHaveErrorCodeMatcher,
toHaveErrorMessageMatcher
};
//# sourceMappingURL=index.js.map