Skip to content

Commit

Permalink
Merge pull request #104 from ed-pilots-network/root-error-boundary
Browse files Browse the repository at this point in the history
Setup root error boundary to gracefully handle all unhandled errors
  • Loading branch information
nitishdhar authored Sep 15, 2023
2 parents 40846fc + 49900c8 commit ead3d59
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 7 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,26 @@ yarn lint
yarn test
```

### Clean

Removes the `.next` and `node_modules` folders and runs `yarn install` to clean up the local workspace

```bash
yarn clean
```

### Take Screenshots

If you are making changes that impact the UI, ensure to test the change on different view ports. Run the following to auto capture screenshots when tests run. Note that this only runs when you run this command locally.

#### Take screenshots of home page

```bash
yarn capture-screenshots
```

#### Take screenshots of a specific page

```bash
PAGE_PATH=/commodities yarn capture-screenshots
```
Expand Down Expand Up @@ -116,4 +127,5 @@ yarn dev
- Docker

### 🌐 Useful Tools
- [ColorKit](https://colorkit.co/color-palette-generator/272f33-4e5d66-9BB9CB-cddce5-e6eef2/) - Color Palette Generator

- [ColorKit](https://colorkit.co/color-palette-generator/272f33-4e5d66-9BB9CB-cddce5-e6eef2/) - Color Palette Generator
35 changes: 35 additions & 0 deletions app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use client';

import { Button, Center, Flex, Heading, Text } from '@chakra-ui/react';
import layoutConfig from './_config/layout';

export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<Center width="100%">
<Flex
flexDirection="column"
alignItems="center"
gap="24px"
maxWidth={layoutConfig.maxWidth}
>
<Heading
as="h1"
size={{ base: 'md', md: 'lg', lg: 'lg' }}
marginX={{ base: 'auto', md: '0', lg: '0' }}
>
Something went wrong!
</Heading>
<Text as="samp">{error.message}</Text>
<Button type="button" variant="outline" onClick={() => reset()}>
Try again
</Button>
</Flex>
</Center>
);
}
10 changes: 5 additions & 5 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client';

import NextLink from 'next/link';
import { Link, Center, Flex, Heading } from '@chakra-ui/react';
import GetColor from '@/app/_hooks/colorSelector';
import { Button, Center, Flex, Heading } from '@chakra-ui/react';
import layoutConfig from './_config/layout';

export default function NotFound() {
return (
Expand All @@ -11,7 +11,7 @@ export default function NotFound() {
flexDirection="column"
alignItems="center"
gap="24px"
maxWidth="1500px"
maxWidth={layoutConfig.maxWidth}
>
<Heading
as="h1"
Expand All @@ -21,9 +21,9 @@ export default function NotFound() {
404 - Page Not Found
</Heading>
<NextLink href="/" passHref>
<Link color={GetColor('textSelected')} href="#">
<Button type="button" variant="outline">
Go back Home
</Link>
</Button>
</NextLink>
</Flex>
</Center>
Expand Down
7 changes: 7 additions & 0 deletions app/playground/client-error/page.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use client';

const PageClient = () => {
throw new Error('This is a simulated client rendering error.');
};

export default PageClient;
8 changes: 8 additions & 0 deletions app/playground/client-error/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import PageClient from './page.client';

// Avoid statically building this page during build.
export const dynamic = 'force-dynamic';

export default async function Page() {
return <PageClient />;
}
4 changes: 3 additions & 1 deletion app/playground/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from './_api';
import { ICommodity, IPost } from '../_types';

// Force dynamic fetching during runtime for playground
// Avoid statically building this page during build.
export const dynamic = 'force-dynamic';

export const metadata: Metadata = {
Expand All @@ -23,12 +23,14 @@ export default async function Page() {
posts = await getPostsForCategoryFromMockApi();
} catch (error) {
console.error('Failed to fetch posts data:', error);
throw error;
}

try {
commodity = await getCommodityByNameFromStagingApi('Wine');
} catch (error) {
console.error('Failed to fetch commodity data:', error);
throw error;
}

return <PageClient posts={posts} commodity={commodity} />;
Expand Down
6 changes: 6 additions & 0 deletions app/playground/server-error/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Avoid statically building this page during build.
export const dynamic = 'force-dynamic';

export default async function Page() {
throw new Error('This is a simulated server rendering error.');
}
22 changes: 22 additions & 0 deletions tests/playwright/playground/error-boundary.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { test, expect } from '@playwright/test';

test('server rendering errors should get caught and gracefully render error', async ({
page,
}) => {
await page.goto('/playground/server-error');
await expect(page.locator('h1')).toContainText('Something went wrong!');
// Error messages for server rendering get replaced for security during builds
await expect(page.locator('samp')).toContainText(
'An error occurred in the Server Components render.',
);
});

test('client rendering errors should get caught and gracefully render error', async ({
page,
}) => {
await page.goto('/playground/client-error');
await expect(page.locator('h1')).toContainText('Something went wrong!');
await expect(page.locator('samp')).toContainText(
'This is a simulated client rendering error',
);
});

0 comments on commit ead3d59

Please sign in to comment.