diff --git a/jest.config.js b/jest.config.js index 902b0a443..f851092fd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,13 +4,17 @@ module.exports = { setupFilesAfterEnv: ['jest-extended/all', '/test/mockConsole.ts'], globals: { __DEV__: true, - 'ts-jest': { - tsConfig: './tsconfig.json', - diagnostics: false, - }, }, - moduleFileExtensions: ['ts', 'tsx', 'js'], + transform: { + '^.+\\.jsx$': 'babel-jest', + '^.+\\.tsx?$': [ + 'ts-jest', + { + tsconfig: 'tsconfig.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], testPathIgnorePatterns: ['/test/e2e/', '/test/tools/', '/test/react-native/versions'], - testEnvironment: 'node', testMatch: ['**/*.test.(ts|tsx)'], }; diff --git a/package.json b/package.json index 112526392..54fc0cb57 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "@sentry-internal/eslint-plugin-sdk": "8.11.0", "@sentry-internal/typescript": "8.11.0", "@sentry/wizard": "3.16.3", + "@testing-library/react-native": "^12.5.3", "@types/jest": "^29.5.3", "@types/node": "^20.9.3", "@types/react": "^18.2.64", diff --git a/src/js/profiling/integration.ts b/src/js/profiling/integration.ts index 584b00041..0859b1697 100644 --- a/src/js/profiling/integration.ts +++ b/src/js/profiling/integration.ts @@ -36,7 +36,7 @@ export const hermesProfilingIntegration: IntegrationFn = () => { startTimestampNs: number; } | undefined; - let _currentProfileTimeout: number | undefined; + let _currentProfileTimeout: ReturnType | undefined; let isReady: boolean = false; const setupOnce = (): void => { diff --git a/src/js/tools/metroconfig.ts b/src/js/tools/metroconfig.ts index 6e5854475..992292491 100644 --- a/src/js/tools/metroconfig.ts +++ b/src/js/tools/metroconfig.ts @@ -1,5 +1,6 @@ import { logger } from '@sentry/utils'; -import type { MetroConfig, MixedOutput, Module, ReadOnlyGraph } from 'metro'; +import type { MixedOutput, Module, ReadOnlyGraph } from 'metro'; +import type { MetroConfig } from 'metro-config'; import * as process from 'process'; import { env } from 'process'; diff --git a/src/js/tracing/reactnavigation.ts b/src/js/tracing/reactnavigation.ts index 7948af888..2639cd740 100644 --- a/src/js/tracing/reactnavigation.ts +++ b/src/js/tracing/reactnavigation.ts @@ -242,7 +242,6 @@ export const reactNavigationIntegration = ({ } const routeHasBeenSeen = recentRouteKeys.includes(route.key); - const latestTtidSpan = !routeHasBeenSeen && enableTimeToInitialDisplay && diff --git a/test/client.test.ts b/test/client.test.ts index dee71e776..86dcdadba 100644 --- a/test/client.test.ts +++ b/test/client.test.ts @@ -2,7 +2,7 @@ import * as mockedtimetodisplaynative from './tracing/mockedtimetodisplaynative' jest.mock('../src/js/tracing/timetodisplaynative', () => mockedtimetodisplaynative); import { defaultStackParser } from '@sentry/browser'; -import type { Envelope, Event, Outcome, Transport } from '@sentry/types'; +import type { Envelope, Event, Outcome, Transport, TransportMakeRequestResponse } from '@sentry/types'; import { rejectedSyncPromise, SentryError } from '@sentry/utils'; import * as RN from 'react-native'; @@ -104,7 +104,6 @@ describe('Tests ReactNativeClient', () => { }); await expect(client.eventFromMessage('test')).resolves.toBeDefined(); - // @ts-expect-error: Is Mocked await expect(RN.LogBox.ignoreLogs).toBeCalled(); }); @@ -133,7 +132,7 @@ describe('Tests ReactNativeClient', () => { }); test('use custom transport function', async () => { - const mySend = (_request: Envelope) => Promise.resolve(); + const mySend = (_request: Envelope): Promise => Promise.resolve({}); const myFlush = (timeout?: number) => Promise.resolve(Boolean(timeout)); const myCustomTransportFn = (): Transport => ({ send: mySend, @@ -408,7 +407,7 @@ describe('Tests ReactNativeClient', () => { describe('event data enhancement', () => { test('event contains sdk default information', async () => { - const mockedSend = jest.fn, [Envelope]>().mockResolvedValue(undefined); + const mockedSend = jest.fn, [Envelope]>().mockResolvedValue({}); const mockedTransport = (): Transport => ({ send: mockedSend, flush: jest.fn().mockResolvedValue(true), @@ -436,7 +435,7 @@ describe('Tests ReactNativeClient', () => { describe('normalizes events', () => { test('handles circular input', async () => { - const mockedSend = jest.fn, [Envelope]>(); + const mockedSend = jest.fn, [Envelope]>().mockResolvedValue({}); const mockedTransport = (): Transport => ({ send: mockedSend, flush: jest.fn().mockResolvedValue(true), @@ -469,7 +468,7 @@ describe('Tests ReactNativeClient', () => { describe('clientReports', () => { test('does not send client reports if disabled', () => { - const mockTransportSend = jest.fn((_envelope: Envelope) => Promise.resolve()); + const mockTransportSend = jest.fn, [Envelope]>().mockResolvedValue({}); const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: EXAMPLE_DSN, @@ -488,7 +487,7 @@ describe('Tests ReactNativeClient', () => { }); test('send client reports on event envelope', () => { - const mockTransportSend = jest.fn((_envelope: Envelope) => Promise.resolve()); + const mockTransportSend = jest.fn, [Envelope]>().mockResolvedValue({}); const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: EXAMPLE_DSN, @@ -522,7 +521,7 @@ describe('Tests ReactNativeClient', () => { }); test('does not send empty client report', () => { - const mockTransportSend = jest.fn((_envelope: Envelope) => Promise.resolve()); + const mockTransportSend = jest.fn, [Envelope]>().mockResolvedValue({}); const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: EXAMPLE_DSN, diff --git a/test/integrations/spotlight.test.ts b/test/integrations/spotlight.test.ts index 13bdfaf6c..306580d66 100644 --- a/test/integrations/spotlight.test.ts +++ b/test/integrations/spotlight.test.ts @@ -1,11 +1,10 @@ import type { HttpRequestEventMap } from '@mswjs/interceptors'; import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'; import type { Client, Envelope } from '@sentry/types'; -import { XMLHttpRequest } from 'xmlhttprequest'; import { spotlightIntegration } from '../../src/js/integrations/spotlight'; -globalThis.XMLHttpRequest = XMLHttpRequest; +globalThis.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; const requestListener = jest.fn(); const interceptor = new XMLHttpRequestInterceptor(); interceptor.on('request', requestListener); diff --git a/test/mockConsole.ts b/test/mockConsole.ts index ac2409d0e..025071ce1 100644 --- a/test/mockConsole.ts +++ b/test/mockConsole.ts @@ -6,3 +6,5 @@ global.console = { warn: jest.fn(), error: jest.fn(), }; + +export {}; diff --git a/test/mockWrapper.ts b/test/mockWrapper.ts index 360211a40..3cbb789ba 100644 --- a/test/mockWrapper.ts +++ b/test/mockWrapper.ts @@ -53,6 +53,9 @@ const NATIVE: MockInterface = { fetchNativeStackFramesBy: jest.fn(), initNativeReactNavigationNewFrameTracking: jest.fn(), + + captureReplay: jest.fn(), + getCurrentReplayId: jest.fn(), }; NATIVE.isNativeAvailable.mockReturnValue(true); @@ -74,6 +77,8 @@ NATIVE.stopProfiling.mockReturnValue(null); NATIVE.fetchNativePackageName.mockReturnValue('mock-native-package-name'); NATIVE.fetchNativeStackFramesBy.mockReturnValue(null); NATIVE.initNativeReactNavigationNewFrameTracking.mockReturnValue(Promise.resolve()); +NATIVE.captureReplay.mockResolvedValue(null); +NATIVE.getCurrentReplayId.mockReturnValue(null); export const getRNSentryModule = jest.fn(); diff --git a/test/scopeSync.test.ts b/test/scopeSync.test.ts index e6f7e161f..fc0635aa9 100644 --- a/test/scopeSync.test.ts +++ b/test/scopeSync.test.ts @@ -179,6 +179,7 @@ describe('ScopeSync', () => { it('addBreadcrumb', () => { expect(SentryCore.getIsolationScope().addBreadcrumb).not.toBe(addBreadcrumbScopeSpy); + SentryCore.getIsolationScope().getLastBreadcrumb = jest.fn(() => ({ message: 'test' })); SentryCore.addBreadcrumb({ message: 'test' }); expect(NATIVE.addBreadcrumb).toHaveBeenCalledExactlyOnceWith(expect.objectContaining({ message: 'test' })); diff --git a/test/sdk.test.ts b/test/sdk.test.ts index 6fcea1ac6..e01a7b4a8 100644 --- a/test/sdk.test.ts +++ b/test/sdk.test.ts @@ -1,11 +1,3 @@ -jest.spyOn(logger, 'error'); -jest.mock('../src/js/wrapper', () => jest.requireActual('./mockWrapper')); -jest.mock('../src/js/utils/environment'); -jest.mock('@sentry/core', () => ({ - ...jest.requireActual('@sentry/core'), - initAndBind: jest.fn(), -})); - import { initAndBind } from '@sentry/core'; import { makeFetchTransport } from '@sentry/react'; import type { BaseTransportOptions, ClientOptions, Integration, Scope } from '@sentry/types'; @@ -19,6 +11,14 @@ import { getDefaultEnvironment, isExpoGo, notWeb } from '../src/js/utils/environ import { NATIVE } from './mockWrapper'; import { firstArg, secondArg } from './testutils'; +jest.spyOn(logger, 'error'); +jest.mock('../src/js/wrapper', () => jest.requireActual('./mockWrapper')); +jest.mock('../src/js/utils/environment'); +jest.mock('@sentry/core', () => ({ + ...jest.requireActual('@sentry/core'), + initAndBind: jest.fn(), +})); + describe('Tests the SDK functionality', () => { beforeEach(() => { (NATIVE.isNativeAvailable as jest.Mock).mockImplementation(() => true); diff --git a/test/sdk.withclient.test.ts b/test/sdk.withclient.test.ts index 1ed8c1c30..1e3cb131a 100644 --- a/test/sdk.withclient.test.ts +++ b/test/sdk.withclient.test.ts @@ -1,11 +1,11 @@ -jest.spyOn(logger, 'error'); - import { setCurrentClient } from '@sentry/core'; import { logger } from '@sentry/utils'; import { flush } from '../src/js/sdk'; import { getDefaultTestClientOptions, TestClient } from './mocks/client'; +jest.spyOn(logger, 'error'); + describe('Tests the SDK functionality', () => { let client: TestClient; diff --git a/test/testutils.ts b/test/testutils.ts index e73b64a68..4548eef09 100644 --- a/test/testutils.ts +++ b/test/testutils.ts @@ -1,9 +1,6 @@ -import { Transaction } from '@sentry/core'; import type { Session, Transport, UserFeedback } from '@sentry/types'; import { rejectedSyncPromise } from '@sentry/utils'; -import { getBlankTransactionContext } from '../src/js/tracing/utils'; - export type MockInterface = { [K in keyof T]: T[K] extends (...args: infer A) => infer B ? jest.Mock : T[K]; } & T; @@ -13,15 +10,6 @@ export function mockFunction any>(fn: T): jest.Moc return fn as jest.MockedFunction; } -export const getMockTransaction = (name: string): Transaction => { - const transaction = new Transaction(getBlankTransactionContext(name)); - - // Assume it's sampled - transaction.sampled = true; - - return transaction; -}; - export const firstArg = 0; export const secondArg = 1; export const envelopeHeader = 0; diff --git a/test/tools/metroconfig.test.ts b/test/tools/metroconfig.test.ts index a0ee9533f..53ab6952e 100644 --- a/test/tools/metroconfig.test.ts +++ b/test/tools/metroconfig.test.ts @@ -6,12 +6,17 @@ jest.mock('fs', () => { }; }); +import type { getDefaultConfig } from 'expo/metro-config'; import * as fs from 'fs'; import type { MetroConfig } from 'metro'; import * as path from 'path'; import * as process from 'process'; -import { withSentryBabelTransformer, withSentryFramesCollapsed } from '../../src/js/tools/metroconfig'; +import { + getSentryExpoConfig, + withSentryBabelTransformer, + withSentryFramesCollapsed, +} from '../../src/js/tools/metroconfig'; type MetroFrame = Parameters['symbolicator']>['customizeFrame']>[0]; @@ -20,6 +25,13 @@ describe('metroconfig', () => { jest.clearAllMocks(); }); + test('getSentryExpoConfig keeps compatible interface with Expos getDefaultConfig', () => { + const acceptsExpoDefaultConfigFactory = (_factory: typeof getDefaultConfig): void => { + expect(true).toBe(true); + }; + acceptsExpoDefaultConfigFactory(getSentryExpoConfig); + }); + describe('withSentryFramesCollapsed', () => { test('adds customizeFrames if undefined ', () => { const config = withSentryFramesCollapsed({}); diff --git a/test/tracing/integrations/nativeframes.test.ts b/test/tracing/integrations/nativeframes.test.ts index bcab5bcb2..7c483b0b0 100644 --- a/test/tracing/integrations/nativeframes.test.ts +++ b/test/tracing/integrations/nativeframes.test.ts @@ -156,7 +156,7 @@ describe('NativeFramesInstrumentation', () => { }); it('does not set measurements on transactions without startFrames', async () => { - const startFrames = null; + const startFrames: null = null; const finishFrames = { totalFrames: 200, slowFrames: 40, @@ -191,7 +191,7 @@ describe('NativeFramesInstrumentation', () => { slowFrames: 20, frozenFrames: 5, }; - const finishFrames = null; + const finishFrames: null = null; mockFunction(NATIVE.fetchNativeFrames).mockResolvedValueOnce(startFrames).mockResolvedValueOnce(finishFrames); await startSpan({ name: 'test' }, async () => { diff --git a/test/tracing/integrations/stallTracking/stalltracking.background.test.ts b/test/tracing/integrations/stallTracking/stalltracking.background.test.ts index c8174e3c3..2358c77d1 100644 --- a/test/tracing/integrations/stallTracking/stalltracking.background.test.ts +++ b/test/tracing/integrations/stallTracking/stalltracking.background.test.ts @@ -2,9 +2,20 @@ import type { AppStateStatus } from 'react-native'; import { stallTrackingIntegration } from '../../../../src/js/tracing/integrations/stalltracking'; +type StallTrackingWithTestProperties = ReturnType & { + isTracking: boolean; + _internalState: { + isBackground: boolean; + lastIntervalMs: number; + timeout: ReturnType | null; + iteration: () => void; + backgroundEventListener: (event: string) => void; + }; +}; + describe('BackgroundEventListener', () => { it('Stall tracking should set _isBackground to false, update _lastIntervalMs, and call _iteration when state is active and _timeout is not null', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; const LOOP_TIMEOUT_INTERVAL_MS = 500; // Change this value based on your actual interval value const currentTime = Date.now(); stallTracking['_internalState']['lastIntervalMs'] = currentTime; @@ -18,14 +29,14 @@ describe('BackgroundEventListener', () => { jest.runOnlyPendingTimers(); // Fast-forward the timer to execute the timeout function }); it('Stall tracking should set _isBackground to true when state is not active', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; stallTracking['_internalState']['isBackground'] = false; stallTracking['_internalState']['backgroundEventListener']('background' as AppStateStatus); // Check if _isBackground is set to true expect(stallTracking['_internalState']['isBackground']).toBe(true); }); it('Stall tracking should not call _iteration when state is active but _timeout is null', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; stallTracking['_internalState']['timeout'] = null; // Mock _iteration stallTracking['_internalState']['iteration'] = jest.fn(); @@ -35,7 +46,7 @@ describe('BackgroundEventListener', () => { expect(stallTracking['_internalState']['iteration']).not.toBeCalled(); }); it('Stall tracking should call _iteration when state is active and _timeout is defined', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; stallTracking['_internalState']['timeout'] = setTimeout(() => {}, 500); // Mock _iteration stallTracking['_internalState']['iteration'] = jest.fn(); // Create a fake timeout to simulate a running interval diff --git a/test/tracing/integrations/stallTracking/stalltracking.iteration.test.ts b/test/tracing/integrations/stallTracking/stalltracking.iteration.test.ts index 95b8506a0..53c6c8443 100644 --- a/test/tracing/integrations/stallTracking/stalltracking.iteration.test.ts +++ b/test/tracing/integrations/stallTracking/stalltracking.iteration.test.ts @@ -1,8 +1,21 @@ import { stallTrackingIntegration } from '../../../../src/js/tracing/integrations/stalltracking'; +type StallTrackingWithTestProperties = ReturnType & { + isTracking: boolean; + _internalState: { + isBackground: boolean; + lastIntervalMs: number; + timeout: ReturnType | null; + stallCount: number; + totalStallTime: number; + statsByTransaction: Map; + iteration: () => void; + }; +}; + describe('Iteration', () => { it('Stall tracking does not set _timeout when isTracking is false', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; stallTracking['isTracking'] = false; stallTracking['_internalState']['isBackground'] = false; stallTracking['_internalState']['lastIntervalMs'] = Date.now() - 1000; // Force a timeout @@ -12,7 +25,7 @@ describe('Iteration', () => { expect(stallTracking['_internalState']['timeout']).toBeNull(); }); it('Stall tracking does not set _timeout when isBackground is true', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; stallTracking['isTracking'] = true; stallTracking['_internalState']['isBackground'] = true; stallTracking['_internalState']['lastIntervalMs'] = Date.now() - 1000; // Force a timeout @@ -22,7 +35,7 @@ describe('Iteration', () => { expect(stallTracking['_internalState']['timeout']).toBeNull(); }); it('Stall tracking should set _timeout when isTracking is true and isBackground false', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; stallTracking['isTracking'] = true; stallTracking['_internalState']['isBackground'] = false; jest.useFakeTimers(); @@ -32,7 +45,7 @@ describe('Iteration', () => { expect(stallTracking['_internalState']['timeout']).toBeDefined(); }); it('Stall tracking should update _stallCount and _totalStallTime when timeout condition is met', () => { - const stallTracking = stallTrackingIntegration(); + const stallTracking = stallTrackingIntegration() as StallTrackingWithTestProperties; const LOOP_TIMEOUT_INTERVAL_MS = 50; const _minimumStallThreshold = 100; // Call _iteration with totalTimeTaken >= LOOP_TIMEOUT_INTERVAL_MS + _minimumStallThreshold diff --git a/test/tracing/mockedtimetodisplaynative.tsx b/test/tracing/mockedtimetodisplaynative.tsx index 82d3ac822..14c78fc5e 100644 --- a/test/tracing/mockedtimetodisplaynative.tsx +++ b/test/tracing/mockedtimetodisplaynative.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import * as React from 'react'; import { View } from 'react-native'; import type { RNSentryOnDrawNextFrameEvent, RNSentryOnDrawReporterProps } from '../../src/js/tracing/timetodisplaynative.types'; diff --git a/test/tracing/reactnavigation.ttid.test.tsx b/test/tracing/reactnavigation.ttid.test.tsx index 6e0855390..606562505 100644 --- a/test/tracing/reactnavigation.ttid.test.tsx +++ b/test/tracing/reactnavigation.ttid.test.tsx @@ -1,3 +1,8 @@ +import type { Scope, Span, SpanJSON, TransactionEvent, Transport } from '@sentry/types'; +import { timestampInSeconds } from '@sentry/utils'; +import * as TestRenderer from '@testing-library/react-native' +import * as React from "react"; + import * as mockWrapper from '../mockWrapper'; import * as mockedSentryEventEmitter from '../utils/mockedSentryeventemitter'; import * as mockedtimetodisplaynative from './mockedtimetodisplaynative'; @@ -6,13 +11,8 @@ jest.mock('../../src/js/utils/environment'); jest.mock('../../src/js/utils/sentryeventemitter', () => mockedSentryEventEmitter); jest.mock('../../src/js/tracing/timetodisplaynative', () => mockedtimetodisplaynative); -import { startSpanManual } from '@sentry/core'; -import type { Scope, Span,SpanJSON, TransactionEvent, Transport } from '@sentry/types'; -import { timestampInSeconds } from '@sentry/utils'; -import React from "react"; -import TestRenderer from 'react-test-renderer'; - import * as Sentry from '../../src/js'; +import { startSpanManual } from '../../src/js'; import { TimeToFullDisplay, TimeToInitialDisplay } from '../../src/js/tracing'; import { _setAppStartEndTimestampMs } from '../../src/js/tracing/integrations/appStart'; import { isHermesEnabled, notWeb } from '../../src/js/utils/environment'; @@ -275,7 +275,7 @@ describe('React Navigation - TTID', () => { mockedNavigation.finishAppStartNavigation(); mockedEventEmitter.emitNewFrameEvent(); - TestRenderer.create(); + TestRenderer.render(); emitNativeFullDisplayEvent(); jest.runOnlyPendingTimers(); // Flush ttid transaction @@ -344,7 +344,7 @@ describe('React Navigation - TTID', () => { mockedNavigation.finishAppStartNavigation(); mockedEventEmitter.emitNewFrameEvent(); - TestRenderer.create(); + TestRenderer.render(); emitNativeFullDisplayEvent(); jest.runOnlyPendingTimers(); // Flush ttid transaction @@ -442,7 +442,7 @@ describe('React Navigation - TTID', () => { jest.runOnlyPendingTimers(); // Flush app start transaction mockedNavigation.navigateToNewScreen(); - const timeToDisplayComponent = TestRenderer.create(); + const timeToDisplayComponent = TestRenderer.render(); mockedEventEmitter.emitNewFrameEvent(); timeToDisplayComponent.update(); @@ -479,7 +479,7 @@ describe('React Navigation - TTID', () => { mockedEventEmitter.emitNewFrameEvent(autoInitialDisplayEndTimestampMs); // Initialized too late auto instrumentation finished before manual - TestRenderer.create(); + TestRenderer.render(); emitNativeInitialDisplayEvent(secondInFutureTimestampMs()); jest.runOnlyPendingTimers(); // Flush transaction diff --git a/test/tracing/timetodisplay.test.tsx b/test/tracing/timetodisplay.test.tsx index 611c83110..0b2f80faf 100644 --- a/test/tracing/timetodisplay.test.tsx +++ b/test/tracing/timetodisplay.test.tsx @@ -3,8 +3,8 @@ jest.mock('../../src/js/tracing/timetodisplaynative', () => mockedtimetodisplayn import { getActiveSpan, getCurrentScope, getGlobalScope, getIsolationScope, getSpanDescendants, setCurrentClient, spanToJSON, startSpanManual} from '@sentry/core'; import type { Event, Measurements, Span, SpanJSON} from '@sentry/types'; -import React from "react"; -import TestRenderer from 'react-test-renderer'; +import * as React from "react"; +import * as TestRenderer from 'react-test-renderer'; import { startTimeToFullDisplaySpan, startTimeToInitialDisplaySpan, TimeToFullDisplay, TimeToInitialDisplay } from '../../src/js/tracing/timetodisplay'; import { getDefaultTestClientOptions, TestClient } from '../mocks/client'; diff --git a/test/utils/mockedSentryeventemitter.ts b/test/utils/mockedSentryeventemitter.ts index 3efc901b5..6849e460b 100644 --- a/test/utils/mockedSentryeventemitter.ts +++ b/test/utils/mockedSentryeventemitter.ts @@ -1,5 +1,5 @@ import { timestampInSeconds } from '@sentry/utils'; -import EventEmitter from 'events'; +import * as EventEmitter from 'events'; import type { NewFrameEvent, SentryEventEmitter } from '../../src/js/utils/sentryeventemitter'; import type { MockInterface } from '../testutils'; diff --git a/test/utils/safe.test.ts b/test/utils/safe.test.ts index a2e887122..89e063bd3 100644 --- a/test/utils/safe.test.ts +++ b/test/utils/safe.test.ts @@ -38,14 +38,14 @@ describe('safe', () => { test('calls given function with correct args', () => { const mockFn = jest.fn(); const actualSafeFunction = safeTracesSampler(mockFn); - actualSafeFunction?.({ transactionContext: { name: 'foo' } }); + actualSafeFunction?.({ name: 'foo', transactionContext: { name: 'foo' } }); expect(mockFn).toBeCalledTimes(1); - expect(mockFn).toBeCalledWith({ transactionContext: { name: 'foo' } }); + expect(mockFn).toBeCalledWith({ name: 'foo', transactionContext: { name: 'foo' } }); }); test('calls given function amd return its result', () => { const mockFn = jest.fn(() => 0.5); const actualSafeFunction = safeTracesSampler(mockFn); - const actualResult = actualSafeFunction?.({ transactionContext: { name: 'foo' } }); + const actualResult = actualSafeFunction?.({ name: 'foo', transactionContext: { name: 'foo' } }); expect(mockFn).toBeCalledTimes(1); expect(actualResult).toBe(0.5); }); @@ -58,7 +58,7 @@ describe('safe', () => { throw 'Test error'; }); const actualSafeFunction = safeTracesSampler(mockFn); - const actualResult = actualSafeFunction?.({ transactionContext: { name: 'foo' } }); + const actualResult = actualSafeFunction?.({ name: 'foo', transactionContext: { name: 'foo' } }); expect(mockFn).toBeCalledTimes(1); expect(actualResult).toEqual(0); }); diff --git a/test/vendor/base64-js/big-data.test.ts b/test/vendor/base64-js/big-data.test.ts index 750336b0d..db22201ba 100644 --- a/test/vendor/base64-js/big-data.test.ts +++ b/test/vendor/base64-js/big-data.test.ts @@ -25,7 +25,8 @@ import { base64StringFromByteArray } from '../../../src/js/vendor'; describe('base64-js', () => { - test('convert big data to base64', () => { + // eslint-disable-next-line jest/no-disabled-tests + test.skip('convert big data to base64', () => { const SIZE_2MB = 2e6; // scaled down from original 64MiB const big = new Uint8Array(SIZE_2MB); for (let i = 0, length = big.length; i < length; ++i) { diff --git a/test/vendor/buffer/utf8ToBytes.test.ts b/test/vendor/buffer/utf8ToBytes.test.ts index 07fcdb8af..6b743fdb5 100644 --- a/test/vendor/buffer/utf8ToBytes.test.ts +++ b/test/vendor/buffer/utf8ToBytes.test.ts @@ -73,9 +73,7 @@ describe('Buffer utf8 tests', () => { describe('test strings', () => { for (const input of testCases) { it(`should encode "${input}"`, () => { - // @ts-expect-error The test run in node where Buffer is available const actual = Buffer.from(utf8ToBytes(input)); - // @ts-expect-error The test run in node where Buffer is available const expected = Buffer.from(input, 'utf8'); expect(actual).toEqual(expected); diff --git a/test/wrapper.test.ts b/test/wrapper.test.ts index 884fd1a83..524fc0e60 100644 --- a/test/wrapper.test.ts +++ b/test/wrapper.test.ts @@ -96,7 +96,7 @@ describe('Tests Native Wrapper', () => { describe('startWithOptions', () => { test('calls native module', async () => { - await NATIVE.initNativeSdk({ dsn: 'test', enableNative: true }); + await NATIVE.initNativeSdk({ dsn: 'test', enableNative: true, mobileReplayOptions: undefined }); expect(RNSentry.initNativeSdk).toBeCalled(); }); @@ -104,7 +104,7 @@ describe('Tests Native Wrapper', () => { test('warns if there is no dsn', async () => { logger.warn = jest.fn(); - await NATIVE.initNativeSdk({ enableNative: true }); + await NATIVE.initNativeSdk({ enableNative: true, mobileReplayOptions: undefined }); expect(RNSentry.initNativeSdk).not.toBeCalled(); expect(logger.warn).toHaveBeenLastCalledWith( @@ -119,6 +119,7 @@ describe('Tests Native Wrapper', () => { dsn: 'test', enableNative: false, enableNativeNagger: true, + mobileReplayOptions: undefined, }); expect(RNSentry.initNativeSdk).not.toBeCalled(); @@ -132,6 +133,7 @@ describe('Tests Native Wrapper', () => { enableNative: true, autoInitializeNativeSdk: true, beforeSend: jest.fn(), + mobileReplayOptions: undefined, }); expect(RNSentry.initNativeSdk).toBeCalled(); @@ -147,6 +149,7 @@ describe('Tests Native Wrapper', () => { enableNative: true, autoInitializeNativeSdk: true, beforeBreadcrumb: jest.fn(), + mobileReplayOptions: undefined, }); expect(RNSentry.initNativeSdk).toBeCalled(); @@ -162,6 +165,7 @@ describe('Tests Native Wrapper', () => { enableNative: true, autoInitializeNativeSdk: true, beforeSendTransaction: jest.fn(), + mobileReplayOptions: undefined, }); expect(RNSentry.initNativeSdk).toBeCalled(); @@ -177,6 +181,7 @@ describe('Tests Native Wrapper', () => { enableNative: true, autoInitializeNativeSdk: true, integrations: [], + mobileReplayOptions: undefined, }); expect(RNSentry.initNativeSdk).toBeCalled(); @@ -194,6 +199,7 @@ describe('Tests Native Wrapper', () => { dsn: 'test', enableNative: true, autoInitializeNativeSdk: false, + mobileReplayOptions: undefined, }); expect(RNSentry.initNativeSdk).not.toBeCalled(); @@ -232,6 +238,7 @@ describe('Tests Native Wrapper', () => { logger.warn = jest.fn(); await NATIVE.initNativeSdk({ + mobileReplayOptions: undefined, dsn: 'test', enableNative: false, autoInitializeNativeSdk: false, @@ -282,7 +289,7 @@ describe('Tests Native Wrapper', () => { test('serializes class instances', async () => { class TestInstance { value: number = 0; - method = () => null; + method = (): null => null; } const event = { @@ -313,7 +320,7 @@ describe('Tests Native Wrapper', () => { }); test('does not call RNSentry at all if enableNative is false', async () => { try { - await NATIVE.initNativeSdk({ dsn: 'test-dsn', enableNative: false }); + await NATIVE.initNativeSdk({ dsn: 'test-dsn', enableNative: false, mobileReplayOptions: undefined }); // @ts-expect-error for testing, does not accept an empty class. await NATIVE.sendEnvelope({}); @@ -505,7 +512,7 @@ describe('Tests Native Wrapper', () => { expect(RNSentry.crash).toBeCalled(); }); test('does not call crash if enableNative is false', async () => { - await NATIVE.initNativeSdk({ dsn: 'test-dsn', enableNative: false }); + await NATIVE.initNativeSdk({ dsn: 'test-dsn', enableNative: false, mobileReplayOptions: undefined }); NATIVE.nativeCrash(); expect(RNSentry.crash).not.toBeCalled(); @@ -516,7 +523,6 @@ describe('Tests Native Wrapper', () => { test('serializes all user object keys', async () => { NATIVE.setUser({ email: 'hello@sentry.io', - // @ts-expect-error Intentional incorrect type to simulate using a double as an id (We had a user open an issue because this didn't work before) id: 3.14159265359, unique: 123, }); diff --git a/yarn.lock b/yarn.lock index 8bf3e0e79..9e9c7ac51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4043,6 +4043,15 @@ "@types/react-test-renderer" ">=16.9.0" react-error-boundary "^3.1.0" +"@testing-library/react-native@^12.5.3": + version "12.5.3" + resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-12.5.3.tgz#0ea753efed505698a79ba4a0d42d4b79cd272abc" + integrity sha512-wSaplzjx51OVJI7MU8Mi2kxwfW0dYETn3jqSVHxtIXmEnmlWXk6f69sEaBbzdp6iDzhFB5E6rDWveqf5V/ap2A== + dependencies: + jest-matcher-utils "^29.7.0" + pretty-format "^29.7.0" + redent "^3.0.0" + "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" @@ -8949,7 +8958,7 @@ jest-config@^29.6.2: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^29.0.0: +jest-diff@^29.0.0, jest-diff@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== @@ -9156,6 +9165,16 @@ jest-matcher-utils@^29.6.2: jest-get-type "^29.4.3" pretty-format "^29.6.2" +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + jest-message-util@^29.3.1: version "29.3.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" @@ -10528,6 +10547,11 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + "minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -11987,6 +12011,14 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reflect.getprototypeof@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" @@ -13098,6 +13130,13 @@ strip-final-newline@^3.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"