From b67ed29b4353f04219e77165be09bbac9d264903 Mon Sep 17 00:00:00 2001
From: Diksha Dabhole
Date: Fri, 12 Jun 2026 16:43:05 +0530
Subject: [PATCH] test(error): add empty-fallback checks and tests for root
error boundaries
---
app/error.empty-fallback.test.tsx | 124 +++++++++++++++++++++++
app/error.tsx | 10 +-
app/global-error.empty-fallback.test.tsx | 72 +++++++++++++
app/global-error.tsx | 5 +-
4 files changed, 206 insertions(+), 5 deletions(-)
create mode 100644 app/error.empty-fallback.test.tsx
create mode 100644 app/global-error.empty-fallback.test.tsx
diff --git a/app/error.empty-fallback.test.tsx b/app/error.empty-fallback.test.tsx
new file mode 100644
index 000000000..1bed148da
--- /dev/null
+++ b/app/error.empty-fallback.test.tsx
@@ -0,0 +1,124 @@
+// app/error.empty-fallback.test.tsx
+
+import { describe, expect, it, vi, beforeEach } from 'vitest';
+import { render, screen, fireEvent } from '@testing-library/react';
+import '@testing-library/jest-dom/vitest';
+
+vi.mock('next/link', () => ({
+ default: ({
+ children,
+ ...props
+ }: React.AnchorHTMLAttributes & { children: React.ReactNode }) => (
+ {children}
+ ),
+}));
+
+vi.mock('sonner', () => ({
+ toast: {
+ success: vi.fn(),
+ error: vi.fn(),
+ },
+}));
+
+import ErrorBoundary from './error';
+
+describe('Root Error Boundary - Empty & Missing Input Fallbacks', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ // Mock clipboard API
+ Object.defineProperty(navigator, 'clipboard', {
+ value: {
+ writeText: vi.fn().mockResolvedValue(undefined),
+ },
+ configurable: true,
+ writable: true,
+ });
+ });
+
+ it('renders successfully when error is null', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(
+ screen.getByRole('heading', {
+ name: /Looks like an exception was thrown in the application/i,
+ })
+ ).toBeInTheDocument();
+ expect(screen.getByText('Unknown runtime error occurred.')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error is undefined', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(
+ screen.getByRole('heading', {
+ name: /Looks like an exception was thrown in the application/i,
+ })
+ ).toBeInTheDocument();
+ expect(screen.getByText('Unknown runtime error occurred.')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error is an empty object', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(
+ screen.getByRole('heading', {
+ name: /Looks like an exception was thrown in the application/i,
+ })
+ ).toBeInTheDocument();
+ expect(screen.getByText('Unknown runtime error occurred.')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error has no message property', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(
+ screen.getByRole('heading', {
+ name: /Looks like an exception was thrown in the application/i,
+ })
+ ).toBeInTheDocument();
+ expect(screen.getByText('Unknown runtime error occurred.')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error message is an empty string', () => {
+ expect(() => render()).not.toThrow();
+
+ expect(
+ screen.getByRole('heading', {
+ name: /Looks like an exception was thrown in the application/i,
+ })
+ ).toBeInTheDocument();
+ expect(screen.getByText('Unknown runtime error occurred.')).toBeInTheDocument();
+ });
+
+ it('renders interactive elements and triggers actions correctly in fallback state', async () => {
+ const resetMock = vi.fn();
+ render();
+
+ // Check actions
+ const retryButton = screen.getByRole('button', { name: /git fetch/i });
+ expect(retryButton).toBeInTheDocument();
+ fireEvent.click(retryButton);
+ expect(resetMock).toHaveBeenCalledOnce();
+
+ const homeLink = screen.getByRole('link', { name: /Return to main/i });
+ expect(homeLink).toBeInTheDocument();
+
+ // Check clipboard copy fallback behavior
+ const terminalContainer = screen.getByText('commitpulse — error').closest('div');
+ expect(terminalContainer).toBeInTheDocument();
+ if (terminalContainer) {
+ fireEvent.click(terminalContainer);
+ expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
+ expect.stringContaining('Unknown exception in the render tree.')
+ );
+ }
+ });
+});
diff --git a/app/error.tsx b/app/error.tsx
index 4667ff618..3910cd0e3 100644
--- a/app/error.tsx
+++ b/app/error.tsx
@@ -11,16 +11,20 @@ export default function ErrorBoundary({
reset: () => void;
}) {
useEffect(() => {
- console.error(error);
+ if (error) {
+ console.error(error);
+ }
}, [error]);
+ const errorMessage = error?.message || '';
+
const terminalContent = `git status
fatal: Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
Error details:
- ${error.message || 'Unknown exception in the render tree.'}`;
+ ${errorMessage || 'Unknown exception in the render tree.'}`;
const handleCopy = async () => {
try {
@@ -88,7 +92,7 @@ export default function ErrorBoundary({
fatal: Your branch and 'origin/main' have diverged.
- {error.message || 'Unknown runtime error occurred.'}
+ {errorMessage || 'Unknown runtime error occurred.'}
diff --git a/app/global-error.empty-fallback.test.tsx b/app/global-error.empty-fallback.test.tsx
new file mode 100644
index 000000000..54c8b3373
--- /dev/null
+++ b/app/global-error.empty-fallback.test.tsx
@@ -0,0 +1,72 @@
+// app/global-error.empty-fallback.test.tsx
+
+import { describe, expect, it, vi } from 'vitest';
+import { render, screen, fireEvent } from '@testing-library/react';
+import '@testing-library/jest-dom/vitest';
+
+vi.mock('next/link', () => ({
+ default: ({
+ children,
+ ...props
+ }: React.AnchorHTMLAttributes & { children: React.ReactNode }) => (
+ {children}
+ ),
+}));
+
+import GlobalError from './global-error';
+
+describe('Global Error Page - Empty & Missing Input Fallbacks', () => {
+ it('renders successfully when error is null', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(screen.getByText('500')).toBeInTheDocument();
+ expect(screen.getByText('A critical error occurred at the root level.')).toBeInTheDocument();
+ expect(screen.getByText('Unknown global error')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error is undefined', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(screen.getByText('500')).toBeInTheDocument();
+ expect(screen.getByText('Unknown global error')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error is an empty object', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(screen.getByText('500')).toBeInTheDocument();
+ expect(screen.getByText('Unknown global error')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error has no message property', () => {
+ expect(() =>
+ render()
+ ).not.toThrow();
+
+ expect(screen.getByText('500')).toBeInTheDocument();
+ expect(screen.getByText('Unknown global error')).toBeInTheDocument();
+ });
+
+ it('renders successfully when error message is an empty string', () => {
+ expect(() => render()).not.toThrow();
+
+ expect(screen.getByText('500')).toBeInTheDocument();
+ expect(screen.getByText('Unknown global error')).toBeInTheDocument();
+ });
+
+ it('renders interactive elements and triggers reset correctly in fallback state', () => {
+ const resetMock = vi.fn();
+ render();
+
+ const retryButton = screen.getByRole('button', { name: /Try again/i });
+ expect(retryButton).toBeInTheDocument();
+ fireEvent.click(retryButton);
+ expect(resetMock).toHaveBeenCalledOnce();
+ });
+});
diff --git a/app/global-error.tsx b/app/global-error.tsx
index f8d4c1a8d..acdb867b2 100644
--- a/app/global-error.tsx
+++ b/app/global-error.tsx
@@ -1,5 +1,4 @@
'use client';
-import Link from 'next/link';
export default function GlobalError({
error,
@@ -8,6 +7,8 @@ export default function GlobalError({
error: Error & { digest?: string };
reset: () => void;
}) {
+ const errorMessage = error?.message || '';
+
return (
@@ -17,7 +18,7 @@ export default function GlobalError({
A critical error occurred at the root level.
- {error.message || 'Unknown global error'}
+ {errorMessage || 'Unknown global error'}