Promote to UAT: GRO-2094 React bootstrap error instrumentation (#45)
Co-authored-by: The Dogfather <20+gb_dogfather@noreply.git.farh.net> Co-committed-by: The Dogfather <20+gb_dogfather@noreply.git.farh.net>
This commit was merged in pull request #45.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import { Component } from "react";
|
||||
import type { ErrorInfo, ReactNode } from "react";
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Top-level ErrorBoundary — renders the error visibly so the actual exception
|
||||
* appears in the DOM (and therefore in the Playwright snapshot) instead of
|
||||
* React 18+ unmounting the entire tree to a blank `<div id="root">`.
|
||||
*
|
||||
* Background: GRO-2094. The bundle was executing but never painting, with
|
||||
* the failure swallowed. Surfacing the error here is the first step; the
|
||||
* real fix is in the underlying component that threw.
|
||||
*/
|
||||
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
state: ErrorBoundaryState = { error: null };
|
||||
|
||||
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||
return { error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, info: ErrorInfo): void {
|
||||
// Also surface to the console — this is what the test harness greps for.
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[ErrorBoundary] Uncaught render error:", error, info);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
const err = this.state.error;
|
||||
return (
|
||||
<div
|
||||
data-testid="error-boundary"
|
||||
style={{
|
||||
padding: "2rem",
|
||||
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
||||
color: "#7f1d1d",
|
||||
background: "#fef2f2",
|
||||
minHeight: "100vh",
|
||||
boxSizing: "border-box",
|
||||
}}
|
||||
>
|
||||
<h1 style={{ fontSize: 18, margin: "0 0 0.5rem" }}>Something went wrong</h1>
|
||||
<p style={{ margin: "0 0 1rem", color: "#991b1b" }}>
|
||||
The app failed to render. The full error is shown below — please share this
|
||||
output when reporting the bug.
|
||||
</p>
|
||||
<pre
|
||||
data-testid="error-boundary-message"
|
||||
style={{
|
||||
whiteSpace: "pre-wrap",
|
||||
wordBreak: "break-word",
|
||||
background: "#fff",
|
||||
border: "1px solid #fecaca",
|
||||
borderRadius: 6,
|
||||
padding: "0.75rem 1rem",
|
||||
margin: 0,
|
||||
fontSize: 13,
|
||||
lineHeight: 1.4,
|
||||
}}
|
||||
>
|
||||
{err.name}: {err.message}
|
||||
{"\n\n"}
|
||||
{err.stack ?? "(no stack)"}
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user