Skip to content

Commit 1811525

Browse files
committed
export helper
1 parent 0f35883 commit 1811525

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

packages/react-router/src/client/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ export {
3131
isNavigateHookInvoked,
3232
type CreateSentryClientInstrumentationOptions,
3333
} from './createClientInstrumentation';
34+
35+
export { sentryOnError } from './sentryOnError';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { captureException } from '@sentry/core';
2+
import { captureReactException } from '@sentry/react';
3+
4+
/**
5+
* A handler function for React Router's `onError` prop on `HydratedRouter`.
6+
*
7+
* Reports errors to Sentry.
8+
*
9+
* @example (entry.client.tsx)
10+
* ```tsx
11+
* import { sentryOnError } from '@sentry/react-router';
12+
*
13+
* startTransition(() => {
14+
* hydrateRoot(
15+
* document,
16+
* <HydratedRouter onError={sentryOnError} />
17+
* );
18+
* });
19+
* ```
20+
*/
21+
export function sentryOnError(
22+
error: unknown,
23+
{
24+
errorInfo,
25+
}: {
26+
errorInfo?: React.ErrorInfo;
27+
},
28+
): void {
29+
if (errorInfo) {
30+
captureReactException(error, errorInfo);
31+
} else {
32+
captureException(error);
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import * as SentryCore from '@sentry/core';
2+
import * as SentryReact from '@sentry/react';
3+
import { afterEach, describe, expect, it, vi } from 'vitest';
4+
import { sentryOnError } from '../../src/client/sentryOnError';
5+
6+
const captureReactExceptionSpy = vi.spyOn(SentryReact, 'captureReactException').mockReturnValue('mock-event-id');
7+
const captureExceptionSpy = vi.spyOn(SentryCore, 'captureException').mockReturnValue('mock-event-id');
8+
9+
describe('sentryOnError', () => {
10+
afterEach(() => {
11+
vi.clearAllMocks();
12+
});
13+
14+
it('calls captureReactException when errorInfo is provided', () => {
15+
const error = new Error('test error');
16+
const errorInfo = { componentStack: '<TestComponent>\n<App>' };
17+
18+
sentryOnError(error, {
19+
errorInfo,
20+
});
21+
22+
expect(captureReactExceptionSpy).toHaveBeenCalledWith(error, errorInfo);
23+
expect(captureExceptionSpy).not.toHaveBeenCalled();
24+
});
25+
26+
it('calls captureException when errorInfo is undefined', () => {
27+
const error = new Error('loader error');
28+
29+
sentryOnError(error, {});
30+
31+
expect(captureExceptionSpy).toHaveBeenCalledWith(error);
32+
expect(captureReactExceptionSpy).not.toHaveBeenCalled();
33+
});
34+
});

0 commit comments

Comments
 (0)