Collection of utility functions for Jest testing framework
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Enhanced error handling with custom stack trace management for better test debugging. The ErrorWithStack class provides improved error reporting by excluding specific functions from stack traces and optimizing stack trace capture.
Error class that captures stack traces while excluding a specific callsite function, providing cleaner and more useful stack traces for debugging.
/**
* Error class with custom stack trace callsite exclusion
*/
class ErrorWithStack extends Error {
/**
* Creates an Error with enhanced stack trace handling
* @param message - Error message (can be undefined)
* @param callsite - Function to exclude from stack trace
* @param stackLimit - Optional stack trace limit for performance
*/
constructor(
message: string | undefined,
callsite: (...args: Array<any>) => unknown,
stackLimit?: number
);
}Usage Examples:
import { ErrorWithStack } from "jest-util";
// Basic usage - exclude current function from stack
function validateTestInput(input: any) {
if (input == null) {
throw new ErrorWithStack("Input cannot be null", validateTestInput);
}
}
// The stack trace will start from the caller of validateTestInput,
// not from within validateTestInput itself
// Jest assertion helper
function expectToBeTruthy(value: any, message?: string) {
if (!value) {
throw new ErrorWithStack(
message || `Expected ${value} to be truthy`,
expectToBeTruthy
);
}
}
// Usage in test
test("should validate user input", () => {
const userData = null;
expectToBeTruthy(userData, "User data is required");
// Stack trace points to this line, not inside expectToBeTruthy
});
// Custom test framework utilities
function createAssertion(name: string, predicate: (value: any) => boolean) {
return function assertion(value: any) {
if (!predicate(value)) {
throw new ErrorWithStack(
`Assertion failed: ${name}`,
assertion
);
}
};
}
const shouldBePositive = createAssertion("should be positive", x => x > 0);
shouldBePositive(-5); // Stack trace excludes the assertion function
// Performance optimization with stack limit
function createPerformantError(message: string, callsite: Function) {
return new ErrorWithStack(message, callsite, 10); // Limit stack to 10 frames
}Advanced Usage:
// Test helper with multiple levels
function deepTestHelper(value: any) {
return intermediateHelper(value);
}
function intermediateHelper(value: any) {
if (typeof value !== "string") {
// Exclude the original calling function, not intermediate ones
throw new ErrorWithStack("Expected string", deepTestHelper);
}
}
// Custom error factory
class ValidationError extends ErrorWithStack {
constructor(field: string, value: any, validator: Function) {
super(
`Validation failed for field '${field}' with value: ${value}`,
validator
);
this.name = "ValidationError";
}
}
function validateEmail(email: string) {
if (!email.includes("@")) {
throw new ValidationError("email", email, validateEmail);
}
}
// Error aggregation for test suites
function collectTestErrors(tests: Array<() => void>): ErrorWithStack[] {
const errors: ErrorWithStack[] = [];
tests.forEach((test, index) => {
try {
test();
} catch (error) {
if (error instanceof ErrorWithStack) {
errors.push(error);
} else {
errors.push(new ErrorWithStack(
`Test ${index} failed: ${error.message}`,
collectTestErrors
));
}
}
});
return errors;
}Stack Trace Behavior:
// Without ErrorWithStack
function regularError() {
throw new Error("Regular error");
}
function callRegularError() {
regularError(); // This will show in stack trace
}
// Stack trace shows:
// Error: Regular error
// at regularError (file.js:2:9)
// at callRegularError (file.js:6:3)
// at ...
// With ErrorWithStack
function betterError() {
throw new ErrorWithStack("Better error", betterError);
}
function callBetterError() {
betterError(); // ErrorWithStack excludes betterError from trace
}
// Stack trace shows:
// ErrorWithStack: Better error
// at callBetterError (file.js:16:3)
// at ...
// Notice betterError function is excludedPerformance Features:
stackLimit parameter prevents excessive stack captureError.captureStackTrace() when available (V8 engines)Error.stackTraceLimit during capture for better tracesIntegration with Testing Frameworks:
// Jest custom matcher
expect.extend({
toBeValidUser(received) {
if (!received || !received.id || !received.name) {
throw new ErrorWithStack(
`Expected valid user object, received: ${JSON.stringify(received)}`,
this.toBeValidUser
);
}
return { pass: true, message: () => "User is valid" };
}
});
// Chai-style assertion
function expect(value: any) {
return {
toBe(expected: any) {
if (value !== expected) {
throw new ErrorWithStack(
`Expected ${value} to be ${expected}`,
this.toBe
);
}
}
};
}When using ErrorWithStack, follow these patterns for clear error messages:
// Good error messages
throw new ErrorWithStack(
`Expected array to have length 3, but got length ${arr.length}`,
validateArrayLength
);
throw new ErrorWithStack(
`User validation failed: missing required field 'email'`,
validateUser
);
// Less helpful messages
throw new ErrorWithStack("Invalid input", someFunction);
throw new ErrorWithStack("Error occurred", someFunction);