Skip to content

Commit f8a0347

Browse files
committed
chore: finish new stories
1 parent f8c5827 commit f8a0347

File tree

5 files changed

+98
-266
lines changed

5 files changed

+98
-266
lines changed

site/src/components/ErrorBoundary/ErrorBoundary.tsx

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { GlobalErrorBoundaryInner } from "./GlobalErrorBoundary";
3+
import { within } from "@testing-library/react";
4+
import type { ErrorResponse } from "react-router-dom";
5+
import { expect, userEvent } from "@storybook/test";
6+
7+
/**
8+
* React Router ErrorResponses have a "hidden" internal field that RR uses to
9+
* detect whether something is a loader error. The property doesn't exist in
10+
* the type information, but it does exist at runtime, and we need it to mock
11+
* out the story correctly
12+
*/
13+
type FullErrorResponse = Readonly<
14+
ErrorResponse & {
15+
internal: true;
16+
}
17+
>;
18+
19+
const meta = {
20+
title: "components/GlobalErrorBoundary",
21+
component: GlobalErrorBoundaryInner,
22+
} satisfies Meta<typeof GlobalErrorBoundaryInner>;
23+
24+
export default meta;
25+
type Story = StoryObj<typeof meta>;
26+
27+
export const VanillaJavascriptError: Story = {
28+
args: {
29+
error: new Error("Something blew up :("),
30+
},
31+
play: async ({ canvasElement, args }) => {
32+
const error = args.error as Error;
33+
const canvas = within(canvasElement);
34+
const showErrorButton = canvas.getByRole("button", {
35+
name: /Show error/i,
36+
});
37+
await userEvent.click(showErrorButton);
38+
39+
// Verify that error message content is now on screen; defer to
40+
// accessible name queries as much as possible
41+
canvas.getByRole("heading", { name: /Error/i });
42+
43+
const p = canvas.getByTestId("description");
44+
expect(p).toHaveTextContent(error.message);
45+
46+
const codeBlock = canvas.getByTestId("code");
47+
expect(codeBlock).toHaveTextContent(error.name);
48+
expect(codeBlock).toHaveTextContent(error.message);
49+
},
50+
};
51+
52+
export const ReactRouterErrorResponse: Story = {
53+
args: {
54+
error: {
55+
internal: true,
56+
status: 500,
57+
statusText: "Aww, beans!",
58+
data: { message: "beans" },
59+
} satisfies FullErrorResponse,
60+
},
61+
play: async ({ canvasElement, args }) => {
62+
const error = args.error as FullErrorResponse;
63+
const canvas = within(canvasElement);
64+
const showErrorButton = canvas.getByRole("button", {
65+
name: /Show error/i,
66+
});
67+
await userEvent.click(showErrorButton);
68+
69+
// Verify that error message content is now on screen; defer to
70+
// accessible name queries as much as possible
71+
const header = canvas.getByRole("heading", { name: /Aww, beans!/i });
72+
expect(header).toHaveTextContent(String(error.status));
73+
74+
const codeBlock = canvas.getByTestId("code");
75+
const content = codeBlock.innerText;
76+
const parsed = JSON.parse(content);
77+
expect(parsed).toEqual(error.data);
78+
},
79+
};
80+
81+
export const UnparsableError: Story = {
82+
args: {
83+
error: class WellThisIsDefinitelyWrong {},
84+
},
85+
play: async ({ canvasElement }) => {
86+
const canvas = within(canvasElement);
87+
const showErrorButton = canvas.queryByRole("button", {
88+
name: /Show error/i,
89+
});
90+
expect(showErrorButton).toBe(null);
91+
},
92+
};

site/src/components/ErrorBoundary/GlobalErrorBoundary.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,22 +131,23 @@ const ErrorStack: FC<ErrorStackProps> = ({ error }) => {
131131
{isRouteErrorResponse(error) ? (
132132
<>
133133
<h2 className="text-base font-bold text-content-primary m-0">
134-
HTTP error code {error.status}
134+
HTTP {error.status} - {error.statusText}
135135
</h2>
136-
<p className="pb-4 leading-5 m-0">{error.statusText}</p>
137136
<pre className="m-0 py-2 px-0 overflow-x-auto text-xs">
138-
<code>{serializeDataAsJson(error.data)}</code>
137+
<code data-testid="code">{serializeDataAsJson(error.data)}</code>
139138
</pre>
140139
</>
141140
) : (
142141
<>
143142
<h2 className="text-base font-bold text-content-primary m-0">
144143
{error.name}
145144
</h2>
146-
<p className="pb-4 leading-5 m-0">{error.message}</p>
145+
<p data-testid="description" className="pb-4 leading-5 m-0">
146+
{error.message}
147+
</p>
147148
{error.stack && (
148149
<pre className="m-0 py-2 px-0 overflow-x-auto text-xs">
149-
<code>{error.stack}</code>
150+
<code data-testid="code">{error.stack}</code>
150151
</pre>
151152
)}
152153
</>

site/src/components/ErrorBoundary/RuntimeErrorState.stories.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.

site/src/components/ErrorBoundary/RuntimeErrorState.tsx

Lines changed: 0 additions & 198 deletions
This file was deleted.

0 commit comments

Comments
 (0)