File tree 5 files changed +109
-4
lines changed
5 files changed +109
-4
lines changed Original file line number Diff line number Diff line change
1
+ import { CircleAlert } from "lucide-react" ;
2
+ import { Header } from "./Header" ;
3
+ import { Card } from "./ui/card" ;
4
+
5
+ export function Error ( ) {
6
+ return (
7
+ < div className = "w-screen h-screen flex flex-col items-center justify-center" >
8
+ < div className = "flex-0 w-full" >
9
+ < Header hasError />
10
+ </ div >
11
+ < div className = "h-24 flex flex-col flex-1 justify-center" >
12
+ < Card className = "p-8 flex flex-col items-center" >
13
+ < CircleAlert className = "text-red-600 mb-2 size-16" />
14
+ < div className = "text-xl font-semibold text-gray-600 text-center" >
15
+ An error occurred
16
+ </ div >
17
+ < div className = "text-md mb-4 text-gray-600 text-center text-balance" >
18
+ If this issue persists, please reach out to us on{ " " }
19
+ < a
20
+ className = "underline text-gray-700"
21
+ href = "https://discord.gg/stacklok"
22
+ rel = "noopener noreferrer"
23
+ target = "_blank"
24
+ >
25
+ Discord
26
+ </ a > { " " }
27
+ or open a new{ " " }
28
+ < a
29
+ className = "underline text-gray-700"
30
+ href = "https://github.com/stacklok/codegate/issues/new"
31
+ rel = "noopener noreferrer"
32
+ target = "_blank"
33
+ >
34
+ Github issue
35
+ </ a >
36
+ </ div >
37
+ </ Card >
38
+ </ div >
39
+ </ div >
40
+ ) ;
41
+ }
Original file line number Diff line number Diff line change
1
+ import type { ReactNode } from "react" ;
2
+ import { Component } from "react" ;
3
+
4
+ interface Props {
5
+ children ?: ReactNode ;
6
+ fallback : ReactNode ;
7
+ }
8
+
9
+ interface State {
10
+ hasError : boolean ;
11
+ }
12
+
13
+ export default class ErrorBoundary extends Component < Props , State > {
14
+ public state : State = {
15
+ hasError : false ,
16
+ } ;
17
+
18
+ public static getDerivedStateFromError ( ) : State {
19
+ return { hasError : true } ;
20
+ }
21
+
22
+ public componentDidCatch ( ) {
23
+ // this should log the error to a service like Sentry
24
+ }
25
+
26
+ public render ( ) {
27
+ if ( this . state . hasError ) {
28
+ return this . props . fallback ;
29
+ }
30
+
31
+ return this . props . children ;
32
+ }
33
+ }
Original file line number Diff line number Diff line change @@ -2,12 +2,17 @@ import { Link } from "react-router-dom";
2
2
import { SidebarTrigger } from "./ui/sidebar" ;
3
3
import { Separator } from "./ui/separator" ;
4
4
5
- export function Header ( ) {
5
+ export function Header ( { hasError } : { hasError ?: boolean } ) {
6
6
return (
7
7
< header className = "flex-shrink-0 h-16 px-3 items-center flex w-full bg-teal-25 opacity-1 border-b-blue-200 border-b" >
8
8
< div className = "flex items-center flex-1" >
9
- < SidebarTrigger />
10
- < Separator orientation = "vertical" className = "h-8 mx-3" />
9
+ { ! hasError && (
10
+ < >
11
+ < SidebarTrigger />
12
+ < Separator orientation = "vertical" className = "h-8 mx-3" />
13
+ </ >
14
+ ) }
15
+
11
16
< nav className = "mx-1 flex" >
12
17
< Link to = "/" >
13
18
< h1 className = "text-2xl w-max flex font-semibold" >
Original file line number Diff line number Diff line change
1
+ import { render } from "@/lib/test-utils" ;
2
+ import { screen } from "@testing-library/react" ;
3
+ import { describe , expect , it , vi } from "vitest" ;
4
+ import ErrorBoundary from "../ErrorBoundary" ;
5
+ import { Error } from "../Error" ;
6
+
7
+ const ErrorComponent = ( ) => {
8
+ throw Error ( ) ;
9
+ } ;
10
+
11
+ describe ( "ErrorBoundary" , ( ) => {
12
+ it ( "renders fallback when a child throws an error" , ( ) => {
13
+ vi . spyOn ( console , "error" ) . mockImplementation ( ( ) => { } ) ;
14
+ render (
15
+ < ErrorBoundary fallback = { < Error /> } >
16
+ < ErrorComponent />
17
+ </ ErrorBoundary > ,
18
+ ) ;
19
+
20
+ expect ( screen . getByText ( / a n e r r o r o c c u r r e d / i) ) . toBeVisible ( ) ;
21
+ } ) ;
22
+ } ) ;
Original file line number Diff line number Diff line change @@ -4,12 +4,16 @@ import "./index.css";
4
4
import App from "./App.tsx" ;
5
5
import { BrowserRouter } from "react-router-dom" ;
6
6
import { SidebarProvider } from "./components/ui/sidebar.tsx" ;
7
+ import ErrorBoundary from "./components/ErrorBoundary.tsx" ;
8
+ import { Error } from "./components/Error.tsx" ;
7
9
8
10
createRoot ( document . getElementById ( "root" ) ! ) . render (
9
11
< StrictMode >
10
12
< BrowserRouter >
11
13
< SidebarProvider >
12
- < App />
14
+ < ErrorBoundary fallback = { < Error /> } >
15
+ < App />
16
+ </ ErrorBoundary >
13
17
</ SidebarProvider >
14
18
</ BrowserRouter >
15
19
</ StrictMode >
You can’t perform that action at this time.
0 commit comments