tftsr-devops_investigation/src/components/ErrorBoundary.test.tsx
Shaun Arman f7b4e591f9 fix(performance): resolve memory leaks and add polish features
- Fix LogStreamPanel event listener cleanup with synchronous unlisten
- Fix eventBus async-unsafe unsubscribe with proper error handling
- Fix KubernetesPage infinite loading by resetting state on section change
- Add ErrorBoundary component with reset capability
- Add Badge component with multiple variants
- Add ResourceDetailsDrawer for slide-out details panel
- Add useFavorites hook with localStorage persistence
- Add useKeyboardShortcuts hook for declarative shortcuts
- Add comprehensive test coverage for all new components/hooks
- Add keyboard shortcuts documentation to README
- Wrap KubernetesPage with ErrorBoundary for crash recovery
- Install react-window for virtual scrolling support

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-09 13:28:30 -05:00

85 lines
2.6 KiB
TypeScript

import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ErrorBoundary } from "./ErrorBoundary";
const ThrowError = ({ shouldThrow }: { shouldThrow: boolean }) => {
if (shouldThrow) {
throw new Error("Test error");
}
return <div>Content</div>;
};
describe("ErrorBoundary", () => {
it("renders children when there is no error", () => {
render(
<ErrorBoundary>
<ThrowError shouldThrow={false} />
</ErrorBoundary>
);
expect(screen.getByText("Content")).toBeInTheDocument();
});
it("renders error UI when child throws", () => {
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
render(
<ErrorBoundary>
<ThrowError shouldThrow={true} />
</ErrorBoundary>
);
expect(screen.getByText("Something went wrong")).toBeInTheDocument();
expect(screen.getByText(/Test error/)).toBeInTheDocument();
consoleError.mockRestore();
});
it("resets error when reset button is clicked", async () => {
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
const user = userEvent.setup();
const { rerender } = render(
<ErrorBoundary>
<ThrowError shouldThrow={true} />
</ErrorBoundary>
);
expect(screen.getByText("Something went wrong")).toBeInTheDocument();
await user.click(screen.getByRole("button", { name: /Reset Component/i }));
rerender(
<ErrorBoundary>
<ThrowError shouldThrow={false} />
</ErrorBoundary>
);
expect(screen.getByText("Content")).toBeInTheDocument();
consoleError.mockRestore();
});
it("uses custom fallback when provided", () => {
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
const customFallback = (error: Error, resetError: () => void) => (
<div>
<p>Custom error: {error.message}</p>
<button onClick={resetError}>Custom Reset</button>
</div>
);
render(
<ErrorBoundary fallback={customFallback}>
<ThrowError shouldThrow={true} />
</ErrorBoundary>
);
expect(screen.getByText("Custom error: Test error")).toBeInTheDocument();
expect(screen.getByText("Custom Reset")).toBeInTheDocument();
consoleError.mockRestore();
});
it("logs error to console", () => {
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
render(
<ErrorBoundary>
<ThrowError shouldThrow={true} />
</ErrorBoundary>
);
expect(consoleError).toHaveBeenCalled();
consoleError.mockRestore();
});
});