@critters/next
Version:
Secure bug reporting library for Next.js applications
125 lines (124 loc) • 5.59 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Unit tests for React components
*/
const react_1 = __importDefault(require("react"));
const components_1 = require("../src/components");
const reporter_1 = require("../src/reporter");
// Mock Critters reporter
jest.mock("../src/reporter", () => ({
Critters: {
getInstance: jest.fn().mockReturnValue({
catch: jest.fn().mockResolvedValue({
success: true,
message: "Error reported successfully",
reportId: "mock-report-id",
}),
}),
},
}));
describe("ErrorBoundary", () => {
// Store original console methods
const originalConsoleError = console.error;
beforeAll(() => {
// Suppress console.error for expected error boundary tests
console.error = jest.fn();
});
afterAll(() => {
// Restore original console methods
console.error = originalConsoleError;
});
beforeEach(() => {
// Reset mock calls before each test
jest.clearAllMocks();
});
it("should render children when no error occurs", () => {
// Mock component rendering
let renderedOutput = null;
// Simulate React's rendering process
const TestComponent = () => react_1.default.createElement("div", null, "Test Content");
// Simulate successful rendering
renderedOutput = (react_1.default.createElement(components_1.ErrorBoundary, null,
react_1.default.createElement(TestComponent, null))).props.children;
// Verify children are rendered normally
expect(renderedOutput).toEqual(react_1.default.createElement(TestComponent, null));
});
it("should render fallback UI when error occurs", () => {
// Mock component that throws error
const ErrorComponent = () => {
throw new Error("Test error");
};
// Create error boundary instance
const boundary = new components_1.ErrorBoundary({
children: react_1.default.createElement(ErrorComponent, null),
fallback: react_1.default.createElement("div", null, "Error occurred!"),
});
// Manually trigger componentDidCatch
boundary.componentDidCatch(new Error("Test error"), {
componentStack: "\n at ErrorComponent",
});
// Check that error state is set
expect(boundary.state.hasError).toBe(true);
// Get the rendered output after error
const renderedOutput = boundary.render();
// Expect fallback UI to be rendered
expect(renderedOutput).toEqual(react_1.default.createElement("div", null, "Error occurred!"));
});
it("should call onError prop when provided", () => {
// Mock error handler
const mockOnError = jest.fn();
// Create error boundary instance
const boundary = new components_1.ErrorBoundary({
children: react_1.default.createElement("div", null, "Test"),
onError: mockOnError,
});
// Mock error and component stack
const error = new Error("Test error");
const errorInfo = { componentStack: "\n at TestComponent" };
// Manually trigger componentDidCatch
boundary.componentDidCatch(error, errorInfo);
// Verify onError was called with error and errorInfo
expect(mockOnError).toHaveBeenCalledWith(error, errorInfo);
});
it("should report error to Critters service", () => {
// Create error boundary instance
const boundary = new components_1.ErrorBoundary({
children: react_1.default.createElement("div", null, "Test"),
});
// Mock error and component stack
const error = new Error("Test error");
const errorInfo = { componentStack: "\n at TestComponent" };
// Manually trigger componentDidCatch
boundary.componentDidCatch(error, errorInfo);
// Verify error was reported to Critters
expect(reporter_1.Critters.getInstance().catch).toHaveBeenCalledWith(error, expect.objectContaining({
type: "react_error_boundary",
component_stack: "\n at TestComponent",
}));
});
});
describe("withErrorBoundary", () => {
it("should wrap component with ErrorBoundary", () => {
// Create a test component
const TestComponent = () => react_1.default.createElement("div", null, "Test Content");
// Wrap with error boundary
const WrappedComponent = (0, components_1.withErrorBoundary)(TestComponent, {
fallback: react_1.default.createElement("div", null, "Error fallback"),
});
// Check that the returned component has the expected displayName
// Using type assertion to fix TypeScript error
expect(WrappedComponent.displayName).toBe("withErrorBoundary(TestComponent)");
// Simulate rendering (simplified)
const wrappedElement = WrappedComponent({});
// Check structure - should be an ErrorBoundary with our component inside
expect(wrappedElement.type).toBe(components_1.ErrorBoundary);
expect(wrappedElement.props.fallback).toEqual(react_1.default.createElement("div", null, "Error fallback"));
// The child should be our component
const childElement = wrappedElement.props.children;
expect(childElement.type).toBe(TestComponent);
});
});