Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ["<rootDir>/src/test/setup.ts"],
transform: {
"^.+\\.tsx?$": "ts-jest"
},
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openstax/ui-components",
"version": "1.22.4",
"version": "1.23.1",
"license": "MIT",
"sideEffects": [
"**/*.css"
Expand Down Expand Up @@ -83,13 +83,13 @@
"react-dom": "^17.0.2",
"react-is": "^16.8.0",
"react-test-renderer": "^17.0.2",
"sentry-testkit": "^5.0.5",
"sentry-testkit": "^6.4.1",
"styled-components": "^5.3.5",
"ts-jest": "^28.0.5",
"typescript": "^4.7.4"
"typescript": "^5.9.3"
},
"dependencies": {
"@sentry/react": "^7.120.3",
"@sentry/react": "^10.60.0",
"classnames": "^2.3.1",
"dompurify": "^3.0.1",
"react-aria": "^3.37.0",
Expand Down
8 changes: 8 additions & 0 deletions src/components/Error.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import { render, act } from '@testing-library/react';
import { Error } from './Error';
import * as Sentry from '@sentry/react';

// Sentry v8+ exposes its named exports as read-only getters, so they can no longer
// be replaced with jest.spyOn directly. Mock the module to make lastEventId spyable.
jest.mock('@sentry/react', () => ({
__esModule: true,
...jest.requireActual('@sentry/react'),
lastEventId: jest.fn(),
}));

describe('Error', () => {
it('matches snapshot', () => {
const tree = renderer.create(
Expand Down
12 changes: 12 additions & 0 deletions src/components/ErrorBoundary.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import * as Sentry from '@sentry/react';
import { findByTestId } from '../test/utils';
import { SessionExpiredError } from '@openstax/ts-utils/errors';

// Sentry v8+ exposes its named exports as read-only getters, so they can no longer
// be replaced with jest.spyOn directly. Mock the module to make lastEventId spyable
// while keeping the real init/captureException so the testkit transport still works.
jest.mock('@sentry/react', () => ({
__esModule: true,
...jest.requireActual('@sentry/react'),
lastEventId: jest.fn(),
}));

const { testkit, sentryTransport } = sentryTestkit();

const ErrorComponent = () => { throw new Error('Test Error') };
Expand All @@ -21,6 +30,9 @@ describe('ErrorBoundary', () => {

afterEach(() => {
jest.resetAllMocks();
// Sentry v8+ flushes captured events to the testkit transport synchronously,
// so reports leak between tests unless we clear them after each one.
testkit.reset();
});

it('renders children', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ErrorBoundary.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const Fallback_GenericError_Custom = () => {
fallback={(props) => (
<>
<h2>This is a custom error fallback</h2>
<p>{props && props.error.toString()}</p>
<p>{props && String(props.error)}</p>
{props && props.resetError ? <button onClick={props && props.resetError}>Reset</button> : null}
</>
)}>
Expand Down
8 changes: 5 additions & 3 deletions src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Sentry from '@sentry/react';
import type { ErrorBoundaryProps } from '@sentry/react';
import React from 'react';
import { Error as ErrorComponent, ErrorPropTypes } from './Error';
import type { ErrorBoundaryProps } from '@sentry/react/types/errorboundary';
import { ErrorContext } from '../contexts';
import { SentryError } from '../types';
import { getTypeFromError } from '../utils';
Expand Down Expand Up @@ -94,9 +94,11 @@ export const ErrorBoundary = ({
fallback={renderElement}
onError={(error, componentStack, eventId) => {
setError({
error,
// Sentry v8+ types this callback's error as `unknown`; a React error boundary
// always hands us a thrown Error here.
error: error as Error,
// If the error is a custom error from ts-utils, use the custom type instead of 'Error'
type: getTypeFromError(error),
type: getTypeFromError(error as Error),
componentStack,
eventId
});
Expand Down
8 changes: 8 additions & 0 deletions src/sentryLogger/sentryLog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { createSentryLogger } from './sentryLog';
import * as Sentry from "@sentry/react";
import { Level, Logger } from '@openstax/ts-utils/services/logger';

// Sentry v8+ exposes its named exports as read-only getters, so they can no longer
// be replaced with jest.spyOn directly. Mock the module to make addBreadcrumb spyable.
jest.mock('@sentry/react', () => ({
__esModule: true,
...jest.requireActual('@sentry/react'),
addBreadcrumb: jest.fn(),
}));

describe('createConsoleLogger', () => {
let logFn: jest.SpyInstance;
let logger: Logger;
Expand Down
10 changes: 10 additions & 0 deletions src/test/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// jsdom does not implement parts of the Performance API that the Sentry v8+
// browserTracingIntegration relies on (web-vitals instrumentation calls
// performance.getEntriesByType on init). Provide no-op shims so Sentry.init
// works under the jsdom test environment; real browsers supply these natively.
if (typeof performance.getEntriesByType !== 'function') {
performance.getEntriesByType = () => [];
}
if (typeof performance.getEntriesByName !== 'function') {
performance.getEntriesByName = () => [];
}
Loading
Loading