From d7401ac44acf524fe4d9a6a525f2cc13c70ce9e5 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 3 Apr 2023 11:14:58 +0200 Subject: [PATCH 1/2] chore: Add prettier settings and run prettier on the repo (#2950) --- .prettierignore | 2 + .prettierrc.json | 7 + package.json | 7 +- src/js/NativeRNSentry.ts | 11 +- src/js/breadcrumb.ts | 4 +- src/js/client.ts | 80 +++---- src/js/index.ts | 4 +- src/js/integrations/debugsymbolicator.ts | 99 ++++---- src/js/integrations/devicecontext.ts | 15 +- src/js/integrations/eventorigin.ts | 2 +- src/js/integrations/factory.ts | 8 +- src/js/integrations/modulesloader.ts | 2 +- .../integrations/reactnativeerrorhandlers.ts | 31 +-- src/js/integrations/reactnativeinfo.ts | 4 +- src/js/integrations/rewriteframes.ts | 9 +- src/js/integrations/screenshot.ts | 16 +- src/js/integrations/sdkinfo.ts | 6 +- src/js/integrations/viewhierarchy.ts | 2 +- src/js/measurements.ts | 26 +- src/js/misc.ts | 10 +- src/js/options.ts | 19 +- src/js/scope.ts | 8 +- src/js/tools/ModulesCollector.ts | 26 +- src/js/tools/collectModules.ts | 4 +- src/js/tracing/gesturetracing.ts | 18 +- src/js/tracing/index.ts | 15 +- src/js/tracing/nativeframes.ts | 115 ++++----- src/js/tracing/ops.ts | 1 - src/js/tracing/reactnativenavigation.ts | 71 ++---- src/js/tracing/reactnativetracing.ts | 179 +++++--------- src/js/tracing/reactnavigation.ts | 55 ++--- src/js/tracing/reactnavigationv4.ts | 78 ++---- src/js/tracing/routingInstrumentation.ts | 16 +- src/js/tracing/stalltracking.ts | 100 +++----- src/js/tracing/transaction.ts | 12 +- src/js/tracing/types.ts | 4 +- src/js/tracing/utils.ts | 11 +- src/js/transports/TextEncoder.ts | 2 +- src/js/transports/native.ts | 10 +- src/js/user.ts | 2 +- src/js/utils/envelope.ts | 29 +-- src/js/utils/outcome.ts | 2 +- src/js/utils/safe.ts | 16 +- src/js/vendor/buffer/index.ts | 4 +- src/js/vendor/buffer/utf8ToBytes.ts | 77 +++--- src/js/vendor/index.ts | 5 +- src/js/wrapper.ts | 70 ++---- test/client.test.ts | 142 +++++------ test/e2e/src/dsn.ts | 3 +- test/e2e/src/index.ts | 5 +- test/e2e/src/utils/getTestProps.ts | 8 +- test/e2e/test/e2e.test.ts | 7 +- test/e2e/test/utils/fetchEvent.ts | 8 +- test/e2e/test/utils/waitFor.ts | 6 +- test/integrations/devicecontext.test.ts | 97 ++++---- test/integrations/eventorigin.test.ts | 4 +- test/integrations/modulesloader.test.ts | 8 +- .../reactnativeerrorhandlers.test.ts | 10 +- test/integrations/reactnativeinfo.test.ts | 32 ++- test/integrations/release.test.ts | 23 +- test/integrations/rewriteframes.test.ts | 21 +- test/integrations/sdkinfo.test.ts | 2 +- test/integrations/viewhierarchy.test.ts | 56 +++-- test/measurements.test.ts | 16 +- test/misc.test.ts | 6 +- test/scope.test.ts | 16 +- test/sdk.test.ts | 79 ++++--- test/testutils.ts | 4 +- test/tools/collectModules.test.ts | 33 +-- test/tracing/gesturetracing.test.ts | 92 ++++---- test/tracing/mockedrountinginstrumention.ts | 26 +- test/tracing/nativeframes.test.ts | 140 +++++------ test/tracing/reactnativenavigation.test.ts | 204 ++++++++-------- test/tracing/reactnativetracing.test.ts | 222 ++++++++---------- test/tracing/reactnavigation.test.ts | 132 ++++------- test/tracing/reactnavigationv4.test.ts | 92 +++----- test/tracing/stalltracking.test.ts | 40 ++-- test/utils/safe.test.ts | 14 +- test/vendor/buffer/utf8ToBytes.test.ts | 31 ++- test/vendor/buffer/utf8ToBytesSize.test.ts | 2 - test/wrapper.test.ts | 84 +++---- 81 files changed, 1284 insertions(+), 1675 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..bb000a1b60 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +/test/react-native/versions + diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000000..ba9a3dc2c2 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "arrowParens": "avoid", + "printWidth": 120, + "proseWrap": "always", + "singleQuote": true, + "trailingComma": "all" +} diff --git a/package.json b/package.json index c4d17bf1bb..b582056baf 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,12 @@ "build:tools": "tsc -p tsconfig.build.tools.json", "clean": "rimraf dist coverage", "test": "jest", - "lint": "eslint --config .eslintrc.js .", + "fix": "yarn fix:eslint && yarn fix:prettier", + "fix:eslint": "eslint --config .eslintrc.js --fix .", + "fix:prettier": "prettier --write \"{src,test,scripts}/**/**.ts\"", + "lint": "yarn lint:eslint && yarn lint:prettier", + "lint:eslint": "eslint --config .eslintrc.js .", + "lint:prettier": "prettier --check \"{src,test,scripts}/**/**.ts\"", "test:watch": "jest --watch", "run-ios": "cd sample && yarn react-native run-ios", "run-android": "cd sample && yarn react-native run-android" diff --git a/src/js/NativeRNSentry.ts b/src/js/NativeRNSentry.ts index c4380faf5f..d0208ed7f6 100644 --- a/src/js/NativeRNSentry.ts +++ b/src/js/NativeRNSentry.ts @@ -1,5 +1,5 @@ import type { Package } from '@sentry/types'; -import type { TurboModule} from 'react-native'; +import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; import type { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; @@ -10,7 +10,7 @@ export interface Spec extends TurboModule { captureEnvelope( bytes: number[], options: { - store: boolean, + store: boolean; }, ): Promise; captureScreenshot(): Promise; @@ -24,10 +24,7 @@ export interface Spec extends TurboModule { fetchNativeAppStart(): Promise; fetchNativeFrames(): Promise; initNativeSdk(options: UnsafeObject): Promise; - setUser( - defaultUserKeys: UnsafeObject | null, - otherUserKeys: UnsafeObject | null - ): void; + setUser(defaultUserKeys: UnsafeObject | null, otherUserKeys: UnsafeObject | null): void; setContext(key: string, value: UnsafeObject | null): void; setExtra(key: string, value: string): void; setTag(key: string, value: string): void; @@ -89,7 +86,7 @@ export type NativeScreenshot = { data: number[]; contentType: string; filename: string; -} +}; // The export must be here to pass codegen even if not used export default TurboModuleRegistry.getEnforcing('RNSentry'); diff --git a/src/js/breadcrumb.ts b/src/js/breadcrumb.ts index 5460eca060..a5f2ab0f94 100644 --- a/src/js/breadcrumb.ts +++ b/src/js/breadcrumb.ts @@ -5,7 +5,7 @@ export const DEFAULT_BREADCRUMB_LEVEL: SeverityLevel = 'info'; type BreadcrumbCandidate = { [K in keyof Partial]: unknown; -} +}; /** * Convert plain object to a valid Breadcrumb @@ -32,7 +32,7 @@ export function breadcrumbFromObject(candidate: BreadcrumbCandidate): Breadcrumb breadcrumb.data = candidate.data; } if (typeof candidate.timestamp === 'string') { - const timestamp = Date.parse(candidate.timestamp) + const timestamp = Date.parse(candidate.timestamp); if (!isNaN(timestamp)) { breadcrumb.timestamp = timestamp; } diff --git a/src/js/client.ts b/src/js/client.ts index 7d8f7e1623..bdef18d212 100644 --- a/src/js/client.ts +++ b/src/js/client.ts @@ -32,7 +32,6 @@ import { NATIVE } from './wrapper'; * @see SentryClient for usage documentation. */ export class ReactNativeClient extends BaseClient { - private _outcomesBuffer: Outcome[]; /** @@ -53,37 +52,31 @@ export class ReactNativeClient extends BaseClient { * @inheritDoc */ public eventFromException(exception: unknown, hint: EventHint = {}): PromiseLike { - return Screenshot.attachScreenshotToEventHint(hint, this._options) - .then(hintWithScreenshot => eventFromException( - this._options.stackParser, - exception, - hintWithScreenshot, - this._options.attachStacktrace, - )); + return Screenshot.attachScreenshotToEventHint(hint, this._options).then(hintWithScreenshot => + eventFromException(this._options.stackParser, exception, hintWithScreenshot, this._options.attachStacktrace), + ); } /** * @inheritDoc */ public eventFromMessage(message: string, level?: SeverityLevel, hint?: EventHint): PromiseLike { - return eventFromMessage( - this._options.stackParser, - message, - level, - hint, - this._options.attachStacktrace, - ).then((event: Event) => { - // TMP! Remove this function once JS SDK uses threads for messages - if (!event.exception?.values || event.exception.values.length <= 0) { + return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace).then( + (event: Event) => { + // TMP! Remove this function once JS SDK uses threads for messages + if (!event.exception?.values || event.exception.values.length <= 0) { + return event; + } + const values = event.exception.values.map( + (exception: Exception): Thread => ({ + stacktrace: exception.stacktrace, + }), + ); + (event as { threads?: { values: Thread[] } }).threads = { values }; + delete event.exception; return event; - } - const values = event.exception.values.map((exception: Exception): Thread => ({ - stacktrace: exception.stacktrace, - })); - (event as { threads?: { values: Thread[] } }).threads = { values }; - delete event.exception; - return event; - }); + }, + ); } /** @@ -108,14 +101,11 @@ export class ReactNativeClient extends BaseClient { * Sends user feedback to Sentry. */ public captureUserFeedback(feedback: UserFeedback): void { - const envelope = createUserFeedbackEnvelope( - feedback, - { - metadata: this._options._metadata, - dsn: this.getDsn(), - tunnel: this._options.tunnel, - }, - ); + const envelope = createUserFeedbackEnvelope(feedback, { + metadata: this._options._metadata, + dsn: this.getDsn(), + tunnel: this._options.tunnel, + }); this._sendEnvelope(envelope); } @@ -125,7 +115,7 @@ export class ReactNativeClient extends BaseClient { public setupIntegrations(): void { super.setupIntegrations(); const tracing = this.getIntegration(ReactNativeTracing); - const routingName = tracing?.options.routingInstrumentation?.name + const routingName = tracing?.options.routingInstrumentation?.name; if (routingName) { this.addIntegration(createIntegration(routingName)); } @@ -144,16 +134,16 @@ export class ReactNativeClient extends BaseClient { let shouldClearOutcomesBuffer = true; if (this._transport && this._dsn) { - this._transport.send(envelope) - .then(null, reason => { - if (reason instanceof SentryError) { // SentryError is thrown by SyncPromise - shouldClearOutcomesBuffer = false; - // If this is called asynchronously we want the _outcomesBuffer to be cleared - logger.error('SentryError while sending event, keeping outcomes buffer:', reason); - } else { - logger.error('Error while sending event:', reason); - } - }); + this._transport.send(envelope).then(null, reason => { + if (reason instanceof SentryError) { + // SentryError is thrown by SyncPromise + shouldClearOutcomesBuffer = false; + // If this is called asynchronously we want the _outcomesBuffer to be cleared + logger.error('SentryError while sending event, keeping outcomes buffer:', reason); + } else { + logger.error('Error while sending event:', reason); + } + }); } else { logger.error('Transport disabled'); } @@ -189,7 +179,7 @@ export class ReactNativeClient extends BaseClient { if (__DEV__ && this._options.enableNativeNagger) { Alert.alert( 'Sentry', - 'Warning, could not connect to Sentry native SDK.\nIf you do not want to use the native component please pass `enableNative: false` in the options.\nVisit: https://docs.sentry.io/platforms/react-native/#linking for more details.' + 'Warning, could not connect to Sentry native SDK.\nIf you do not want to use the native component please pass `enableNative: false` in the options.\nVisit: https://docs.sentry.io/platforms/react-native/#linking for more details.', ); } } diff --git a/src/js/index.ts b/src/js/index.ts index 893d0e389d..07033189af 100644 --- a/src/js/index.ts +++ b/src/js/index.ts @@ -48,9 +48,7 @@ export { withProfiler, } from '@sentry/react'; -export { - lastEventId, -} from '@sentry/browser'; +export { lastEventId } from '@sentry/browser'; import * as Integrations from './integrations'; import { SDK_NAME, SDK_VERSION } from './version'; diff --git a/src/js/integrations/debugsymbolicator.ts b/src/js/integrations/debugsymbolicator.ts index b395ce3119..e3397fa3c5 100644 --- a/src/js/integrations/debugsymbolicator.ts +++ b/src/js/integrations/debugsymbolicator.ts @@ -2,9 +2,7 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core'; import type { Event, EventHint, Integration, StackFrame } from '@sentry/types'; import { addContextToFrame, logger } from '@sentry/utils'; -const INTERNAL_CALLSITES_REGEX = new RegExp( - ['ReactNativeRenderer-dev\\.js$', 'MessageQueue\\.js$'].join('|') -); +const INTERNAL_CALLSITES_REGEX = new RegExp(['ReactNativeRenderer-dev\\.js$', 'MessageQueue\\.js$'].join('|')); interface GetDevServer { (): { url: string }; @@ -78,10 +76,7 @@ export class DebugSymbolicator implements Integration { * Symbolicates the stack on the device talking to local dev server. * Mutates the passed event. */ - private async _symbolicate( - event: Event, - stack: string | undefined - ): Promise { + private async _symbolicate(event: Event, stack: string | undefined): Promise { try { // eslint-disable-next-line @typescript-eslint/no-var-requires const symbolicateStackTrace = require('react-native/Libraries/Core/Devtools/symbolicateStackTrace'); @@ -99,12 +94,10 @@ export class DebugSymbolicator implements Integration { const stackWithoutInternalCallsites = newStack.filter( (frame: { file?: string }) => // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - frame.file && frame.file.match(INTERNAL_CALLSITES_REGEX) === null + frame.file && frame.file.match(INTERNAL_CALLSITES_REGEX) === null, ); - const symbolicatedFrames = await this._convertReactNativeFramesToSentryFrames( - stackWithoutInternalCallsites - ); + const symbolicatedFrames = await this._convertReactNativeFramesToSentryFrames(stackWithoutInternalCallsites); this._replaceFramesInEvent(event, symbolicatedFrames); } else { logger.error('The stack is null'); @@ -120,9 +113,7 @@ export class DebugSymbolicator implements Integration { * Converts ReactNativeFrames to frames in the Sentry format * @param frames ReactNativeFrame[] */ - private async _convertReactNativeFramesToSentryFrames( - frames: ReactNativeFrame[] - ): Promise { + private async _convertReactNativeFramesToSentryFrames(frames: ReactNativeFrame[]): Promise { let getDevServer: GetDevServer; try { getDevServer = require('react-native/Libraries/Core/Devtools/getDevServer'); @@ -132,44 +123,40 @@ export class DebugSymbolicator implements Integration { // Below you will find lines marked with :HACK to prevent showing errors in the sentry ui // But since this is a debug only feature: This is Fine (TM) return Promise.all( - frames.map( - async (frame: ReactNativeFrame): Promise => { - let inApp = !!frame.column && !!frame.lineNumber; - inApp = - inApp && - frame.file !== undefined && - !frame.file.includes('node_modules') && - !frame.file.includes('native code'); - - const newFrame: StackFrame = { - colno: frame.column, - filename: frame.file, - function: frame.methodName, - in_app: inApp, - lineno: inApp ? frame.lineNumber : undefined, // :HACK - platform: inApp ? 'javascript' : 'node', // :HACK - }; - - // The upstream `react-native@0.61` delegates parsing of stacks to `stacktrace-parser`, which is buggy and - // leaves a trailing `(address at` in the function name. - // `react-native@0.62` seems to have custom logic to parse hermes frames specially. - // Anyway, all we do here is throw away the bogus suffix. - if (newFrame.function) { - const addressAtPos = newFrame.function.indexOf('(address at'); - if (addressAtPos >= 0) { - newFrame.function = newFrame.function - .substr(0, addressAtPos) - .trim(); - } - } - - if (inApp) { - await this._addSourceContext(newFrame, getDevServer); + frames.map(async (frame: ReactNativeFrame): Promise => { + let inApp = !!frame.column && !!frame.lineNumber; + inApp = + inApp && + frame.file !== undefined && + !frame.file.includes('node_modules') && + !frame.file.includes('native code'); + + const newFrame: StackFrame = { + colno: frame.column, + filename: frame.file, + function: frame.methodName, + in_app: inApp, + lineno: inApp ? frame.lineNumber : undefined, // :HACK + platform: inApp ? 'javascript' : 'node', // :HACK + }; + + // The upstream `react-native@0.61` delegates parsing of stacks to `stacktrace-parser`, which is buggy and + // leaves a trailing `(address at` in the function name. + // `react-native@0.62` seems to have custom logic to parse hermes frames specially. + // Anyway, all we do here is throw away the bogus suffix. + if (newFrame.function) { + const addressAtPos = newFrame.function.indexOf('(address at'); + if (addressAtPos >= 0) { + newFrame.function = newFrame.function.substr(0, addressAtPos).trim(); } + } - return newFrame; + if (inApp) { + await this._addSourceContext(newFrame, getDevServer); } - ) + + return newFrame; + }), ); } @@ -195,10 +182,7 @@ export class DebugSymbolicator implements Integration { * @param frame StackFrame * @param getDevServer function from RN to get DevServer URL */ - private async _addSourceContext( - frame: StackFrame, - getDevServer?: GetDevServer - ): Promise { + private async _addSourceContext(frame: StackFrame, getDevServer?: GetDevServer): Promise { let response; const segments = frame.filename?.split('/') ?? []; @@ -206,12 +190,9 @@ export class DebugSymbolicator implements Integration { if (getDevServer) { for (const idx in segments) { if (Object.prototype.hasOwnProperty.call(segments, idx)) { - response = await fetch( - `${getDevServer().url}${segments.slice(-idx).join('/')}`, - { - method: 'GET', - } - ); + response = await fetch(`${getDevServer().url}${segments.slice(-idx).join('/')}`, { + method: 'GET', + }); if (response.ok) { break; diff --git a/src/js/integrations/devicecontext.ts b/src/js/integrations/devicecontext.ts index 8e79970db5..6a7e575037 100644 --- a/src/js/integrations/devicecontext.ts +++ b/src/js/integrations/devicecontext.ts @@ -22,10 +22,7 @@ export class DeviceContext implements Integration { /** * @inheritDoc */ - public setupOnce( - addGlobalEventProcessor: (callback: EventProcessor) => void, - getCurrentHub: () => Hub, - ): void { + public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { addGlobalEventProcessor(async (event: Event) => { const self = getCurrentHub().getIntegration(DeviceContext); if (!self) { @@ -54,7 +51,7 @@ export class DeviceContext implements Integration { nativeContext.app = { ...nativeContext.app, in_foreground: AppState.currentState === 'active', - } + }; } if (nativeContext) { event.contexts = { ...nativeContext, ...event.contexts }; @@ -73,13 +70,11 @@ export class DeviceContext implements Integration { const nativeFingerprint = native.fingerprint; if (nativeFingerprint) { event.fingerprint = (event.fingerprint ?? []).concat( - nativeFingerprint.filter((item) => (event.fingerprint ?? []).indexOf(item) < 0), - ) + nativeFingerprint.filter(item => (event.fingerprint ?? []).indexOf(item) < 0), + ); } - const nativeLevel = typeof native['level'] === 'string' - ? severityLevelFromString(native['level']) - : undefined; + const nativeLevel = typeof native['level'] === 'string' ? severityLevelFromString(native['level']) : undefined; if (!event.level && nativeLevel) { event.level = nativeLevel; } diff --git a/src/js/integrations/eventorigin.ts b/src/js/integrations/eventorigin.ts index 6b9a0df813..3b61e562f1 100644 --- a/src/js/integrations/eventorigin.ts +++ b/src/js/integrations/eventorigin.ts @@ -16,7 +16,7 @@ export class EventOrigin implements Integration { * @inheritDoc */ public setupOnce(addGlobalEventProcessor: (e: EventProcessor) => void): void { - addGlobalEventProcessor((event) => { + addGlobalEventProcessor(event => { event.tags = event.tags ?? {}; event.tags['event.origin'] = 'javascript'; diff --git a/src/js/integrations/factory.ts b/src/js/integrations/factory.ts index b5e2116943..6dbea2eaec 100644 --- a/src/js/integrations/factory.ts +++ b/src/js/integrations/factory.ts @@ -1,6 +1,4 @@ -import type { - Integration, -} from '@sentry/types'; +import type { Integration } from '@sentry/types'; /** * Creates an integration out of the provided name and setup function. @@ -8,7 +6,9 @@ import type { */ export function createIntegration( name: Integration['name'], - setupOnce: Integration['setupOnce'] = () => { /* noop */ }, + setupOnce: Integration['setupOnce'] = () => { + /* noop */ + }, ): Integration { return { name: name, diff --git a/src/js/integrations/modulesloader.ts b/src/js/integrations/modulesloader.ts index dded0c7bf7..b3f4da04cc 100644 --- a/src/js/integrations/modulesloader.ts +++ b/src/js/integrations/modulesloader.ts @@ -1,4 +1,4 @@ -import type { Event,EventProcessor, Integration } from '@sentry/types'; +import type { Event, EventProcessor, Integration } from '@sentry/types'; import { logger } from '@sentry/utils'; import { NATIVE } from '../wrapper'; diff --git a/src/js/integrations/reactnativeerrorhandlers.ts b/src/js/integrations/reactnativeerrorhandlers.ts index d80e232316..401b7ba8bb 100644 --- a/src/js/integrations/reactnativeerrorhandlers.ts +++ b/src/js/integrations/reactnativeerrorhandlers.ts @@ -74,9 +74,7 @@ export class ReactNativeErrorHandlers implements Integration { */ private _polyfillPromise(): void { /* eslint-disable import/no-extraneous-dependencies,@typescript-eslint/no-var-requires */ - const { - polyfillGlobal, - } = require('react-native/Libraries/Utilities/PolyfillFunctions'); + const { polyfillGlobal } = require('react-native/Libraries/Utilities/PolyfillFunctions'); // Below, we follow the exact way React Native initializes its promise library, and we globally replace it. const Promise = require('promise/setimmediate/es6-extensions'); @@ -101,16 +99,14 @@ export class ReactNativeErrorHandlers implements Integration { const promiseRejectionTrackingOptions: PromiseRejectionTrackingOptions = { onUnhandled: (id, rejection = {}) => { // eslint-disable-next-line no-console - console.warn( - `Possible Unhandled Promise Rejection (id: ${id}):\n${rejection}` - ); + console.warn(`Possible Unhandled Promise Rejection (id: ${id}):\n${rejection}`); }, - onHandled: (id) => { + onHandled: id => { // eslint-disable-next-line no-console console.warn( `Promise Rejection Handled (id: ${id})\n` + - 'This means you can ignore any previous messages of the form ' + - `"Possible Unhandled Promise Rejection (id: ${id}):"` + 'This means you can ignore any previous messages of the form ' + + `"Possible Unhandled Promise Rejection (id: ${id}):"`, ); }, }; @@ -142,7 +138,7 @@ export class ReactNativeErrorHandlers implements Integration { if (Promise !== RN_GLOBAL_OBJ.Promise) { logger.warn( - 'Unhandled promise rejections will not be caught by Sentry. Read about how to fix this on our troubleshooting page.' + 'Unhandled promise rejections will not be caught by Sentry. Read about how to fix this on our troubleshooting page.', ); } else { logger.log('Unhandled promise rejections will be caught by Sentry.'); @@ -150,7 +146,7 @@ export class ReactNativeErrorHandlers implements Integration { } catch (e) { // Do Nothing logger.warn( - 'Unhandled promise rejections will not be caught by Sentry. Read about how to fix this on our troubleshooting page.' + 'Unhandled promise rejections will not be caught by Sentry. Read about how to fix this on our troubleshooting page.', ); } } @@ -167,8 +163,7 @@ export class ReactNativeErrorHandlers implements Integration { return; } - const defaultHandler = - errorUtils.getGlobalHandler && errorUtils.getGlobalHandler(); + const defaultHandler = errorUtils.getGlobalHandler && errorUtils.getGlobalHandler(); // eslint-disable-next-line @typescript-eslint/no-explicit-any errorUtils.setGlobalHandler(async (error: any, isFatal?: boolean) => { @@ -176,10 +171,7 @@ export class ReactNativeErrorHandlers implements Integration { const shouldHandleFatal = isFatal && !__DEV__; if (shouldHandleFatal) { if (handlingFatal) { - logger.log( - 'Encountered multiple fatals in a row. The latest:', - error - ); + logger.log('Encountered multiple fatals in a row. The latest:', error); return; } handlingFatal = true; @@ -190,10 +182,7 @@ export class ReactNativeErrorHandlers implements Integration { const scope = currentHub.getScope(); if (!client) { - logger.error( - 'Sentry client is missing, the error event might be lost.', - error - ); + logger.error('Sentry client is missing, the error event might be lost.', error); // If there is no client something is fishy, anyway we call the default handler defaultHandler(error, isFatal); diff --git a/src/js/integrations/reactnativeinfo.ts b/src/js/integrations/reactnativeinfo.ts index 340d64246f..756145084b 100644 --- a/src/js/integrations/reactnativeinfo.ts +++ b/src/js/integrations/reactnativeinfo.ts @@ -27,9 +27,7 @@ export class ReactNativeInfo implements Integration { */ public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void): void { addGlobalEventProcessor(async (event: Event, hint?: EventHint) => { - const reactNativeError = hint?.originalException - ? hint?.originalException as ReactNativeError - : undefined; + const reactNativeError = hint?.originalException ? (hint?.originalException as ReactNativeError) : undefined; const reactNativeContext: ReactNativeContext = { turbo_module: isTurboModuleEnabled(), diff --git a/src/js/integrations/rewriteframes.ts b/src/js/integrations/rewriteframes.ts index 47c3342b74..4b2984c305 100644 --- a/src/js/integrations/rewriteframes.ts +++ b/src/js/integrations/rewriteframes.ts @@ -15,16 +15,11 @@ export function createReactNativeRewriteFrames(): RewriteFrames { .replace(/^address at /, '') .replace(/^.*\/[^.]+(\.app|CodePush|.*(?=\/))/, ''); - if ( - frame.filename !== '[native code]' && - frame.filename !== 'native' - ) { + if (frame.filename !== '[native code]' && frame.filename !== 'native') { const appPrefix = 'app://'; // We always want to have a triple slash frame.filename = - frame.filename.indexOf('/') === 0 - ? `${appPrefix}${frame.filename}` - : `${appPrefix}/${frame.filename}`; + frame.filename.indexOf('/') === 0 ? `${appPrefix}${frame.filename}` : `${appPrefix}/${frame.filename}`; } delete frame.abs_path; } diff --git a/src/js/integrations/screenshot.ts b/src/js/integrations/screenshot.ts index 640082502f..42a259900b 100644 --- a/src/js/integrations/screenshot.ts +++ b/src/js/integrations/screenshot.ts @@ -26,16 +26,12 @@ export class Screenshot implements Integration { return resolvedSyncPromise(hint); } - return NATIVE.captureScreenshot() - .then((screenshots) => { - if (screenshots !== null && screenshots.length > 0) { - hint.attachments = [ - ...screenshots, - ...(hint?.attachments || []), - ]; - } - return hint; - }); + return NATIVE.captureScreenshot().then(screenshots => { + if (screenshots !== null && screenshots.length > 0) { + hint.attachments = [...screenshots, ...(hint?.attachments || [])]; + } + return hint; + }); } /** diff --git a/src/js/integrations/sdkinfo.ts b/src/js/integrations/sdkinfo.ts index 21df83c193..1efef0125f 100644 --- a/src/js/integrations/sdkinfo.ts +++ b/src/js/integrations/sdkinfo.ts @@ -1,7 +1,7 @@ import type { EventProcessor, Integration, Package, SdkInfo as SdkInfoType } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { SDK_NAME, SDK_PACKAGE_NAME,SDK_VERSION } from '../version'; +import { SDK_NAME, SDK_PACKAGE_NAME, SDK_VERSION } from '../version'; import { NATIVE } from '../wrapper'; type DefaultSdkInfo = Pick, 'name' | 'packages' | 'version'>; @@ -35,7 +35,7 @@ export class SdkInfo implements Integration { * @inheritDoc */ public setupOnce(addGlobalEventProcessor: (e: EventProcessor) => void): void { - addGlobalEventProcessor(async (event) => { + addGlobalEventProcessor(async event => { // The native SDK info package here is only used on iOS as `beforeSend` is not called on `captureEnvelope`. // this._nativeSdkInfo should be defined a following time so this call won't always be awaited. if (NATIVE.platform === 'ios' && this._nativeSdkInfo === null) { @@ -44,7 +44,7 @@ export class SdkInfo implements Integration { } catch (e) { // If this fails, go ahead as usual as we would rather have the event be sent with a package missing. logger.warn( - '[SdkInfo] Native SDK Info retrieval failed...something could be wrong with your Sentry installation:' + '[SdkInfo] Native SDK Info retrieval failed...something could be wrong with your Sentry installation:', ); logger.warn(e); } diff --git a/src/js/integrations/viewhierarchy.ts b/src/js/integrations/viewhierarchy.ts index 02539c5d58..15b29b0d25 100644 --- a/src/js/integrations/viewhierarchy.ts +++ b/src/js/integrations/viewhierarchy.ts @@ -31,7 +31,7 @@ export class ViewHierarchy implements Integration { let viewHierarchy: Uint8Array | null = null; try { - viewHierarchy = await NATIVE.fetchViewHierarchy() + viewHierarchy = await NATIVE.fetchViewHierarchy(); } catch (e) { logger.error('Failed to get view hierarchy from native.', e); } diff --git a/src/js/measurements.ts b/src/js/measurements.ts index a2f81b26e4..01daa162cc 100644 --- a/src/js/measurements.ts +++ b/src/js/measurements.ts @@ -3,7 +3,7 @@ import { getCurrentHub, getMainCarrier } from '@sentry/core'; import type { Transaction } from '@sentry/tracing'; import type { CustomSamplingContext, Span, SpanContext, TransactionContext } from '@sentry/types'; -import { DEFAULT,ReactNativeTracing } from './tracing'; +import { DEFAULT, ReactNativeTracing } from './tracing'; export const APP_START_WARM = 'app_start_warm'; export const APP_START_COLD = 'app_start_cold'; @@ -20,16 +20,13 @@ export function _addTracingExtensions(): void { if (carrier.__SENTRY__) { carrier.__SENTRY__.extensions = carrier.__SENTRY__.extensions || {}; if (carrier.__SENTRY__.extensions.startTransaction) { - const originalStartTransaction = carrier.__SENTRY__.extensions - .startTransaction as StartTransactionFunction; + const originalStartTransaction = carrier.__SENTRY__.extensions.startTransaction as StartTransactionFunction; /* Overwrites the transaction start and finish to start and finish stall tracking. Preferably instead of overwriting add a callback method for this in the Transaction itself. */ - const _startTransaction = _patchStartTransaction( - originalStartTransaction - ); + const _startTransaction = _patchStartTransaction(originalStartTransaction); carrier.__SENTRY__.extensions.startTransaction = _startTransaction; } @@ -39,32 +36,27 @@ export function _addTracingExtensions(): void { export type StartTransactionFunction = ( this: Hub, transactionContext: TransactionContext, - customSamplingContext?: CustomSamplingContext + customSamplingContext?: CustomSamplingContext, ) => Transaction; /** * Overwrite the startTransaction extension method to start and end stall tracking. */ -const _patchStartTransaction = ( - originalStartTransaction: StartTransactionFunction -): StartTransactionFunction => { +const _patchStartTransaction = (originalStartTransaction: StartTransactionFunction): StartTransactionFunction => { /** * Method to overwrite with */ function _startTransaction( this: Hub, transactionContext: TransactionContext, - customSamplingContext?: CustomSamplingContext + customSamplingContext?: CustomSamplingContext, ): Transaction { // Native SDKs require op to be set - for JS Relay sets `default` if (!transactionContext.op) { transactionContext.op = DEFAULT; } - const transaction: Transaction = originalStartTransaction.apply(this, [ - transactionContext, - customSamplingContext, - ]); + const transaction: Transaction = originalStartTransaction.apply(this, [transactionContext, customSamplingContext]); const originalStartChild: Transaction['startChild'] = transaction.startChild.bind(transaction); transaction.startChild = ( spanContext?: Pick>, @@ -76,9 +68,7 @@ const _patchStartTransaction = ( }); }; - const reactNativeTracing = getCurrentHub().getIntegration( - ReactNativeTracing - ); + const reactNativeTracing = getCurrentHub().getIntegration(ReactNativeTracing); if (reactNativeTracing) { reactNativeTracing.onTransactionStart(transaction); diff --git a/src/js/misc.ts b/src/js/misc.ts index a7db0c7a17..a5a83d09d1 100644 --- a/src/js/misc.ts +++ b/src/js/misc.ts @@ -1,7 +1,4 @@ -import type { - EnvelopeItem, - Exception, -} from '@sentry/types'; +import type { EnvelopeItem, Exception } from '@sentry/types'; type EnvelopeItemPayload = EnvelopeItem[1]; @@ -10,9 +7,8 @@ type EnvelopeItemPayload = EnvelopeItem[1]; * No exceptions or undefined handled are not hard crashes. */ export function isHardCrash(payload: EnvelopeItemPayload): boolean { - const values: Exception[] = typeof payload !== 'string' && 'exception' in payload && payload.exception?.values - ? payload.exception.values - : []; + const values: Exception[] = + typeof payload !== 'string' && 'exception' in payload && payload.exception?.values ? payload.exception.values : []; for (const exception of values) { if (!(exception.mechanism?.handled !== false)) { return true; diff --git a/src/js/options.ts b/src/js/options.ts index 8940ba8d67..670b39448e 100644 --- a/src/js/options.ts +++ b/src/js/options.ts @@ -7,11 +7,11 @@ import type { TouchEventBoundaryProps } from './touchevents'; export interface BaseReactNativeOptions { /** - * Enables native transport + device info + offline caching. - * Be careful, disabling this also breaks automatic release setting. - * This means you have to manage setting the release yourself. - * Defaults to `true`. - */ + * Enables native transport + device info + offline caching. + * Be careful, disabling this also breaks automatic release setting. + * This means you have to manage setting the release yourself. + * Defaults to `true`. + */ enableNative?: boolean; /** @@ -155,7 +155,7 @@ export interface BaseReactNativeOptions { export interface ReactNativeTransportOptions extends BrowserTransportOptions { /** * @deprecated use `maxQueueSize` in the root of the SDK options. - */ + */ bufferSize?: number; } @@ -164,12 +164,9 @@ export interface ReactNativeTransportOptions extends BrowserTransportOptions { * @see ReactNativeFrontend for more information. */ -export interface ReactNativeOptions extends Options, BaseReactNativeOptions { -} - -export interface ReactNativeClientOptions extends ClientOptions, BaseReactNativeOptions { -} +export interface ReactNativeOptions extends Options, BaseReactNativeOptions {} +export interface ReactNativeClientOptions extends ClientOptions, BaseReactNativeOptions {} export interface ReactNativeWrapperOptions { /** Props for the root React profiler */ diff --git a/src/js/scope.ts b/src/js/scope.ts index 428c9cd9a9..52033083b6 100644 --- a/src/js/scope.ts +++ b/src/js/scope.ts @@ -29,7 +29,7 @@ export class ReactNativeScope extends Scope { */ public setTags(tags: { [key: string]: string }): this { // As native only has setTag, we just loop through each tag key. - Object.keys(tags).forEach((key) => { + Object.keys(tags).forEach(key => { NATIVE.setTag(key, tags[key]); }); return super.setTags(tags); @@ -40,7 +40,7 @@ export class ReactNativeScope extends Scope { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any public setExtras(extras: { [key: string]: any }): this { - Object.keys(extras).forEach((key) => { + Object.keys(extras).forEach(key => { NATIVE.setExtra(key, extras[key]); }); return super.setExtras(extras); @@ -92,8 +92,8 @@ export class ReactNativeScope extends Scope { } /** - * @inheritDoc - */ + * @inheritDoc + */ public clearAttachments(): this { return super.clearAttachments(); } diff --git a/src/js/tools/ModulesCollector.ts b/src/js/tools/ModulesCollector.ts index 497cad49cd..30505d0da9 100644 --- a/src/js/tools/ModulesCollector.ts +++ b/src/js/tools/ModulesCollector.ts @@ -8,18 +8,17 @@ logger.enable(); const { dirname, join, resolve, sep: posixSep } = posix; interface Package { - name?: string, - version?: string, + name?: string; + version?: string; } /** * Collects JS modules from source paths. */ export default class ModulesCollector { - /** Collect method */ public static collect(sources: unknown[], modulesPaths: string[]): Record { - const normalizedModulesPaths = modulesPaths.map((modulesPath) => resolve(modulesPath.split(sep).join(posixSep))); + const normalizedModulesPaths = modulesPaths.map(modulesPath => resolve(modulesPath.split(sep).join(posixSep))); const infos: Record = {}; const seen: Record = {}; @@ -46,11 +45,7 @@ export default class ModulesCollector { return; } - if ( - !dir || - parentDir === dir || - seen[dir] - ) { + if (!dir || parentDir === dir || seen[dir]) { return; } seen[dir] = true; @@ -89,10 +84,10 @@ export default class ModulesCollector { modulesPaths, collect, }: Partial<{ - sourceMapPath: string, - outputModulesPath: string, - modulesPaths: string[], - collect: (sources: unknown[], modulesPaths: string[]) => Record, + sourceMapPath: string; + outputModulesPath: string; + modulesPaths: string[]; + collect: (sources: unknown[], modulesPaths: string[]) => Record; }>): void { if (!sourceMapPath) { logger.error('First argument `source-map-path` is missing!'); @@ -129,9 +124,7 @@ export default class ModulesCollector { } const sources: unknown[] = map.sources; - const modules = collect - ? collect(sources, modulesPaths) - : ModulesCollector.collect(sources, modulesPaths); + const modules = collect ? collect(sources, modulesPaths) : ModulesCollector.collect(sources, modulesPaths); const outputModulesDirPath = dirname(outputModulesPath); if (!existsSync(outputModulesDirPath)) { @@ -140,5 +133,4 @@ export default class ModulesCollector { writeFileSync(outputModulesPath, JSON.stringify(modules, null, 2)); logger.info(`Modules collected and saved to: ${outputModulesPath}`); } - } diff --git a/src/js/tools/collectModules.ts b/src/js/tools/collectModules.ts index 6c3bcfaf7f..ed386b2f50 100755 --- a/src/js/tools/collectModules.ts +++ b/src/js/tools/collectModules.ts @@ -5,8 +5,6 @@ import ModulesCollector from './ModulesCollector'; const sourceMapPath: string | undefined = argv[2]; const outputModulesPath: string | undefined = argv[3]; -const modulesPaths: string[] = argv[4] - ? argv[4].split(',') - : []; +const modulesPaths: string[] = argv[4] ? argv[4].split(',') : []; ModulesCollector.run({ sourceMapPath, outputModulesPath, modulesPaths }); diff --git a/src/js/tracing/gesturetracing.ts b/src/js/tracing/gesturetracing.ts index 2ae4391e77..8bc6f9d2b6 100644 --- a/src/js/tracing/gesturetracing.ts +++ b/src/js/tracing/gesturetracing.ts @@ -56,7 +56,9 @@ export function sentryTraceGesture( return gesture; } if (!gestureCandidate.handlers) { - logger.warn('[GestureTracing] Can not wrap gesture without handlers. If you want to wrap a gesture composition wrap individual gestures.'); + logger.warn( + '[GestureTracing] Can not wrap gesture without handlers. If you want to wrap a gesture composition wrap individual gestures.', + ); return gesture; } if (!label) { @@ -65,14 +67,18 @@ export function sentryTraceGesture( } const hub = options.getCurrentHub?.() || getCurrentHub(); - const name = gestureCandidate.handlerName.length > GESTURE_POSTFIX_LENGTH - ? gestureCandidate.handlerName - .substring(0, gestureCandidate.handlerName.length - GESTURE_POSTFIX_LENGTH).toLowerCase() - : ACTION_GESTURE_FALLBACK; + const name = + gestureCandidate.handlerName.length > GESTURE_POSTFIX_LENGTH + ? gestureCandidate.handlerName + .substring(0, gestureCandidate.handlerName.length - GESTURE_POSTFIX_LENGTH) + .toLowerCase() + : ACTION_GESTURE_FALLBACK; const originalOnBegin = gestureCandidate.handlers.onBegin; (gesture as unknown as Required).handlers.onBegin = (event: GestureEvent) => { - hub.getClient()?.getIntegration(ReactNativeTracing) + hub + .getClient() + ?.getIntegration(ReactNativeTracing) ?.startUserInteractionTransaction({ elementId: label, op: `${UI_ACTION}.${name}` }); addGestureBreadcrumb(`Gesture ${label} begin.`, { event, hub, name }); diff --git a/src/js/tracing/index.ts b/src/js/tracing/index.ts index a811d084e8..a78acfed15 100644 --- a/src/js/tracing/index.ts +++ b/src/js/tracing/index.ts @@ -1,9 +1,6 @@ export { ReactNativeTracing } from './reactnativetracing'; -export { - RoutingInstrumentation, - RoutingInstrumentationInstance, -} from './routingInstrumentation'; +export { RoutingInstrumentation, RoutingInstrumentationInstance } from './routingInstrumentation'; export { ReactNavigationInstrumentation, @@ -13,16 +10,10 @@ export { export { ReactNavigationV4Instrumentation } from './reactnavigationv4'; export { ReactNativeNavigationInstrumentation } from './reactnativenavigation'; -export { - ReactNavigationCurrentRoute, - ReactNavigationRoute, - ReactNavigationTransactionContext, -} from './types'; +export { ReactNavigationCurrentRoute, ReactNavigationRoute, ReactNavigationTransactionContext } from './types'; export { ReactNativeProfiler } from './reactnativeprofiler'; -export { - sentryTraceGesture, -} from './gesturetracing'; +export { sentryTraceGesture } from './gesturetracing'; export * from './ops'; diff --git a/src/js/tracing/nativeframes.ts b/src/js/tracing/nativeframes.ts index e2e11a158b..c121b5194a 100644 --- a/src/js/tracing/nativeframes.ts +++ b/src/js/tracing/nativeframes.ts @@ -7,9 +7,9 @@ import { NATIVE } from '../wrapper'; import { instrumentChildSpanFinish } from './utils'; export interface FramesMeasurements extends Measurements { - 'frames_total': { value: number, unit: MeasurementUnit }; - 'frames_slow': { value: number, unit: MeasurementUnit }; - 'frames_frozen': { value: number, unit: MeasurementUnit }; + frames_total: { value: number; unit: MeasurementUnit }; + frames_slow: { value: number; unit: MeasurementUnit }; + frames_frozen: { value: number; unit: MeasurementUnit }; } /** @@ -23,10 +23,7 @@ const MARGIN_OF_ERROR_SECONDS = 0.05; */ export class NativeFramesInstrumentation { /** The native frames at the transaction finish time, keyed by traceId. */ - private _finishFrames: Map< - string, - { timestamp: number; nativeFrames: NativeFramesResponse | null } - > = new Map(); + private _finishFrames: Map = new Map(); /** The listeners for each native frames response, keyed by traceId */ private _framesListeners: Map void> = new Map(); /** The native frames at the finish time of the most recent span. */ @@ -35,15 +32,10 @@ export class NativeFramesInstrumentation { nativeFrames: NativeFramesResponse; }; - public constructor( - addGlobalEventProcessor: (e: EventProcessor) => void, - doesExist: () => boolean - ) { - logger.log( - '[ReactNativeTracing] Native frames instrumentation initialized.' - ); + public constructor(addGlobalEventProcessor: (e: EventProcessor) => void, doesExist: () => boolean) { + logger.log('[ReactNativeTracing] Native frames instrumentation initialized.'); - addGlobalEventProcessor((event) => this._processEvent(event, doesExist)); + addGlobalEventProcessor(event => this._processEvent(event, doesExist)); } /** @@ -51,13 +43,15 @@ export class NativeFramesInstrumentation { * Logs the native frames at this start point and instruments child span finishes. */ public onTransactionStart(transaction: Transaction): void { - void NATIVE.fetchNativeFrames().then((framesMetrics) => { - if (framesMetrics) { - transaction.setData('__startFrames', framesMetrics); - } - }).then(undefined, (error) => { - logger.error(`[ReactNativeTracing] Error while fetching native frames: ${error}`); - }); + void NATIVE.fetchNativeFrames() + .then(framesMetrics => { + if (framesMetrics) { + transaction.setData('__startFrames', framesMetrics); + } + }) + .then(undefined, error => { + logger.error(`[ReactNativeTracing] Error while fetching native frames: ${error}`); + }); instrumentChildSpanFinish(transaction, (_: Span, endTimestamp?: number) => { if (!endTimestamp) { @@ -80,16 +74,18 @@ export class NativeFramesInstrumentation { private _onSpanFinish(): void { const timestamp = timestampInSeconds(); - void NATIVE.fetchNativeFrames().then((nativeFrames) => { - if (nativeFrames) { - this._lastSpanFinishFrames = { - timestamp, - nativeFrames, - }; - } - }).then(undefined, (error) => { - logger.error(`[ReactNativeTracing] Error while fetching native frames: ${error}`); - }); + void NATIVE.fetchNativeFrames() + .then(nativeFrames => { + if (nativeFrames) { + this._lastSpanFinishFrames = { + timestamp, + nativeFrames, + }; + } + }) + .then(undefined, error => { + logger.error(`[ReactNativeTracing] Error while fetching native frames: ${error}`); + }); } /** @@ -98,13 +94,13 @@ export class NativeFramesInstrumentation { private async _getFramesMeasurements( traceId: string, finalEndTimestamp: number, - startFrames: NativeFramesResponse + startFrames: NativeFramesResponse, ): Promise { if (this._finishFrames.has(traceId)) { return this._prepareMeasurements(traceId, finalEndTimestamp, startFrames); } - return new Promise((resolve) => { + return new Promise(resolve => { const timeout = setTimeout(() => { this._framesListeners.delete(traceId); @@ -112,9 +108,7 @@ export class NativeFramesInstrumentation { }, 2000); this._framesListeners.set(traceId, () => { - resolve( - this._prepareMeasurements(traceId, finalEndTimestamp, startFrames) - ); + resolve(this._prepareMeasurements(traceId, finalEndTimestamp, startFrames)); clearTimeout(timeout); this._framesListeners.delete(traceId); @@ -128,7 +122,7 @@ export class NativeFramesInstrumentation { private _prepareMeasurements( traceId: string, finalEndTimestamp: number, // The actual transaction finish time. - startFrames: NativeFramesResponse + startFrames: NativeFramesResponse, ): FramesMeasurements | null { let finalFinishFrames: NativeFramesResponse | undefined; @@ -142,8 +136,7 @@ export class NativeFramesInstrumentation { finalFinishFrames = finish.nativeFrames; } else if ( this._lastSpanFinishFrames && - Math.abs(this._lastSpanFinishFrames.timestamp - finalEndTimestamp) < - MARGIN_OF_ERROR_SECONDS + Math.abs(this._lastSpanFinishFrames.timestamp - finalEndTimestamp) < MARGIN_OF_ERROR_SECONDS ) { // Fallback to the last span finish if it is within the margin of error of the actual finish timestamp. // This should be the case for trimEnd. @@ -155,31 +148,26 @@ export class NativeFramesInstrumentation { const measurements = { frames_total: { value: finalFinishFrames.totalFrames - startFrames.totalFrames, - unit: 'none' + unit: 'none', }, frames_frozen: { value: finalFinishFrames.frozenFrames - startFrames.frozenFrames, - unit: 'none' + unit: 'none', }, frames_slow: { value: finalFinishFrames.slowFrames - startFrames.slowFrames, - unit: 'none' + unit: 'none', }, }; - return measurements; } /** * Fetch finish frames for a transaction at the current time. Calls any awaiting listeners. */ - private async _fetchFramesForTransaction( - transaction: Transaction - ): Promise { - const startFrames = transaction.data.__startFrames as - | NativeFramesResponse - | undefined; + private async _fetchFramesForTransaction(transaction: Transaction): Promise { + const startFrames = transaction.data.__startFrames as NativeFramesResponse | undefined; // This timestamp marks when the finish frames were retrieved. It should be pretty close to the transaction finish. const timestamp = timestampInSeconds(); @@ -206,7 +194,7 @@ export class NativeFramesInstrumentation { this._finishFrames.delete(transaction.traceId); logger.log( - `[NativeFrames] Native frames timed out for ${transaction.op} transaction ${transaction.name}. Not adding native frames measurements.` + `[NativeFrames] Native frames timed out for ${transaction.op} transaction ${transaction.name}. Not adding native frames measurements.`, ); } } @@ -215,20 +203,12 @@ export class NativeFramesInstrumentation { * Adds frames measurements to an event. Called from a valid event processor. * Awaits for finish frames if needed. */ - private async _processEvent( - event: Event, - doesExist: () => boolean - ): Promise { + private async _processEvent(event: Event, doesExist: () => boolean): Promise { if (!doesExist()) { return event; } - if ( - event.type === 'transaction' && - event.transaction && - event.contexts && - event.contexts.trace - ) { + if (event.type === 'transaction' && event.transaction && event.contexts && event.contexts.trace) { const traceContext = event.contexts.trace as { data?: { [key: string]: unknown }; trace_id: string; @@ -242,21 +222,18 @@ export class NativeFramesInstrumentation { const measurements = await this._getFramesMeasurements( traceId, event.timestamp, - traceContext.data.__startFrames as NativeFramesResponse + traceContext.data.__startFrames as NativeFramesResponse, ); if (!measurements) { logger.log( - `[NativeFrames] Could not fetch native frames for ${traceContext.op} transaction ${event.transaction}. Not adding native frames measurements.` + `[NativeFrames] Could not fetch native frames for ${traceContext.op} transaction ${event.transaction}. Not adding native frames measurements.`, ); } else { logger.log( - `[Measurements] Adding measurements to ${traceContext.op - } transaction ${event.transaction}: ${JSON.stringify( - measurements, - undefined, - 2 - )}` + `[Measurements] Adding measurements to ${traceContext.op} transaction ${ + event.transaction + }: ${JSON.stringify(measurements, undefined, 2)}`, ); event.measurements = { diff --git a/src/js/tracing/ops.ts b/src/js/tracing/ops.ts index fa852bcfe8..0f574d89b9 100644 --- a/src/js/tracing/ops.ts +++ b/src/js/tracing/ops.ts @@ -1,4 +1,3 @@ - export const DEFAULT = 'default'; export const NAVIGATION = 'navigation'; diff --git a/src/js/tracing/reactnativenavigation.ts b/src/js/tracing/reactnativenavigation.ts index e50715ec20..ed72443f43 100644 --- a/src/js/tracing/reactnativenavigation.ts +++ b/src/js/tracing/reactnativenavigation.ts @@ -2,12 +2,8 @@ import type { Transaction as TransactionType, TransactionContext } from '@sentry import { logger } from '@sentry/utils'; import type { EmitterSubscription } from 'react-native'; -import type { - OnConfirmRoute, - TransactionCreator} from './routingInstrumentation'; -import { - InternalRoutingInstrumentation -} from './routingInstrumentation'; +import type { OnConfirmRoute, TransactionCreator } from './routingInstrumentation'; +import { InternalRoutingInstrumentation } from './routingInstrumentation'; import type { BeforeNavigate, RouteChangeContextData } from './types'; import { customTransactionSource, defaultTransactionSource, getBlankTransactionContext } from './utils'; @@ -38,11 +34,7 @@ interface ComponentEvent { componentId: string; } -type ComponentType = - | 'Component' - | 'TopBarTitle' - | 'TopBarBackground' - | 'TopBarButton'; +type ComponentType = 'Component' | 'TopBarTitle' | 'TopBarBackground' | 'TopBarButton'; export interface ComponentWillAppearEvent extends ComponentEvent { componentName: string; @@ -59,15 +51,9 @@ export interface BottomTabPressedEvent { } export interface EventsRegistry { - registerComponentWillAppearListener( - callback: (event: ComponentWillAppearEvent) => void - ): EmitterSubscription; - registerCommandListener( - callback: (name: string, params: unknown) => void - ): EventSubscription; - registerBottomTabPressedListener( - callback: (event: BottomTabPressedEvent) => void - ): EmitterSubscription; + registerComponentWillAppearListener(callback: (event: ComponentWillAppearEvent) => void): EmitterSubscription; + registerCommandListener(callback: (name: string, params: unknown) => void): EventSubscription; + registerBottomTabPressedListener(callback: (event: BottomTabPressedEvent) => void): EmitterSubscription; } export interface NavigationDelegate { @@ -99,7 +85,7 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum public constructor( /** The react native navigation `NavigationDelegate`. This is usually the import named `Navigation`. */ navigation: unknown, - options: Partial = {} + options: Partial = {}, ) { super(); @@ -117,29 +103,17 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum public registerRoutingInstrumentation( listener: TransactionCreator, beforeNavigate: BeforeNavigate, - onConfirmRoute: OnConfirmRoute + onConfirmRoute: OnConfirmRoute, ): void { - super.registerRoutingInstrumentation( - listener, - beforeNavigate, - onConfirmRoute - ); + super.registerRoutingInstrumentation(listener, beforeNavigate, onConfirmRoute); - this._navigation - .events() - .registerCommandListener(this._onNavigation.bind(this)); + this._navigation.events().registerCommandListener(this._onNavigation.bind(this)); if (this._options.enableTabsInstrumentation) { - this._navigation - .events() - .registerBottomTabPressedListener(this._onNavigation.bind(this)); + this._navigation.events().registerBottomTabPressedListener(this._onNavigation.bind(this)); } - this._navigation - .events() - .registerComponentWillAppearListener( - this._onComponentWillAppear.bind(this) - ); + this._navigation.events().registerComponentWillAppearListener(this._onComponentWillAppear.bind(this)); } /** @@ -151,12 +125,12 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum } this._latestTransaction = this.onRouteWillChange( - getBlankTransactionContext(ReactNativeNavigationInstrumentation.name) + getBlankTransactionContext(ReactNativeNavigationInstrumentation.name), ); this._stateChangeTimeout = setTimeout( this._discardLatestTransaction.bind(this), - this._options.routeChangeTimeoutMs + this._options.routeChangeTimeoutMs, ); } @@ -169,8 +143,7 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum } // We ignore actions that pertain to the same screen. - const isSameComponent = this._prevComponentEvent - && event.componentId === this._prevComponentEvent.componentId; + const isSameComponent = this._prevComponentEvent && event.componentId === this._prevComponentEvent.componentId; if (isSameComponent) { this._discardLatestTransaction(); return; @@ -179,9 +152,7 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum this._clearStateChangeTimeout(); const originalContext = this._latestTransaction.toContext(); - const routeHasBeenSeen = this._recentComponentIds.includes( - event.componentId - ); + const routeHasBeenSeen = this._recentComponentIds.includes(event.componentId); const data: RouteChangeContextData = { ...originalContext.data, @@ -192,9 +163,9 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum }, previousRoute: this._prevComponentEvent ? { - ...this._prevComponentEvent, - name: this._prevComponentEvent?.componentName, - } + ...this._prevComponentEvent, + name: this._prevComponentEvent?.componentName, + } : null, }; @@ -230,7 +201,7 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum // This block is to catch users not returning a transaction context if (!finalContext) { logger.error( - `[${ReactNativeNavigationInstrumentation.name}] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.` + `[${ReactNativeNavigationInstrumentation.name}] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.`, ); finalContext = { @@ -241,7 +212,7 @@ export class ReactNativeNavigationInstrumentation extends InternalRoutingInstrum if (finalContext.sampled === false) { logger.log( - `[${ReactNativeNavigationInstrumentation.name}] Will not send transaction "${finalContext.name}" due to beforeNavigate.` + `[${ReactNativeNavigationInstrumentation.name}] Will not send transaction "${finalContext.name}" due to beforeNavigate.`, ); } diff --git a/src/js/tracing/reactnativetracing.ts b/src/js/tracing/reactnativetracing.ts index 020f5ad718..cfa0e166d1 100644 --- a/src/js/tracing/reactnativetracing.ts +++ b/src/js/tracing/reactnativetracing.ts @@ -1,24 +1,14 @@ /* eslint-disable max-lines */ import type { Hub } from '@sentry/core'; import { getCurrentHub } from '@sentry/core'; -import type { - IdleTransaction, - RequestInstrumentationOptions, - Transaction -} from '@sentry/tracing'; +import type { IdleTransaction, RequestInstrumentationOptions, Transaction } from '@sentry/tracing'; import { defaultRequestInstrumentationOptions, - getActiveTransaction - , + getActiveTransaction, instrumentOutgoingRequests, - startIdleTransaction + startIdleTransaction, } from '@sentry/tracing'; -import type { - EventProcessor, - Integration, - Transaction as TransactionType, - TransactionContext, -} from '@sentry/types'; +import type { EventProcessor, Integration, Transaction as TransactionType, TransactionContext } from '@sentry/types'; import { logger } from '@sentry/utils'; import { APP_START_COLD, APP_START_WARM } from '../measurements'; @@ -26,24 +16,13 @@ import type { NativeAppStartResponse } from '../NativeRNSentry'; import type { RoutingInstrumentationInstance } from '../tracing/routingInstrumentation'; import { NATIVE } from '../wrapper'; import { NativeFramesInstrumentation } from './nativeframes'; -import { - APP_START_COLD as APP_START_COLD_OP, - APP_START_WARM as APP_START_WARM_OP, - UI_LOAD, -} from './ops'; +import { APP_START_COLD as APP_START_COLD_OP, APP_START_WARM as APP_START_WARM_OP, UI_LOAD } from './ops'; import { StallTrackingInstrumentation } from './stalltracking'; -import { - onlySampleIfChildSpans, -} from './transaction'; +import { onlySampleIfChildSpans } from './transaction'; import type { BeforeNavigate, RouteChangeContextData } from './types'; -import { - adjustTransactionDuration, - getTimeOriginMilliseconds, - isNearToNow, -} from './utils'; +import { adjustTransactionDuration, getTimeOriginMilliseconds, isNearToNow } from './utils'; -export interface ReactNativeTracingOptions - extends RequestInstrumentationOptions { +export interface ReactNativeTracingOptions extends RequestInstrumentationOptions { /** * @deprecated Replaced by idleTimeoutMs */ @@ -128,7 +107,7 @@ const defaultReactNativeTracingOptions: ReactNativeTracingOptions = { idleTimeoutMs: 1000, finalTimeoutMs: 600000, ignoreEmptyBackNavigationTransactions: true, - beforeNavigate: (context) => context, + beforeNavigate: context => context, enableAppStartTracking: true, enableNativeFramesTracking: true, enableStallTracking: true, @@ -167,17 +146,19 @@ export class ReactNativeTracing implements Integration { this.options = { ...defaultReactNativeTracingOptions, ...options, - finalTimeoutMs: options.finalTimeoutMs + finalTimeoutMs: + options.finalTimeoutMs ?? // eslint-disable-next-line deprecation/deprecation - ?? (typeof options.maxTransactionDuration === 'number' - // eslint-disable-next-line deprecation/deprecation - ? options.maxTransactionDuration * 1000 - : undefined) - ?? defaultReactNativeTracingOptions.finalTimeoutMs, - idleTimeoutMs: options.idleTimeoutMs + (typeof options.maxTransactionDuration === 'number' + ? // eslint-disable-next-line deprecation/deprecation + options.maxTransactionDuration * 1000 + : undefined) ?? + defaultReactNativeTracingOptions.finalTimeoutMs, + idleTimeoutMs: + options.idleTimeoutMs ?? // eslint-disable-next-line deprecation/deprecation - ?? options.idleTimeout - ?? defaultReactNativeTracingOptions.idleTimeoutMs, + options.idleTimeout ?? + defaultReactNativeTracingOptions.idleTimeoutMs, }; } @@ -187,7 +168,7 @@ export class ReactNativeTracing implements Integration { public setupOnce( // @ts-ignore TODO addGlobalEventProcessor: (callback: EventProcessor) => void, - getCurrentHub: () => Hub + getCurrentHub: () => Hub, ): void { // eslint-disable-next-line @typescript-eslint/unbound-method const { @@ -212,18 +193,15 @@ export class ReactNativeTracing implements Integration { if (enableNativeFramesTracking) { NATIVE.enableNativeFramesTracking(); - this.nativeFramesInstrumentation = new NativeFramesInstrumentation( - addGlobalEventProcessor, - () => { - const self = getCurrentHub().getIntegration(ReactNativeTracing); - - if (self) { - return !!self.nativeFramesInstrumentation; - } + this.nativeFramesInstrumentation = new NativeFramesInstrumentation(addGlobalEventProcessor, () => { + const self = getCurrentHub().getIntegration(ReactNativeTracing); - return false; + if (self) { + return !!self.nativeFramesInstrumentation; } - ); + + return false; + }); } else { NATIVE.disableNativeFramesTracking(); } @@ -236,12 +214,10 @@ export class ReactNativeTracing implements Integration { routingInstrumentation.registerRoutingInstrumentation( this._onRouteWillChange.bind(this), this.options.beforeNavigate, - this._onConfirmRoute.bind(this) + this._onConfirmRoute.bind(this), ); } else { - logger.log( - '[ReactNativeTracing] Not instrumenting route changes as routingInstrumentation has not been set.' - ); + logger.log('[ReactNativeTracing] Not instrumenting route changes as routingInstrumentation has not been set.'); } instrumentOutgoingRequests({ @@ -267,15 +243,9 @@ export class ReactNativeTracing implements Integration { /** * To be called on a transaction finish. Cannot have async methods. */ - public onTransactionFinish( - transaction: Transaction, - endTimestamp?: number - ): void { + public onTransactionFinish(transaction: Transaction, endTimestamp?: number): void { this.nativeFramesInstrumentation?.onTransactionFinish(transaction); - this.stallTrackingInstrumentation?.onTransactionFinish( - transaction, - endTimestamp - ); + this.stallTrackingInstrumentation?.onTransactionFinish(transaction, endTimestamp); } /** @@ -299,7 +269,9 @@ export class ReactNativeTracing implements Integration { return; } if (!this.options.routingInstrumentation) { - logger.error('[ReactNativeTracing] User Interaction Tracing is not working because no routing instrumentation is set.'); + logger.error( + '[ReactNativeTracing] User Interaction Tracing is not working because no routing instrumentation is set.', + ); return; } if (!elementId) { @@ -316,7 +288,9 @@ export class ReactNativeTracing implements Integration { const activeTransactionIsNotInteraction = activeTransaction?.spanId !== this._inflightInteractionTransaction?.spanId; if (activeTransaction && activeTransactionIsNotInteraction) { - logger.warn(`[ReactNativeTracing] Did not create ${op} transaction because active transaction ${activeTransaction.name} exists on the scope.`); + logger.warn( + `[ReactNativeTracing] Did not create ${op} transaction because active transaction ${activeTransaction.name} exists on the scope.`, + ); return; } @@ -333,13 +307,7 @@ export class ReactNativeTracing implements Integration { op, trimEnd: true, }; - this._inflightInteractionTransaction = startIdleTransaction( - hub, - context, - idleTimeoutMs, - finalTimeoutMs, - true, - ); + this._inflightInteractionTransaction = startIdleTransaction(hub, context, idleTimeoutMs, finalTimeoutMs, true); this._inflightInteractionTransaction.registerBeforeFinishCallback((transaction: IdleTransaction) => { this._inflightInteractionTransaction = undefined; this.onTransactionFinish(transaction); @@ -389,10 +357,7 @@ export class ReactNativeTracing implements Integration { /** * Adds app start measurements and starts a child span on a transaction. */ - private _addAppStartData( - transaction: IdleTransaction, - appStart: NativeAppStartResponse - ): void { + private _addAppStartData(transaction: IdleTransaction, appStart: NativeAppStartResponse): void { if (!this._appStartFinishTimestamp) { logger.warn('App start was never finished.'); return; @@ -408,8 +373,7 @@ export class ReactNativeTracing implements Integration { endTimestamp: this._appStartFinishTimestamp, }); - const appStartDurationMilliseconds = - this._appStartFinishTimestamp * 1000 - appStart.appStartTime; + const appStartDurationMilliseconds = this._appStartFinishTimestamp * 1000 - appStart.appStartTime; // we filter out app start more than 60s. // this could be due to many different reasons. @@ -423,9 +387,7 @@ export class ReactNativeTracing implements Integration { } /** To be called when the route changes, but BEFORE the components of the new route mount. */ - private _onRouteWillChange( - context: TransactionContext - ): TransactionType | undefined { + private _onRouteWillChange(context: TransactionContext): TransactionType | undefined { return this._createRouteTransaction(context); } @@ -436,7 +398,7 @@ export class ReactNativeTracing implements Integration { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access this._currentRoute = context.data?.route?.name; - this._getCurrentHub?.().configureScope((scope) => { + this._getCurrentHub?.().configureScope(scope => { if (context.data) { const contextData = context.data as RouteChangeContextData; @@ -457,19 +419,15 @@ export class ReactNativeTracing implements Integration { } /** Create routing idle transaction. */ - private _createRouteTransaction( - context: TransactionContext - ): IdleTransaction | undefined { + private _createRouteTransaction(context: TransactionContext): IdleTransaction | undefined { if (!this._getCurrentHub) { - logger.warn( - `[ReactNativeTracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.` - ); + logger.warn(`[ReactNativeTracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.`); return undefined; } if (this._inflightInteractionTransaction) { logger.log( - `[ReactNativeTracing] Canceling ${this._inflightInteractionTransaction.op} transaction because navigation ${context.op}.` + `[ReactNativeTracing] Canceling ${this._inflightInteractionTransaction.op} transaction because navigation ${context.op}.`, ); this._inflightInteractionTransaction.setStatus('cancelled'); this._inflightInteractionTransaction.finish(); @@ -484,30 +442,19 @@ export class ReactNativeTracing implements Integration { }; const hub = this._getCurrentHub(); - const idleTransaction = startIdleTransaction( - hub as Hub, - expandedContext, - idleTimeoutMs, - finalTimeoutMs, - true - ); + const idleTransaction = startIdleTransaction(hub as Hub, expandedContext, idleTimeoutMs, finalTimeoutMs, true); this.onTransactionStart(idleTransaction); - logger.log( - `[ReactNativeTracing] Starting ${context.op} transaction "${context.name}" on scope` - ); + logger.log(`[ReactNativeTracing] Starting ${context.op} transaction "${context.name}" on scope`); - idleTransaction.registerBeforeFinishCallback( - (transaction, endTimestamp) => { - this.onTransactionFinish(transaction, endTimestamp); - } - ); + idleTransaction.registerBeforeFinishCallback((transaction, endTimestamp) => { + this.onTransactionFinish(transaction, endTimestamp); + }); - idleTransaction.registerBeforeFinishCallback((transaction) => { + idleTransaction.registerBeforeFinishCallback(transaction => { if (this.options.enableAppStartTracking && this._awaitingAppStartData) { - transaction.startTimestamp = - this._awaitingAppStartData.appStartTime / 1000; + transaction.startTimestamp = this._awaitingAppStartData.appStartTime / 1000; transaction.op = 'ui.load'; this._addAppStartData(transaction, this._awaitingAppStartData); @@ -516,28 +463,20 @@ export class ReactNativeTracing implements Integration { } }); - idleTransaction.registerBeforeFinishCallback( - (transaction, endTimestamp) => { - adjustTransactionDuration( - finalTimeoutMs, - transaction, - endTimestamp - ); - } - ); + idleTransaction.registerBeforeFinishCallback((transaction, endTimestamp) => { + adjustTransactionDuration(finalTimeoutMs, transaction, endTimestamp); + }); if (this.options.ignoreEmptyBackNavigationTransactions) { - idleTransaction.registerBeforeFinishCallback((transaction) => { + idleTransaction.registerBeforeFinishCallback(transaction => { if ( // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access transaction.data?.route?.hasBeenSeen && (!transaction.spanRecorder || - transaction.spanRecorder.spans.filter( - (span) => span.spanId !== transaction.spanId - ).length === 0) + transaction.spanRecorder.spans.filter(span => span.spanId !== transaction.spanId).length === 0) ) { logger.log( - '[ReactNativeTracing] Not sampling transaction as route has been seen before. Pass ignoreEmptyBackNavigationTransactions = false to disable this feature.' + '[ReactNativeTracing] Not sampling transaction as route has been seen before. Pass ignoreEmptyBackNavigationTransactions = false to disable this feature.', ); // Route has been seen before and has no child spans. transaction.sampled = false; diff --git a/src/js/tracing/reactnavigation.ts b/src/js/tracing/reactnavigation.ts index 89429832e5..54ad946fcd 100644 --- a/src/js/tracing/reactnavigation.ts +++ b/src/js/tracing/reactnavigation.ts @@ -3,17 +3,9 @@ import type { Transaction as TransactionType, TransactionContext } from '@sentry import { logger } from '@sentry/utils'; import { RN_GLOBAL_OBJ } from '../utils/worldwide'; -import type { - OnConfirmRoute, - TransactionCreator} from './routingInstrumentation'; -import { - InternalRoutingInstrumentation -} from './routingInstrumentation'; -import type { - BeforeNavigate, - ReactNavigationTransactionContext, - RouteChangeContextData, -} from './types'; +import type { OnConfirmRoute, TransactionCreator } from './routingInstrumentation'; +import { InternalRoutingInstrumentation } from './routingInstrumentation'; +import type { BeforeNavigate, ReactNavigationTransactionContext, RouteChangeContextData } from './types'; import { customTransactionSource, defaultTransactionSource, getBlankTransactionContext } from './utils'; export interface NavigationRoute { @@ -83,13 +75,9 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati public registerRoutingInstrumentation( listener: TransactionCreator, beforeNavigate: BeforeNavigate, - onConfirmRoute: OnConfirmRoute + onConfirmRoute: OnConfirmRoute, ): void { - super.registerRoutingInstrumentation( - listener, - beforeNavigate, - onConfirmRoute - ); + super.registerRoutingInstrumentation(listener, beforeNavigate, onConfirmRoute); // We create an initial state here to ensure a transaction gets created before the first route mounts. if (!this._initialStateHandled) { @@ -125,11 +113,11 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati if (this._navigationContainer) { this._navigationContainer.addListener( '__unsafe_action__', // This action is emitted on every dispatch - this._onDispatch.bind(this) + this._onDispatch.bind(this), ); this._navigationContainer.addListener( 'state', // This action is emitted on every state change - this._onStateChange.bind(this) + this._onStateChange.bind(this), ); if (!this._initialStateHandled) { @@ -140,20 +128,18 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati this._initialStateHandled = true; } else { logger.log( - '[ReactNavigationInstrumentation] Navigation container registered, but integration has not been setup yet.' + '[ReactNavigationInstrumentation] Navigation container registered, but integration has not been setup yet.', ); } } RN_GLOBAL_OBJ.__sentry_rn_v5_registered = true; } else { - logger.warn( - '[ReactNavigationInstrumentation] Received invalid navigation container ref!' - ); + logger.warn('[ReactNavigationInstrumentation] Received invalid navigation container ref!'); } } else { logger.log( - '[ReactNavigationInstrumentation] Instrumentation already exists, but register has been called again, doing nothing.' + '[ReactNavigationInstrumentation] Instrumentation already exists, but register has been called again, doing nothing.', ); } } @@ -166,21 +152,19 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati private _onDispatch(): void { if (this._latestTransaction) { logger.log( - '[ReactNavigationInstrumentation] A transaction was detected that turned out to be a noop, discarding.' + '[ReactNavigationInstrumentation] A transaction was detected that turned out to be a noop, discarding.', ); this._discardLatestTransaction(); this._clearStateChangeTimeout(); } this._latestTransaction = this.onRouteWillChange( - getBlankTransactionContext( - ReactNavigationInstrumentation.instrumentationName - ) + getBlankTransactionContext(ReactNavigationInstrumentation.instrumentationName), ); this._stateChangeTimeout = setTimeout( this._discardLatestTransaction.bind(this), - this._options.routeChangeTimeoutMs + this._options.routeChangeTimeoutMs, ); } @@ -193,7 +177,7 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati if (!this._navigationContainer) { logger.warn( - '[ReactNavigationInstrumentation] Missing navigation container ref. Route transactions will not be sent.' + '[ReactNavigationInstrumentation] Missing navigation container ref. Route transactions will not be sent.', ); return; @@ -262,7 +246,7 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati // This block is to catch users not returning a transaction context if (!finalContext) { logger.error( - `[ReactNavigationInstrumentation] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.` + `[ReactNavigationInstrumentation] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.`, ); finalContext = { @@ -274,7 +258,7 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati // Note: finalContext.sampled will be false at this point only if the user sets it to be so in beforeNavigate. if (finalContext.sampled === false) { logger.log( - `[ReactNavigationInstrumentation] Will not send transaction "${finalContext.name}" due to beforeNavigate.` + `[ReactNavigationInstrumentation] Will not send transaction "${finalContext.name}" due to beforeNavigate.`, ); } else { // Clear the timeout so the transaction does not get cancelled. @@ -289,9 +273,7 @@ export class ReactNavigationInstrumentation extends InternalRoutingInstrumentati this._recentRouteKeys.push(key); if (this._recentRouteKeys.length > this._maxRecentRouteLen) { - this._recentRouteKeys = this._recentRouteKeys.slice( - this._recentRouteKeys.length - this._maxRecentRouteLen - ); + this._recentRouteKeys = this._recentRouteKeys.slice(this._recentRouteKeys.length - this._maxRecentRouteLen); } }; @@ -325,8 +307,7 @@ export const BLANK_TRANSACTION_CONTEXT = { name: 'Route Change', op: 'navigation', tags: { - 'routing.instrumentation': - ReactNavigationInstrumentation.instrumentationName, + 'routing.instrumentation': ReactNavigationInstrumentation.instrumentationName, }, data: {}, }; diff --git a/src/js/tracing/reactnavigationv4.ts b/src/js/tracing/reactnavigationv4.ts index efd6a411f9..8d7f302558 100644 --- a/src/js/tracing/reactnavigationv4.ts +++ b/src/js/tracing/reactnavigationv4.ts @@ -3,17 +3,9 @@ import type { Transaction, TransactionContext } from '@sentry/types'; import { logger } from '@sentry/utils'; import { RN_GLOBAL_OBJ } from '../utils/worldwide'; -import type { - OnConfirmRoute, - TransactionCreator} from './routingInstrumentation'; -import { - InternalRoutingInstrumentation -} from './routingInstrumentation'; -import type { - BeforeNavigate, - ReactNavigationTransactionContext, - RouteChangeContextData, -} from './types'; +import type { OnConfirmRoute, TransactionCreator } from './routingInstrumentation'; +import { InternalRoutingInstrumentation } from './routingInstrumentation'; +import type { BeforeNavigate, ReactNavigationTransactionContext, RouteChangeContextData } from './types'; import { customTransactionSource, defaultTransactionSource } from './utils'; export interface NavigationRouteV4 { @@ -38,7 +30,7 @@ export interface AppContainerInstance { getStateForAction: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any action: any, - state: NavigationStateV4 + state: NavigationStateV4, ) => NavigationStateV4; }; }; @@ -96,19 +88,13 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { public registerRoutingInstrumentation( listener: TransactionCreator, beforeNavigate: BeforeNavigate, - onConfirmRoute: OnConfirmRoute + onConfirmRoute: OnConfirmRoute, ): void { - super.registerRoutingInstrumentation( - listener, - beforeNavigate, - onConfirmRoute - ); + super.registerRoutingInstrumentation(listener, beforeNavigate, onConfirmRoute); // Need to handle the initial state as the router patch will only attach transactions on subsequent route changes. if (!this._initialStateHandled) { - this._latestTransaction = this.onRouteWillChange( - INITIAL_TRANSACTION_CONTEXT_V4 - ); + this._latestTransaction = this.onRouteWillChange(INITIAL_TRANSACTION_CONTEXT_V4); if (this._appContainer) { this._updateLatestTransaction(); @@ -116,7 +102,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { } else { this._stateChangeTimeout = setTimeout( this._discardLatestTransaction.bind(this), - this._options.routeChangeTimeoutMs + this._options.routeChangeTimeoutMs, ); } } @@ -149,7 +135,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { this._updateLatestTransaction(); } else { logger.log( - '[ReactNavigationV4Instrumentation] App container registered, but integration has not been setup yet.' + '[ReactNavigationV4Instrumentation] App container registered, but integration has not been setup yet.', ); } this._initialStateHandled = true; @@ -157,9 +143,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { RN_GLOBAL_OBJ.__sentry_rn_v4_registered = true; } else { - logger.warn( - '[ReactNavigationV4Instrumentation] Received invalid app container ref!' - ); + logger.warn('[ReactNavigationV4Instrumentation] Received invalid app container ref!'); } } } @@ -187,13 +171,9 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { */ private _patchRouter(): void { if (this._appContainer) { - const originalGetStateForAction = this._appContainer._navigation.router - .getStateForAction; + const originalGetStateForAction = this._appContainer._navigation.router.getStateForAction; - this._appContainer._navigation.router.getStateForAction = ( - action, - state - ) => { + this._appContainer._navigation.router.getStateForAction = (action, state) => { const newState = originalGetStateForAction(action, state); this._onStateChange(newState); @@ -206,16 +186,11 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { /** * To be called on navigation state changes and creates the transaction. */ - private _onStateChange( - state: NavigationStateV4 | undefined, - updateLatestTransaction: boolean = false - ): void { + private _onStateChange(state: NavigationStateV4 | undefined, updateLatestTransaction: boolean = false): void { // it's not guaranteed that a state is always produced. // see: https://github.com/react-navigation/react-navigation/blob/45d419be93c34e900e8734ce98321ae875ac4997/packages/core/src/routers/SwitchRouter.js?rgh-link-date=2021-09-25T12%3A43%3A36Z#L301 if (!state || state === undefined) { - logger.warn( - '[ReactNavigationV4Instrumentation] onStateChange called without a valid state.' - ); + logger.warn('[ReactNavigationV4Instrumentation] onStateChange called without a valid state.'); return; } @@ -224,10 +199,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { // If the route is a different key, this is so we ignore actions that pertain to the same screen. if (!this._prevRoute || currentRoute.key !== this._prevRoute.key) { - const originalContext = this._getTransactionContext( - currentRoute, - this._prevRoute - ); + const originalContext = this._getTransactionContext(currentRoute, this._prevRoute); let mergedContext = originalContext; if (updateLatestTransaction && this._latestTransaction) { @@ -265,7 +237,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { // This block is to catch users not returning a transaction context if (!finalContext) { logger.error( - `[ReactNavigationV4Instrumentation] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.` + `[ReactNavigationV4Instrumentation] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.`, ); finalContext = { @@ -286,7 +258,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { */ private _getTransactionContext( route: NavigationRouteV4, - previousRoute?: NavigationRouteV4 + previousRoute?: NavigationRouteV4, ): ReactNavigationTransactionContext { const data: RouteChangeContextData = { route: { @@ -308,8 +280,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { name: route.routeName, op: 'navigation', tags: { - 'routing.instrumentation': - ReactNavigationV4Instrumentation.instrumentationName, + 'routing.instrumentation': ReactNavigationV4Instrumentation.instrumentationName, 'routing.route.name': route.routeName, }, data, @@ -319,9 +290,7 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { /** * Gets the current route given a navigation state */ - private _getCurrentRouteFromState( - state: NavigationStateV4 - ): NavigationRouteV4 { + private _getCurrentRouteFromState(state: NavigationStateV4): NavigationRouteV4 { const parentRoute = state.routes[state.index]; if ( @@ -341,16 +310,14 @@ class ReactNavigationV4Instrumentation extends InternalRoutingInstrumentation { this._recentRouteKeys.push(key); if (this._recentRouteKeys.length > this._maxRecentRouteLen) { - this._recentRouteKeys = this._recentRouteKeys.slice( - this._recentRouteKeys.length - this._maxRecentRouteLen - ); + this._recentRouteKeys = this._recentRouteKeys.slice(this._recentRouteKeys.length - this._maxRecentRouteLen); } }; /** Helper to log a transaction that was not sampled due to beforeNavigate */ private _onBeforeNavigateNotSampled = (transactionName: string): void => { logger.log( - `[ReactNavigationV4Instrumentation] Will not send transaction "${transactionName}" due to beforeNavigate.` + `[ReactNavigationV4Instrumentation] Will not send transaction "${transactionName}" due to beforeNavigate.`, ); }; @@ -368,8 +335,7 @@ const INITIAL_TRANSACTION_CONTEXT_V4: TransactionContext = { name: 'App Launch', op: 'navigation', tags: { - 'routing.instrumentation': - ReactNavigationV4Instrumentation.instrumentationName, + 'routing.instrumentation': ReactNavigationV4Instrumentation.instrumentationName, }, data: {}, metadata: { diff --git a/src/js/tracing/routingInstrumentation.ts b/src/js/tracing/routingInstrumentation.ts index 303a75e9d6..c7778fdcb2 100644 --- a/src/js/tracing/routingInstrumentation.ts +++ b/src/js/tracing/routingInstrumentation.ts @@ -3,9 +3,7 @@ import type { Transaction, TransactionContext } from '@sentry/types'; import type { BeforeNavigate } from './types'; -export type TransactionCreator = ( - context: TransactionContext -) => Transaction | undefined; +export type TransactionCreator = (context: TransactionContext) => Transaction | undefined; export type OnConfirmRoute = (context: TransactionContext) => void; @@ -26,7 +24,7 @@ export interface RoutingInstrumentationInstance { registerRoutingInstrumentation( listener: TransactionCreator, beforeNavigate: BeforeNavigate, - onConfirmRoute: OnConfirmRoute + onConfirmRoute: OnConfirmRoute, ): void; /** * To be called when the route changes, BEFORE the new route mounts. @@ -55,7 +53,7 @@ export class RoutingInstrumentation implements RoutingInstrumentationInstance { public registerRoutingInstrumentation( listener: TransactionCreator, beforeNavigate: BeforeNavigate, - onConfirmRoute: OnConfirmRoute + onConfirmRoute: OnConfirmRoute, ): void { this._tracingListener = listener; this._beforeNavigate = beforeNavigate; @@ -63,9 +61,7 @@ export class RoutingInstrumentation implements RoutingInstrumentationInstance { } /** @inheritdoc */ - public onRouteWillChange( - context: TransactionContext - ): Transaction | undefined { + public onRouteWillChange(context: TransactionContext): Transaction | undefined { const transaction = this._tracingListener?.(context); if (transaction) { @@ -81,9 +77,7 @@ export class RoutingInstrumentation implements RoutingInstrumentationInstance { */ export class InternalRoutingInstrumentation extends RoutingInstrumentation { /** @inheritdoc */ - public onRouteWillChange( - context: TransactionContext - ): Transaction | undefined { + public onRouteWillChange(context: TransactionContext): Transaction | undefined { return this._tracingListener?.(context); } } diff --git a/src/js/tracing/stalltracking.ts b/src/js/tracing/stalltracking.ts index 9886c4c8ce..9f3c9949d8 100644 --- a/src/js/tracing/stalltracking.ts +++ b/src/js/tracing/stalltracking.ts @@ -6,9 +6,9 @@ import { logger, timestampInSeconds } from '@sentry/utils'; import { STALL_COUNT, STALL_LONGEST_TIME, STALL_TOTAL_TIME } from '../measurements'; export interface StallMeasurements extends Measurements { - [STALL_COUNT]: { value: number, unit: MeasurementUnit }; - [STALL_TOTAL_TIME]: { value: number, unit: MeasurementUnit }; - [STALL_LONGEST_TIME]: { value: number, unit: MeasurementUnit }; + [STALL_COUNT]: { value: number; unit: MeasurementUnit }; + [STALL_TOTAL_TIME]: { value: number; unit: MeasurementUnit }; + [STALL_LONGEST_TIME]: { value: number; unit: MeasurementUnit }; } export type StallTrackingOptions = { @@ -59,9 +59,7 @@ export class StallTrackingInstrumentation { } > = new Map(); - public constructor( - options: StallTrackingOptions = { minimumStallThreshold: 50 } - ) { + public constructor(options: StallTrackingOptions = { minimumStallThreshold: 50 }) { this._minimumStallThreshold = options.minimumStallThreshold; } @@ -80,7 +78,7 @@ export class StallTrackingInstrumentation { public onTransactionStart(transaction: Transaction): void { if (this._statsByTransaction.has(transaction)) { logger.error( - '[StallTracking] Tried to start stall tracking on a transaction already being tracked. Measurements might be lost.' + '[StallTracking] Tried to start stall tracking on a transaction already being tracked. Measurements might be lost.', ); return; @@ -122,17 +120,12 @@ export class StallTrackingInstrumentation { * Stops stall tracking if no more transactions are running. * @returns The stall measurements */ - public onTransactionFinish( - transaction: Transaction | IdleTransaction, - passedEndTimestamp?: number - ): void { + public onTransactionFinish(transaction: Transaction | IdleTransaction, passedEndTimestamp?: number): void { const transactionStats = this._statsByTransaction.get(transaction); if (!transactionStats) { // Transaction has been flushed out somehow, we return null. - logger.log( - '[StallTracking] Stall measurements were not added to transaction due to exceeding the max count.' - ); + logger.log('[StallTracking] Stall measurements were not added to transaction due to exceeding the max count.'); this._statsByTransaction.delete(transaction); this._shouldStopTracking(); @@ -142,13 +135,8 @@ export class StallTrackingInstrumentation { const endTimestamp = passedEndTimestamp ?? transaction.endTimestamp; - const spans = transaction.spanRecorder - ? transaction.spanRecorder.spans - : []; - const finishedSpanCount = spans.reduce( - (count, s) => (s !== transaction && s.endTimestamp ? count + 1 : count), - 0 - ); + const spans = transaction.spanRecorder ? transaction.spanRecorder.spans : []; + const finishedSpanCount = spans.reduce((count, s) => (s !== transaction && s.endTimestamp ? count + 1 : count), 0); const trimEnd = transaction.toContext().trimEnd; const endWillBeTrimmed = trimEnd && finishedSpanCount > 0; @@ -171,10 +159,7 @@ export class StallTrackingInstrumentation { // There will be cancelled spans, which means that the end won't be trimmed const spansWillBeCancelled = spans.some( - (s) => - s !== transaction && - s.startTimestamp < endTimestamp && - !s.endTimestamp + s => s !== transaction && s.startTimestamp < endTimestamp && !s.endTimestamp, ); if (endWillBeTrimmed && !spansWillBeCancelled) { @@ -201,54 +186,47 @@ export class StallTrackingInstrumentation { if (!statsOnFinish) { if (typeof endTimestamp !== 'undefined') { - logger.log( - '[StallTracking] Stall measurements not added due to `endTimestamp` being set.' - ); + logger.log('[StallTracking] Stall measurements not added due to `endTimestamp` being set.'); } else if (trimEnd) { logger.log( - '[StallTracking] Stall measurements not added due to `trimEnd` being set but we could not determine the stall measurements at that time.' + '[StallTracking] Stall measurements not added due to `trimEnd` being set but we could not determine the stall measurements at that time.', ); } return; } - transaction.setMeasurement(STALL_COUNT, - statsOnFinish.stall_count.value - - transactionStats.atStart.stall_count.value, - transactionStats.atStart.stall_count.unit); + transaction.setMeasurement( + STALL_COUNT, + statsOnFinish.stall_count.value - transactionStats.atStart.stall_count.value, + transactionStats.atStart.stall_count.unit, + ); - transaction.setMeasurement(STALL_TOTAL_TIME, - statsOnFinish.stall_total_time.value - - transactionStats.atStart.stall_total_time.value, - transactionStats.atStart.stall_total_time.unit); + transaction.setMeasurement( + STALL_TOTAL_TIME, + statsOnFinish.stall_total_time.value - transactionStats.atStart.stall_total_time.value, + transactionStats.atStart.stall_total_time.unit, + ); - transaction.setMeasurement(STALL_LONGEST_TIME, + transaction.setMeasurement( + STALL_LONGEST_TIME, statsOnFinish.stall_longest_time.value, - statsOnFinish.stall_longest_time.unit); + statsOnFinish.stall_longest_time.unit, + ); } /** * Logs the finish time of the span for use in `trimEnd: true` transactions. */ - private _markSpanFinish( - transaction: Transaction, - spanEndTimestamp: number - ): void { + private _markSpanFinish(transaction: Transaction, spanEndTimestamp: number): void { const previousStats = this._statsByTransaction.get(transaction); if (previousStats) { - if ( - Math.abs(timestampInSeconds() - spanEndTimestamp) > - MARGIN_OF_ERROR_SECONDS - ) { + if (Math.abs(timestampInSeconds() - spanEndTimestamp) > MARGIN_OF_ERROR_SECONDS) { logger.log( - '[StallTracking] Span end not logged due to end timestamp being outside the margin of error from now.' + '[StallTracking] Span end not logged due to end timestamp being outside the margin of error from now.', ); - if ( - previousStats.atTimestamp && - previousStats.atTimestamp.timestamp < spanEndTimestamp - ) { + if (previousStats.atTimestamp && previousStats.atTimestamp.timestamp < spanEndTimestamp) { // We also need to delete the stat for the last span, as the transaction would be trimmed to this span not the last one. this._statsByTransaction.set(transaction, { ...previousStats, @@ -275,7 +253,8 @@ export class StallTrackingInstrumentation { stall_count: { value: this._stallCount, unit: 'none' }, stall_total_time: { value: this._totalStallTime, unit: 'millisecond' }, stall_longest_time: { - value: this._statsByTransaction.get(transaction)?.longestStallTime ?? 0, unit: 'millisecond' + value: this._statsByTransaction.get(transaction)?.longestStallTime ?? 0, + unit: 'millisecond', }, }; } @@ -333,19 +312,13 @@ export class StallTrackingInstrumentation { const now = timestampInSeconds() * 1000; const totalTimeTaken = now - this._lastIntervalMs; - if ( - totalTimeTaken >= - LOOP_TIMEOUT_INTERVAL_MS + this._minimumStallThreshold - ) { + if (totalTimeTaken >= LOOP_TIMEOUT_INTERVAL_MS + this._minimumStallThreshold) { const stallTime = totalTimeTaken - LOOP_TIMEOUT_INTERVAL_MS; this._stallCount += 1; this._totalStallTime += stallTime; for (const [transaction, value] of this._statsByTransaction.entries()) { - const longestStallTime = Math.max( - value.longestStallTime ?? 0, - stallTime - ); + const longestStallTime = Math.max(value.longestStallTime ?? 0, stallTime); this._statsByTransaction.set(transaction, { ...value, @@ -357,10 +330,7 @@ export class StallTrackingInstrumentation { this._lastIntervalMs = now; if (this.isTracking) { - this._timeout = setTimeout( - this._iteration.bind(this), - LOOP_TIMEOUT_INTERVAL_MS - ); + this._timeout = setTimeout(this._iteration.bind(this), LOOP_TIMEOUT_INTERVAL_MS); } } diff --git a/src/js/tracing/transaction.ts b/src/js/tracing/transaction.ts index b533ce0723..34540c8e63 100644 --- a/src/js/tracing/transaction.ts +++ b/src/js/tracing/transaction.ts @@ -6,15 +6,13 @@ import { logger } from '@sentry/utils'; * Idle Transaction callback to only sample transactions with child spans. * To avoid side effects of other callbacks this should be hooked as the last callback. */ -export const onlySampleIfChildSpans: BeforeFinishCallback = ( - transaction: IdleTransaction, -): void => { - const spansCount = transaction.spanRecorder && transaction.spanRecorder.spans.filter( - (span) => span.spanId !== transaction.spanId - ).length; +export const onlySampleIfChildSpans: BeforeFinishCallback = (transaction: IdleTransaction): void => { + const spansCount = + transaction.spanRecorder && + transaction.spanRecorder.spans.filter(span => span.spanId !== transaction.spanId).length; if (!spansCount || spansCount <= 0) { logger.log(`Not sampling as ${transaction.op} transaction has no child spans.`); transaction.sampled = false; } -} +}; diff --git a/src/js/tracing/types.ts b/src/js/tracing/types.ts index 4c4d2b1ddb..16f9914eb5 100644 --- a/src/js/tracing/types.ts +++ b/src/js/tracing/types.ts @@ -31,6 +31,4 @@ export interface ReactNavigationTransactionContext extends TransactionContext { data: RouteChangeContextData; } -export type BeforeNavigate = ( - context: TransactionContext -) => TransactionContext; +export type BeforeNavigate = (context: TransactionContext) => TransactionContext; diff --git a/src/js/tracing/utils.ts b/src/js/tracing/utils.ts index 358529918c..7851d5521e 100644 --- a/src/js/tracing/utils.ts +++ b/src/js/tracing/utils.ts @@ -5,9 +5,7 @@ import { timestampInSeconds } from '@sentry/utils'; export const defaultTransactionSource: TransactionSource = 'component'; export const customTransactionSource: TransactionSource = 'custom'; -export const getBlankTransactionContext = ( - name: string -): TransactionContext => { +export const getBlankTransactionContext = (name: string): TransactionContext => { return { name: 'Route Change', op: 'navigation', @@ -35,11 +33,10 @@ const timeOriginMilliseconds = Date.now(); export function adjustTransactionDuration( maxDurationMs: number, transaction: IdleTransaction, - endTimestamp: number + endTimestamp: number, ): void { const diff = endTimestamp - transaction.startTimestamp; - const isOutdatedTransaction = - endTimestamp && (diff > maxDurationMs || diff < 0); + const isOutdatedTransaction = endTimestamp && (diff > maxDurationMs || diff < 0); if (isOutdatedTransaction) { transaction.setStatus('deadline_exceeded'); transaction.setTag('maxTransactionDurationExceeded', 'true'); @@ -58,7 +55,7 @@ export function getTimeOriginMilliseconds(): number { */ export function instrumentChildSpanFinish( transaction: Transaction, - callback: (span: Span, endTimestamp?: number) => void + callback: (span: Span, endTimestamp?: number) => void, ): void { if (transaction.spanRecorder) { // eslint-disable-next-line @typescript-eslint/unbound-method diff --git a/src/js/transports/TextEncoder.ts b/src/js/transports/TextEncoder.ts index a1c77d7f80..05206d44a6 100644 --- a/src/js/transports/TextEncoder.ts +++ b/src/js/transports/TextEncoder.ts @@ -11,4 +11,4 @@ export const makeUtf8TextEncoder = (): TextEncoderInternal => { encoding: 'utf-8', }; return textEncoder; -} +}; diff --git a/src/js/transports/native.ts b/src/js/transports/native.ts index 7b5daa3167..9ae0e95689 100644 --- a/src/js/transports/native.ts +++ b/src/js/transports/native.ts @@ -6,7 +6,7 @@ import { NATIVE } from '../wrapper'; export const DEFAULT_BUFFER_SIZE = 30; -export type BaseNativeTransport = BaseTransportOptions +export type BaseNativeTransport = BaseTransportOptions; export interface BaseNativeTransportOptions { bufferSize?: number; @@ -53,9 +53,11 @@ export function makeNativeTransport(options: BaseNativeTransportOptions = {}): N /** * Creates a Native Transport factory if the native transport is available. */ -export function makeNativeTransportFactory( - { enableNative }: { enableNative?: boolean }, -): typeof makeNativeTransport | null { +export function makeNativeTransportFactory({ + enableNative, +}: { + enableNative?: boolean; +}): typeof makeNativeTransport | null { if (enableNative && NATIVE.isNativeAvailable()) { return makeNativeTransport; } diff --git a/src/js/user.ts b/src/js/user.ts index 38dedd18a3..5380929ec3 100644 --- a/src/js/user.ts +++ b/src/js/user.ts @@ -1,4 +1,4 @@ import type { User } from '@sentry/types'; /** Requires all the keys defined on User interface to be present on an object */ -export type RequiredKeysUser = { [P in keyof Required]: User[P] | undefined; }; +export type RequiredKeysUser = { [P in keyof Required]: User[P] | undefined }; diff --git a/src/js/utils/envelope.ts b/src/js/utils/envelope.ts index ebacb23f05..a5b7386537 100644 --- a/src/js/utils/envelope.ts +++ b/src/js/utils/envelope.ts @@ -1,10 +1,4 @@ -import type { - DsnComponents, - EventEnvelope, - SdkMetadata, - UserFeedback, - UserFeedbackItem, -} from '@sentry/types'; +import type { DsnComponents, EventEnvelope, SdkMetadata, UserFeedback, UserFeedbackItem } from '@sentry/types'; import { createEnvelope, dsnToString } from '@sentry/utils'; export const header = 0; @@ -20,18 +14,21 @@ export function createUserFeedbackEnvelope( tunnel, dsn, }: { - metadata: SdkMetadata | undefined, - tunnel: string | undefined, - dsn: DsnComponents | undefined, + metadata: SdkMetadata | undefined; + tunnel: string | undefined; + dsn: DsnComponents | undefined; }, ): EventEnvelope { const headers: EventEnvelope[0] = { event_id: feedback.event_id, sent_at: new Date().toISOString(), - ...(metadata && metadata.sdk && { sdk: { - name: metadata.sdk.name, - version: metadata.sdk.version, - }}), + ...(metadata && + metadata.sdk && { + sdk: { + name: metadata.sdk.name, + version: metadata.sdk.version, + }, + }), ...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }), }; const item = createUserFeedbackEnvelopeItem(feedback); @@ -39,9 +36,7 @@ export function createUserFeedbackEnvelope( return createEnvelope(headers, [item]); } -function createUserFeedbackEnvelopeItem( - feedback: UserFeedback -): UserFeedbackItem { +function createUserFeedbackEnvelopeItem(feedback: UserFeedback): UserFeedbackItem { const feedbackHeaders: UserFeedbackItem[0] = { type: 'user_report', }; diff --git a/src/js/utils/outcome.ts b/src/js/utils/outcome.ts index 338beaeaa5..cd4279d46c 100644 --- a/src/js/utils/outcome.ts +++ b/src/js/utils/outcome.ts @@ -16,7 +16,7 @@ export function mergeOutcomes(...merge: Outcome[][]): Outcome[] { } }; - merge.forEach((outcomes) => outcomes.forEach(process)); + merge.forEach(outcomes => outcomes.forEach(process)); return [...map.values()]; } diff --git a/src/js/utils/safe.ts b/src/js/utils/safe.ts index bff53941c8..03dcc33c47 100644 --- a/src/js/utils/safe.ts +++ b/src/js/utils/safe.ts @@ -3,10 +3,8 @@ import { logger } from '@sentry/utils'; import type { ReactNativeOptions } from '../options'; type DangerTypesWithoutCallSignature = -// eslint-disable-next-line @typescript-eslint/ban-types - | Object - | null - | undefined; + // eslint-disable-next-line @typescript-eslint/ban-types + Object | null | undefined; /** * Returns callback factory wrapped with try/catch @@ -27,9 +25,7 @@ export function safeFactory - ): ReturnType => { + return (...args: Parameters): ReturnType => { try { return tracesSampler(...args); } catch (error) { logger.error('The tracesSampler callback threw an error', error); return 0; } - } + }; } else { return tracesSampler; } diff --git a/src/js/vendor/buffer/index.ts b/src/js/vendor/buffer/index.ts index fe10ac2611..86753dde74 100644 --- a/src/js/vendor/buffer/index.ts +++ b/src/js/vendor/buffer/index.ts @@ -1,3 +1 @@ -export { - utf8ToBytes, -} from './utf8ToBytes'; +export { utf8ToBytes } from './utf8ToBytes'; diff --git a/src/js/vendor/buffer/utf8ToBytes.ts b/src/js/vendor/buffer/utf8ToBytes.ts index 3909eeb6eb..e7d77bc530 100644 --- a/src/js/vendor/buffer/utf8ToBytes.ts +++ b/src/js/vendor/buffer/utf8ToBytes.ts @@ -9,81 +9,74 @@ * License: MIT (https://github.com/feross/buffer) */ export function utf8ToBytes(string: string, units?: number): number[] { - units = units || Infinity - let codePoint - const length = string.length - let leadSurrogate = null - const bytes: number[] = [] + units = units || Infinity; + let codePoint; + const length = string.length; + let leadSurrogate = null; + const bytes: number[] = []; for (let i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) + codePoint = string.charCodeAt(i); // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { + if (codePoint > 0xd7ff && codePoint < 0xe000) { // last char was a lead if (!leadSurrogate) { // no lead yet - if (codePoint > 0xDBFF) { + if (codePoint > 0xdbff) { // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + continue; } else if (i + 1 === length) { // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + continue; } // valid lead - leadSurrogate = codePoint + leadSurrogate = codePoint; - continue + continue; } // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue + if (codePoint < 0xdc00) { + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); + leadSurrogate = codePoint; + continue; } // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + codePoint = (((leadSurrogate - 0xd800) << 10) | (codePoint - 0xdc00)) + 0x10000; } else if (leadSurrogate) { // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + if ((units -= 3) > -1) bytes.push(0xef, 0xbf, 0xbd); } - leadSurrogate = null + leadSurrogate = null; // encode utf8 if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) + if ((units -= 1) < 0) break; + bytes.push(codePoint); } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) + if ((units -= 2) < 0) break; + bytes.push((codePoint >> 0x6) | 0xc0, (codePoint & 0x3f) | 0x80); } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) + if ((units -= 3) < 0) break; + bytes.push((codePoint >> 0xc) | 0xe0, ((codePoint >> 0x6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80); } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break + if ((units -= 4) < 0) break; bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) + (codePoint >> 0x12) | 0xf0, + ((codePoint >> 0xc) & 0x3f) | 0x80, + ((codePoint >> 0x6) & 0x3f) | 0x80, + (codePoint & 0x3f) | 0x80, + ); } else { - throw new Error('Invalid code point') + throw new Error('Invalid code point'); } } - return bytes + return bytes; } diff --git a/src/js/vendor/index.ts b/src/js/vendor/index.ts index becf74c146..80d5ec4054 100644 --- a/src/js/vendor/index.ts +++ b/src/js/vendor/index.ts @@ -1,4 +1 @@ - -export { - utf8ToBytes, -} from './buffer'; +export { utf8ToBytes } from './buffer'; diff --git a/src/js/wrapper.ts b/src/js/wrapper.ts index 59b2d1af83..f7d63003f4 100644 --- a/src/js/wrapper.ts +++ b/src/js/wrapper.ts @@ -23,7 +23,7 @@ import type { } from './NativeRNSentry'; import type { ReactNativeClientOptions } from './options'; import type { RequiredKeysUser } from './user'; -import { isTurboModuleEnabled } from './utils/environment' +import { isTurboModuleEnabled } from './utils/environment'; import { utf8ToBytes } from './vendor'; const RNSentry: Spec | undefined = isTurboModuleEnabled() @@ -48,9 +48,7 @@ interface SentryNativeWrapper { _processLevels(event: Event): Event; _processLevel(level: SeverityLevel): SeverityLevel; _serializeObject(data: { [key: string]: unknown }): { [key: string]: string }; - _isModuleLoaded( - module: Spec | undefined - ): module is Spec; + _isModuleLoaded(module: Spec | undefined): module is Spec; _getBreadcrumbs(event: Event): Breadcrumb[] | undefined; isNativeAvailable(): boolean; @@ -133,9 +131,8 @@ export const NATIVE: SentryNativeWrapper = { bytesContentType = 'text/plain'; bytesPayload = utf8ToBytes(itemPayload); } else if (itemPayload instanceof Uint8Array) { - bytesContentType = typeof itemHeader.content_type === 'string' - ? itemHeader.content_type - : 'application/octet-stream'; + bytesContentType = + typeof itemHeader.content_type === 'string' ? itemHeader.content_type : 'application/octet-stream'; bytesPayload = [...itemPayload]; } else { bytesContentType = 'application/json'; @@ -180,7 +177,7 @@ export const NATIVE: SentryNativeWrapper = { if (!options.autoInitializeNativeSdk) { if (options.enableNativeNagger) { logger.warn( - 'Note: Native Sentry SDK was not initialized automatically, you will need to initialize it manually. If you wish to disable the native SDK and get rid of this warning, pass enableNative: false' + 'Note: Native Sentry SDK was not initialized automatically, you will need to initialize it manually. If you wish to disable the native SDK and get rid of this warning, pass enableNative: false', ); } return false; @@ -188,7 +185,7 @@ export const NATIVE: SentryNativeWrapper = { if (!options.dsn) { logger.warn( - 'Warning: No DSN was provided. The Sentry SDK will be disabled. Native SDK will also not be initalized.' + 'Warning: No DSN was provided. The Sentry SDK will be disabled. Native SDK will also not be initalized.', ); return false; } @@ -199,12 +196,7 @@ export const NATIVE: SentryNativeWrapper = { // filter out all the options that would crash native. /* eslint-disable @typescript-eslint/unbound-method,@typescript-eslint/no-unused-vars */ - const { - beforeSend, - beforeBreadcrumb, - integrations, - ...filteredOptions - } = options; + const { beforeSend, beforeBreadcrumb, integrations, ...filteredOptions } = options; /* eslint-enable @typescript-eslint/unbound-method,@typescript-eslint/no-unused-vars */ const nativeIsReady = await RNSentry.initNativeSdk(filteredOptions); @@ -348,8 +340,7 @@ export const NATIVE: SentryNativeWrapper = { throw this._NativeClientError; } - const stringifiedValue = - typeof value === 'string' ? value : JSON.stringify(value); + const stringifiedValue = typeof value === 'string' ? value : JSON.stringify(value); RNSentry.setTag(key, stringifiedValue); }, @@ -369,8 +360,7 @@ export const NATIVE: SentryNativeWrapper = { } // we stringify the extra as native only takes in strings. - const stringifiedExtra = - typeof extra === 'string' ? extra : JSON.stringify(extra); + const stringifiedExtra = typeof extra === 'string' ? extra : JSON.stringify(extra); RNSentry.setExtra(key, stringifiedExtra); }, @@ -390,12 +380,8 @@ export const NATIVE: SentryNativeWrapper = { RNSentry.addBreadcrumb({ ...breadcrumb, // Process and convert deprecated levels - level: breadcrumb.level - ? this._processLevel(breadcrumb.level) - : undefined, - data: breadcrumb.data - ? normalize(breadcrumb.data) - : undefined, + level: breadcrumb.level ? this._processLevel(breadcrumb.level) : undefined, + data: breadcrumb.data ? normalize(breadcrumb.data) : undefined, }); }, @@ -426,10 +412,7 @@ export const NATIVE: SentryNativeWrapper = { throw this._NativeClientError; } - RNSentry.setContext( - key, - context !== null ? normalize(context) : null - ); + RNSentry.setContext(key, context !== null ? normalize(context) : null); }, /** @@ -538,15 +521,12 @@ export const NATIVE: SentryNativeWrapper = { * @param data key-value map. * @returns An object where all root-level values are strings. */ - _serializeObject(data: { - [key: string]: unknown; - }): { [key: string]: string } { + _serializeObject(data: { [key: string]: unknown }): { [key: string]: string } { const serialized: { [key: string]: string } = {}; - Object.keys(data).forEach((dataKey) => { + Object.keys(data).forEach(dataKey => { const value = data[dataKey]; - serialized[dataKey] = - typeof value === 'string' ? value : JSON.stringify(value); + serialized[dataKey] = typeof value === 'string' ? value : JSON.stringify(value); }); return serialized; @@ -562,11 +542,9 @@ export const NATIVE: SentryNativeWrapper = { const processed: Event = { ...event, level: event.level ? this._processLevel(event.level) : undefined, - breadcrumbs: event.breadcrumbs?.map((breadcrumb) => ({ + breadcrumbs: event.breadcrumbs?.map(breadcrumb => ({ ...breadcrumb, - level: breadcrumb.level - ? this._processLevel(breadcrumb.level) - : undefined, + level: breadcrumb.level ? this._processLevel(breadcrumb.level) : undefined, })), }; @@ -580,7 +558,7 @@ export const NATIVE: SentryNativeWrapper = { */ _processLevel(level: SeverityLevel): SeverityLevel { - if (level == 'log' as SeverityLevel) { + if (level == ('log' as SeverityLevel)) { return 'debug' as SeverityLevel; } return level; @@ -589,17 +567,13 @@ export const NATIVE: SentryNativeWrapper = { /** * Checks whether the RNSentry module is loaded. */ - _isModuleLoaded( - module: Spec | undefined - ): module is Spec { + _isModuleLoaded(module: Spec | undefined): module is Spec { return !!module; }, _DisabledNativeError: new SentryError('Native is disabled'), - _NativeClientError: new SentryError( - "Native Client is not available, can't start on native." - ), + _NativeClientError: new SentryError("Native Client is not available, can't start on native."), /** * Get breadcrumbs (removes breadcrumbs from handled exceptions on Android) @@ -615,9 +589,7 @@ export const NATIVE: SentryNativeWrapper = { let breadcrumbs: Breadcrumb[] | undefined = event.breadcrumbs; const hardCrashed = isHardCrash(event); - if (NATIVE.platform === 'android' - && event.breadcrumbs - && !hardCrashed) { + if (NATIVE.platform === 'android' && event.breadcrumbs && !hardCrashed) { breadcrumbs = []; } diff --git a/test/client.test.ts b/test/client.test.ts index a823722b4e..4d5580ce2d 100644 --- a/test/client.test.ts +++ b/test/client.test.ts @@ -21,8 +21,7 @@ import { getSyncPromiseRejectOnFirstCall, } from './testutils'; -const EXAMPLE_DSN = - 'https://6890c2f6677340daa4804f8194804ea2@o19635.ingest.sentry.io/148053'; +const EXAMPLE_DSN = 'https://6890c2f6677340daa4804f8194804ea2@o19635.ingest.sentry.io/148053'; interface MockedReactNative { NativeModules: { @@ -76,7 +75,7 @@ jest.mock( }, }), /* virtual allows us to mock modules that aren't in package.json */ - { virtual: true } + { virtual: true }, ); const DEFAULT_OPTIONS: ReactNativeClientOptions = { @@ -106,7 +105,7 @@ describe('Tests ReactNativeClient', () => { const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: EXAMPLE_DSN, - transport: () => new NativeTransport() + transport: () => new NativeTransport(), }); await expect(client.eventFromMessage('test')).resolves.toBeDefined(); @@ -120,7 +119,7 @@ describe('Tests ReactNativeClient', () => { new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: 'not a dsn', - transport: () => new NativeTransport() + transport: () => new NativeTransport(), }); } catch (e: any) { expect(e.message).toBe('Invalid Sentry Dsn: not a dsn'); @@ -132,7 +131,7 @@ describe('Tests ReactNativeClient', () => { const backend = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: undefined, - transport: () => new NativeTransport() + transport: () => new NativeTransport(), }); return expect(backend.eventFromMessage('test')).resolves.toBeDefined(); @@ -144,12 +143,12 @@ describe('Tests ReactNativeClient', () => { const myFlush = (timeout?: number) => Promise.resolve(Boolean(timeout)); const myCustomTransportFn = (): Transport => ({ send: mySend, - flush: myFlush + flush: myFlush, }); const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: EXAMPLE_DSN, - transport: myCustomTransportFn + transport: myCustomTransportFn, }); // eslint-disable-next-line @typescript-eslint/unbound-method expect(client.getTransport()?.flush).toBe(myFlush); @@ -159,49 +158,55 @@ describe('Tests ReactNativeClient', () => { }); describe('onReady', () => { - test('calls onReady callback with true if Native SDK is initialized', (done) => { - new ReactNativeClient(mockedOptions({ - dsn: EXAMPLE_DSN, - enableNative: true, - onReady: ({ didCallNativeInit }) => { - expect(didCallNativeInit).toBe(true); - - done(); - }, - transport: () => new NativeTransport() - })); + test('calls onReady callback with true if Native SDK is initialized', done => { + new ReactNativeClient( + mockedOptions({ + dsn: EXAMPLE_DSN, + enableNative: true, + onReady: ({ didCallNativeInit }) => { + expect(didCallNativeInit).toBe(true); + + done(); + }, + transport: () => new NativeTransport(), + }), + ); }); - test('calls onReady callback with false if Native SDK was not initialized', (done) => { - new ReactNativeClient(mockedOptions({ - dsn: EXAMPLE_DSN, - enableNative: false, - onReady: ({ didCallNativeInit }) => { - expect(didCallNativeInit).toBe(false); - - done(); - }, - transport: () => new NativeTransport() - })); + test('calls onReady callback with false if Native SDK was not initialized', done => { + new ReactNativeClient( + mockedOptions({ + dsn: EXAMPLE_DSN, + enableNative: false, + onReady: ({ didCallNativeInit }) => { + expect(didCallNativeInit).toBe(false); + + done(); + }, + transport: () => new NativeTransport(), + }), + ); }); - test('calls onReady callback with false if Native SDK failed to initialize', (done) => { + test('calls onReady callback with false if Native SDK failed to initialize', done => { const RN: MockedReactNative = require('react-native'); RN.NativeModules.RNSentry.initNativeSdk = jest.fn(() => { throw new Error(); }); - new ReactNativeClient(mockedOptions({ - dsn: EXAMPLE_DSN, - enableNative: true, - onReady: ({ didCallNativeInit }) => { - expect(didCallNativeInit).toBe(false); + new ReactNativeClient( + mockedOptions({ + dsn: EXAMPLE_DSN, + enableNative: true, + onReady: ({ didCallNativeInit }) => { + expect(didCallNativeInit).toBe(false); - done(); - }, - transport: () => new NativeTransport() - })); + done(); + }, + transport: () => new NativeTransport(), + }), + ); }); }); @@ -212,8 +217,7 @@ describe('Tests ReactNativeClient', () => { const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, enableNative: true, - transport: () => new NativeTransport() - + transport: () => new NativeTransport(), }); client.nativeCrash(); @@ -242,7 +246,7 @@ describe('Tests ReactNativeClient', () => { expect(mockTransportSend.mock.calls[0][firstArg][envelopeHeader].event_id).toEqual('testEvent123'); expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][0][envelopeItemHeader].type).toEqual( - 'user_report' + 'user_report', ); expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][0][envelopeItemPayload]).toEqual({ comments: 'Test Comments', @@ -307,8 +311,7 @@ describe('Tests ReactNativeClient', () => { }); const expectedSdkInfo = { name: SDK_NAME, version: SDK_VERSION }; - const getSdkInfoFrom = (func: jest.Mock) => - func.mock.calls[0][firstArg][envelopeHeader].sdk; + const getSdkInfoFrom = (func: jest.Mock) => func.mock.calls[0][firstArg][envelopeHeader].sdk; test('send SdkInfo in the message envelope header', () => { client.captureMessage('message_test_value'); @@ -352,7 +355,9 @@ describe('Tests ReactNativeClient', () => { client.captureEvent({ message: 'test event' }); expect(mockedSend).toBeCalled(); - const actualEvent: Event | undefined = mockedSend.mock.calls[0][firstArg][envelopeItems][0][envelopeItemPayload]; + const actualEvent: Event | undefined = ( + mockedSend.mock.calls[0][firstArg][envelopeItems][0][envelopeItemPayload] + ); expect(actualEvent?.sdk?.packages).toEqual([ { name: SDK_PACKAGE_NAME, @@ -384,7 +389,9 @@ describe('Tests ReactNativeClient', () => { client.captureEvent(circularEvent); expect(mockedSend).toBeCalled(); - const actualEvent: Event | undefined = mockedSend.mock.calls[0][firstArg][envelopeItems][0][envelopeItemPayload]; + const actualEvent: Event | undefined = ( + mockedSend.mock.calls[0][firstArg][envelopeItems][0][envelopeItemPayload] + ); expect(actualEvent?.extra).toEqual({ circular: { extra: '[Circular ~]', @@ -430,9 +437,9 @@ describe('Tests ReactNativeClient', () => { client.captureMessage('message_test_value'); expect(mockTransportSend).toBeCalledTimes(1); - expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][1][envelopeItemHeader]).toEqual( - { type: 'client_report' } - ); + expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][1][envelopeItemHeader]).toEqual({ + type: 'client_report', + }); expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][1][envelopeItemPayload]).toEqual( expect.objectContaining({ discarded_events: [ @@ -440,7 +447,7 @@ describe('Tests ReactNativeClient', () => { reason: 'before_send', category: 'error', quantity: 1, - } + }, ], }), ); @@ -465,8 +472,7 @@ describe('Tests ReactNativeClient', () => { }); test('keeps outcomes in case envelope fails to send', () => { - const mockTransportSend = jest.fn((_envelope: Envelope) => - rejectedSyncPromise(new SentryError('Test'))); + const mockTransportSend = jest.fn((_envelope: Envelope) => rejectedSyncPromise(new SentryError('Test'))); const client = new ReactNativeClient({ ...DEFAULT_OPTIONS, dsn: EXAMPLE_DSN, @@ -505,9 +511,9 @@ describe('Tests ReactNativeClient', () => { expect(mockTransportSend).toBeCalledTimes(2); expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems].length).toEqual(2); - expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][1][envelopeItemHeader]).toEqual( - { type: 'client_report' } - ); + expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][1][envelopeItemHeader]).toEqual({ + type: 'client_report', + }); expect(mockTransportSend.mock.calls[0][firstArg][envelopeItems][1][envelopeItemPayload]).toEqual( expect.objectContaining({ discarded_events: [ @@ -530,9 +536,7 @@ describe('Tests ReactNativeClient', () => { ); } - function mockDroppedEvent( - client: ReactNativeClient, - ) { + function mockDroppedEvent(client: ReactNativeClient) { client.recordDroppedEvent('before_send', 'error'); } }); @@ -543,15 +547,17 @@ describe('Tests ReactNativeClient', () => { registerRoutingInstrumentation: jest.fn(), onRouteWillChange: jest.fn(), name: 'MockRoutingInstrumentation', - } - const client = new ReactNativeClient(mockedOptions({ - dsn: EXAMPLE_DSN, - integrations: [ - new ReactNativeTracing({ - routingInstrumentation: mockRoutingInstrumentation, - }), - ], - })); + }; + const client = new ReactNativeClient( + mockedOptions({ + dsn: EXAMPLE_DSN, + integrations: [ + new ReactNativeTracing({ + routingInstrumentation: mockRoutingInstrumentation, + }), + ], + }), + ); client.setupIntegrations(); expect(client.getIntegrationById('MockRoutingInstrumentation')).toBeTruthy(); diff --git a/test/e2e/src/dsn.ts b/test/e2e/src/dsn.ts index 1da1872d6a..76bf197765 100644 --- a/test/e2e/src/dsn.ts +++ b/test/e2e/src/dsn.ts @@ -1,2 +1 @@ -export const SENTRY_INTERNAL_DSN = - 'https://d870ad989e7046a8b9715a57f59b23b5@o447951.ingest.sentry.io/5428561'; +export const SENTRY_INTERNAL_DSN = 'https://d870ad989e7046a8b9715a57f59b23b5@o447951.ingest.sentry.io/5428561'; diff --git a/test/e2e/src/index.ts b/test/e2e/src/index.ts index b8d537d9eb..9a29ebaaa5 100644 --- a/test/e2e/src/index.ts +++ b/test/e2e/src/index.ts @@ -1,6 +1,3 @@ - import EndToEndTestsScreen from './EndToEndTests'; -export { - EndToEndTestsScreen, -}; +export { EndToEndTestsScreen }; diff --git a/test/e2e/src/utils/getTestProps.ts b/test/e2e/src/utils/getTestProps.ts index f2028a3839..838848e652 100644 --- a/test/e2e/src/utils/getTestProps.ts +++ b/test/e2e/src/utils/getTestProps.ts @@ -1,4 +1,4 @@ -import {Platform} from 'react-native'; +import { Platform } from 'react-native'; /** * Each platform uses different test ids There is a bug in Appium where accessibilityLabel does not work on iOS so we need testID, @@ -6,7 +6,9 @@ import {Platform} from 'react-native'; * @param id * @param platform */ -const getTestProps = (id: string): { +const getTestProps = ( + id: string, +): { accessibilityLabel?: string; accessible?: boolean; testID?: string; @@ -20,4 +22,4 @@ const getTestProps = (id: string): { testID: id, }; -export {getTestProps}; +export { getTestProps }; diff --git a/test/e2e/test/e2e.test.ts b/test/e2e/test/e2e.test.ts index 610d6cd94f..97b1e5657b 100644 --- a/test/e2e/test/e2e.test.ts +++ b/test/e2e/test/e2e.test.ts @@ -13,7 +13,7 @@ jest.setTimeout(T_20_MINUTES_IN_MS); let driver: WebdriverIO.Browser | null = null; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); +const sleep = (ms: number) => new Promise(r => setTimeout(r, ms)); async function getElement(accessibilityId: string): Promise { if (!driver) { @@ -49,8 +49,7 @@ beforeAll(async () => { if (process.env.APPIUM_APP === undefined) { throw new Error('APPIUM_APP environment variable must be set'); } - if (process.env.PLATFORM === 'ios' && - process.env.APPIUM_DERIVED_DATA === undefined) { + if (process.env.PLATFORM === 'ios' && process.env.APPIUM_DERIVED_DATA === undefined) { throw new Error('APPIUM_DERIVED_DATA environment variable must be set'); } @@ -66,7 +65,7 @@ beforeAll(async () => { 'appium:automationName': 'XCUITest', 'appium:app': process.env.APPIUM_APP, // DerivedData of the WebDriverRunner Xcode project. - 'appium:derivedDataPath': path.resolve((process.env.APPIUM_DERIVED_DATA || '')), + 'appium:derivedDataPath': path.resolve(process.env.APPIUM_DERIVED_DATA || ''), 'appium:showXcodeLog': true, 'appium:usePrebuiltWDA': true, }; diff --git a/test/e2e/test/utils/fetchEvent.ts b/test/e2e/test/utils/fetchEvent.ts index 0efe0f47ac..7bc17072eb 100644 --- a/test/e2e/test/utils/fetchEvent.ts +++ b/test/e2e/test/utils/fetchEvent.ts @@ -1,4 +1,4 @@ -import type {Event} from '@sentry/types'; +import type { Event } from '@sentry/types'; import fetch from 'node-fetch'; const domain = 'sentry.io'; @@ -39,7 +39,7 @@ const fetchEvent = async (eventId: string): Promise => { console.log(`Retrying api request. Retry number: ${retries}`); resolve( fetch(request) - .then((res) => res.json()) + .then(res => res.json()) .then(retryer), ); }, RETRY_INTERVAL); @@ -53,10 +53,10 @@ const fetchEvent = async (eventId: string): Promise => { const json: ApiEvent = await fetch(request) // tslint:disable-next-line: no-unsafe-any - .then((res) => res.json()) + .then(res => res.json()) .then(retryer); return json; }; -export {fetchEvent}; +export { fetchEvent }; diff --git a/test/e2e/test/utils/waitFor.ts b/test/e2e/test/utils/waitFor.ts index 06bcf39065..47ea127a76 100644 --- a/test/e2e/test/utils/waitFor.ts +++ b/test/e2e/test/utils/waitFor.ts @@ -24,11 +24,7 @@ export async function waitForTruthyResult(value: () => Promise): Promise { clearInterval(interval); - reject( - new Error( - `waitForTruthyResult function timed out after ${FINAL_TIMEOUT_MS} ms`, - ), - ); + reject(new Error(`waitForTruthyResult function timed out after ${FINAL_TIMEOUT_MS} ms`)); }, FINAL_TIMEOUT_MS); }); diff --git a/test/integrations/devicecontext.test.ts b/test/integrations/devicecontext.test.ts index b4898f3aba..a217e0d63c 100644 --- a/test/integrations/devicecontext.test.ts +++ b/test/integrations/devicecontext.test.ts @@ -17,25 +17,30 @@ jest.mock('react-native', () => ({ describe('Device Context Integration', () => { let integration: DeviceContext; - const mockGetCurrentHub = () => ({ - getIntegration: () => integration, - } as unknown as Hub); + const mockGetCurrentHub = () => + ({ + getIntegration: () => integration, + } as unknown as Hub); beforeEach(() => { integration = new DeviceContext(); }); it('add native user', async () => { - (await executeIntegrationWith({ - nativeContexts: { user: { id: 'native-user' } }, - })).expectEvent.toStrictEqualToNativeContexts(); + ( + await executeIntegrationWith({ + nativeContexts: { user: { id: 'native-user' } }, + }) + ).expectEvent.toStrictEqualToNativeContexts(); }); it('do not overwrite event user', async () => { - (await executeIntegrationWith({ - nativeContexts: { user: { id: 'native-user' } }, - mockEvent: { user: { id: 'event-user' } }, - })).expectEvent.toStrictEqualMockEvent(); + ( + await executeIntegrationWith({ + nativeContexts: { user: { id: 'native-user' } }, + mockEvent: { user: { id: 'event-user' } }, + }) + ).expectEvent.toStrictEqualMockEvent(); }); it('merge event and native contexts', async () => { @@ -91,29 +96,37 @@ describe('Device Context Integration', () => { }); it('add native level', async () => { - (await executeIntegrationWith({ - nativeContexts: { level: 'fatal' }, - })).expectEvent.toStrictEqualToNativeContexts(); + ( + await executeIntegrationWith({ + nativeContexts: { level: 'fatal' }, + }) + ).expectEvent.toStrictEqualToNativeContexts(); }); it('do not overwrite event level', async () => { - (await executeIntegrationWith({ - nativeContexts: { level: 'native-level' }, - mockEvent: { level: 'info' }, - })).expectEvent.toStrictEqualMockEvent(); + ( + await executeIntegrationWith({ + nativeContexts: { level: 'native-level' }, + mockEvent: { level: 'info' }, + }) + ).expectEvent.toStrictEqualMockEvent(); }); it('add native environment', async () => { - (await executeIntegrationWith({ - nativeContexts: { environment: 'native-environment' }, - })).expectEvent.toStrictEqualToNativeContexts(); + ( + await executeIntegrationWith({ + nativeContexts: { environment: 'native-environment' }, + }) + ).expectEvent.toStrictEqualToNativeContexts(); }); it('do not overwrite event environment', async () => { - (await executeIntegrationWith({ - nativeContexts: { environment: 'native-environment' }, - mockEvent: { environment: 'event-environment' }, - })).expectEvent.toStrictEqualMockEvent(); + ( + await executeIntegrationWith({ + nativeContexts: { environment: 'native-environment' }, + mockEvent: { environment: 'event-environment' }, + }) + ).expectEvent.toStrictEqualMockEvent(); }); it('use only native breadcrumbs', async () => { @@ -122,10 +135,7 @@ describe('Device Context Integration', () => { mockEvent: { breadcrumbs: [{ message: 'duplicate-breadcrumb' }, { message: 'event-breadcrumb' }] }, }); expect(processedEvent).toStrictEqual({ - breadcrumbs: [ - { message: 'duplicate-breadcrumb' }, - { message: 'native-breadcrumb' }, - ], + breadcrumbs: [{ message: 'duplicate-breadcrumb' }, { message: 'native-breadcrumb' }], }); }); @@ -173,7 +183,10 @@ describe('Device Context Integration', () => { }); }); - async function executeIntegrationWith({ nativeContexts, mockEvent }: { + async function executeIntegrationWith({ + nativeContexts, + mockEvent, + }: { nativeContexts: Record; mockEvent?: Event; }): Promise<{ @@ -183,10 +196,9 @@ describe('Device Context Integration', () => { toStrictEqualMockEvent: () => void; }; }> { - (NATIVE.fetchNativeDeviceContexts as jest.MockedFunction) - .mockImplementation( - () => Promise.resolve(nativeContexts as NativeDeviceContextsResponse), - ); + ( + NATIVE.fetchNativeDeviceContexts as jest.MockedFunction + ).mockImplementation(() => Promise.resolve(nativeContexts as NativeDeviceContextsResponse)); const originalNativeContexts = { ...nativeContexts }; const originalMockEvent = { ...mockEvent }; const processedEvent = await executeIntegrationFor(mockEvent ?? {}); @@ -201,17 +213,14 @@ describe('Device Context Integration', () => { function executeIntegrationFor(mockedEvent: Event): Promise { return new Promise((resolve, reject) => { - integration.setupOnce( - async (eventProcessor) => { - try { - const processedEvent = await eventProcessor(mockedEvent, {}); - resolve(processedEvent); - } catch (e) { - reject(e); - } - }, - mockGetCurrentHub, - ); + integration.setupOnce(async eventProcessor => { + try { + const processedEvent = await eventProcessor(mockedEvent, {}); + resolve(processedEvent); + } catch (e) { + reject(e); + } + }, mockGetCurrentHub); }); } }); diff --git a/test/integrations/eventorigin.test.ts b/test/integrations/eventorigin.test.ts index 3b67754ee8..faae0f56e6 100644 --- a/test/integrations/eventorigin.test.ts +++ b/test/integrations/eventorigin.test.ts @@ -3,12 +3,12 @@ import type { Event } from '@sentry/types'; import { EventOrigin } from '../../src/js/integrations'; describe('Event Origin', () => { - it('Adds event.origin and event.environment javascript tags to events', (done) => { + it('Adds event.origin and event.environment javascript tags to events', done => { const integration = new EventOrigin(); const mockEvent: Event = {}; - integration.setupOnce(async (eventProcessor) => { + integration.setupOnce(async eventProcessor => { try { const processedEvent = await eventProcessor(mockEvent, {}); diff --git a/test/integrations/modulesloader.test.ts b/test/integrations/modulesloader.test.ts index 53873596cb..f4315b8ad1 100644 --- a/test/integrations/modulesloader.test.ts +++ b/test/integrations/modulesloader.test.ts @@ -13,7 +13,9 @@ describe('Modules Loader', () => { }); it('integration event processor does not throw on native error', async () => { - (NATIVE.fetchModules as jest.Mock).mockImplementation(() => { throw new Error('Test Error') }); + (NATIVE.fetchModules as jest.Mock).mockImplementation(() => { + throw new Error('Test Error'); + }); const mockEvent: Event = { modules: { eventModule: 'eventModuleVersion', @@ -33,7 +35,7 @@ describe('Modules Loader', () => { modules: { eventModule: 'eventModuleVersion', duplicateModule: 'duplicateEventModuleVersion', - } + }, }; const processedEvent = await executeIntegrationFor(mockEvent); @@ -46,7 +48,7 @@ describe('Modules Loader', () => { function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint = {}): Promise { return new Promise((resolve, reject) => { - integration.setupOnce(async (eventProcessor) => { + integration.setupOnce(async eventProcessor => { try { const processedEvent = await eventProcessor(mockedEvent, mockedHint); resolve(processedEvent); diff --git a/test/integrations/reactnativeerrorhandlers.test.ts b/test/integrations/reactnativeerrorhandlers.test.ts index c81fe6912b..7f6012a52a 100644 --- a/test/integrations/reactnativeerrorhandlers.test.ts +++ b/test/integrations/reactnativeerrorhandlers.test.ts @@ -6,7 +6,6 @@ const mockBrowserClient: BrowserClient = new BrowserClient({ transport: jest.fn(), }); - jest.mock('@sentry/core', () => { const core = jest.requireActual('@sentry/core'); @@ -16,7 +15,8 @@ jest.mock('@sentry/core', () => { const client = { getOptions: () => ({}), - eventFromException: (_exception: any, _hint?: EventHint): PromiseLike => mockBrowserClient.eventFromException(_exception, _hint) + eventFromException: (_exception: any, _hint?: EventHint): PromiseLike => + mockBrowserClient.eventFromException(_exception, _hint), }; const hub = { @@ -64,7 +64,7 @@ describe('ReactNativeErrorHandlers', () => { beforeEach(() => { errorHandlerCallback = () => Promise.resolve(); - ErrorUtils.setGlobalHandler = jest.fn((_callback) => { + ErrorUtils.setGlobalHandler = jest.fn(_callback => { errorHandlerCallback = _callback as typeof errorHandlerCallback; }); @@ -108,9 +108,7 @@ describe('ReactNativeErrorHandlers', () => { function getActualCaptureEventArgs() { const hub = getCurrentHub(); // eslint-disable-next-line @typescript-eslint/unbound-method - const mockCall = (hub.captureEvent as jest.MockedFunction< - typeof hub.captureEvent - >).mock.calls[0]; + const mockCall = (hub.captureEvent as jest.MockedFunction).mock.calls[0]; return mockCall; } diff --git a/test/integrations/reactnativeinfo.test.ts b/test/integrations/reactnativeinfo.test.ts index 5749a72e1f..67bed82339 100644 --- a/test/integrations/reactnativeinfo.test.ts +++ b/test/integrations/reactnativeinfo.test.ts @@ -1,7 +1,7 @@ import type { Event, EventHint } from '@sentry/types'; import type { ReactNativeError } from '../../src/js/integrations/debugsymbolicator'; -import type { ReactNativeContext} from '../../src/js/integrations/reactnativeinfo'; +import type { ReactNativeContext } from '../../src/js/integrations/reactnativeinfo'; import { ReactNativeInfo } from '../../src/js/integrations/reactnativeinfo'; let mockedIsHermesEnabled: jest.Mock; @@ -27,7 +27,7 @@ describe('React Native Info', () => { it('does not pollute event with undefined fields', async () => { const mockEvent: Event = { - message: 'test' + message: 'test', }; const mockedHint: EventHint = {}; const actualEvent = await executeIntegrationFor(mockEvent, mockedHint); @@ -50,9 +50,9 @@ describe('React Native Info', () => { expectMocksToBeCalledOnce(); expect(actualEvent?.tags?.hermes).toEqual('true'); - expect( - (actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.js_engine, - ).toEqual('hermes'); + expect((actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.js_engine).toEqual( + 'hermes', + ); }); it('does not override existing hermes tag', async () => { @@ -78,9 +78,9 @@ describe('React Native Info', () => { expectMocksToBeCalledOnce(); expect(actualEvent?.tags?.hermes).toEqual(undefined); - expect( - (actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.js_engine, - ).toEqual('test_engine'); + expect((actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.js_engine).toEqual( + 'test_engine', + ); }); it('adds component stack', async () => { @@ -92,9 +92,9 @@ describe('React Native Info', () => { const actualEvent = await executeIntegrationFor({}, mockedHint); expectMocksToBeCalledOnce(); - expect( - (actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.component_stack, - ).toEqual('test_stack'); + expect((actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.component_stack).toEqual( + 'test_stack', + ); }); it('marks turbo modules enabled', async () => { @@ -102,9 +102,7 @@ describe('React Native Info', () => { const actualEvent = await executeIntegrationFor({}, {}); expectMocksToBeCalledOnce(); - expect( - (actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.turbo_module, - ).toEqual(true); + expect((actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.turbo_module).toEqual(true); }); it('marks fabric enabled', async () => { @@ -112,9 +110,7 @@ describe('React Native Info', () => { const actualEvent = await executeIntegrationFor({}, {}); expectMocksToBeCalledOnce(); - expect( - (actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.fabric, - ).toEqual(true); + expect((actualEvent?.contexts?.react_native_context as ReactNativeContext | undefined)?.fabric).toEqual(true); }); it('does not override existing react_native_context', async () => { @@ -143,7 +139,7 @@ function expectMocksToBeCalledOnce() { function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint): Promise { const integration = new ReactNativeInfo(); return new Promise((resolve, reject) => { - integration.setupOnce(async (eventProcessor) => { + integration.setupOnce(async eventProcessor => { try { const processedEvent = await eventProcessor(mockedEvent, mockedHint); resolve(processedEvent); diff --git a/test/integrations/release.test.ts b/test/integrations/release.test.ts index ee020fcb99..56db341fd6 100644 --- a/test/integrations/release.test.ts +++ b/test/integrations/release.test.ts @@ -39,7 +39,7 @@ describe('Tests the Release integration', () => { let eventProcessor: EventProcessor = () => null; // @ts-ignore Mock - addGlobalEventProcessor.mockImplementation((e) => (eventProcessor = e)); + addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); releaseIntegration.setupOnce(); expect(addGlobalEventProcessor).toBeCalled(); @@ -61,7 +61,7 @@ describe('Tests the Release integration', () => { let eventProcessor: EventProcessor = () => null; // @ts-ignore Mock - addGlobalEventProcessor.mockImplementation((e) => (eventProcessor = e)); + addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); releaseIntegration.setupOnce(); const client = getCurrentHub().getClient(); @@ -83,7 +83,7 @@ describe('Tests the Release integration', () => { let eventProcessor: EventProcessor = () => null; // @ts-ignore Mock - addGlobalEventProcessor.mockImplementation((e) => (eventProcessor = e)); + addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); releaseIntegration.setupOnce(); const client = getCurrentHub().getClient(); @@ -105,7 +105,7 @@ describe('Tests the Release integration', () => { let eventProcessor: EventProcessor = () => null; // @ts-ignore Mock - addGlobalEventProcessor.mockImplementation((e) => (eventProcessor = e)); + addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); releaseIntegration.setupOnce(); expect(addGlobalEventProcessor).toBeCalled(); @@ -130,7 +130,7 @@ describe('Tests the Release integration', () => { let eventProcessor: EventProcessor = () => null; // @ts-ignore Mock - addGlobalEventProcessor.mockImplementation((e) => (eventProcessor = e)); + addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); releaseIntegration.setupOnce(); expect(addGlobalEventProcessor).toBeCalled(); @@ -143,12 +143,15 @@ describe('Tests the Release integration', () => { release: 'options_release', })); - const event = await eventProcessor({ - extra: { - __sentry_dist: 'sentry_dist', - __sentry_release: 'sentry_release', + const event = await eventProcessor( + { + extra: { + __sentry_dist: 'sentry_dist', + __sentry_release: 'sentry_release', + }, }, - }, {}); + {}, + ); expect(event?.release).toBe('sentry_release'); expect(event?.dist).toBe('sentry_dist'); diff --git a/test/integrations/rewriteframes.test.ts b/test/integrations/rewriteframes.test.ts index 46fe540b9c..4224fed08e 100644 --- a/test/integrations/rewriteframes.test.ts +++ b/test/integrations/rewriteframes.test.ts @@ -3,19 +3,22 @@ import { defaultStackParser, eventFromException } from '@sentry/browser'; import { createReactNativeRewriteFrames } from '../../src/js/integrations/rewriteframes'; - describe('RewriteFrames', () => { const HINT = {}; const ATTACH_STACKTRACE = true; - const exceptionFromError = async (options: { message: string, name: string, stack: string }): Promise => { + const exceptionFromError = async (options: { + message: string; + name: string; + stack: string; + }): Promise => { const error = new Error(options.message); error.stack = options.stack; const event = await eventFromException(defaultStackParser, error, HINT, ATTACH_STACKTRACE); createReactNativeRewriteFrames().process(event); const exception = event.exception?.values?.[0]; return exception; - } + }; it('should parse exceptions for react-native-v8', async () => { const REACT_NATIVE_V8_EXCEPTION = { @@ -118,32 +121,28 @@ describe('RewriteFrames', () => { frames: [ { filename: '[native code]', function: 'forEach', in_app: true }, { - filename: - 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', + filename: 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', function: 'p', lineno: 96, colno: 385, in_app: true, }, { - filename: - 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', + filename: 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', function: 'onResponderRelease', lineno: 221, colno: 5666, in_app: true, }, { - filename: - 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', + filename: 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', function: 'value', lineno: 221, colno: 7656, in_app: true, }, { - filename: - 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', + filename: 'app:///bundle-613EDD44F3305B9D75D4679663900F2BCDDDC326F247CA3202A3A4219FD412D3', function: 'onPress', lineno: 595, colno: 658, diff --git a/test/integrations/sdkinfo.test.ts b/test/integrations/sdkinfo.test.ts index a89256ccc0..2eff68529e 100644 --- a/test/integrations/sdkinfo.test.ts +++ b/test/integrations/sdkinfo.test.ts @@ -62,7 +62,7 @@ describe('Sdk Info', () => { function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint = {}): Promise { const integration = new SdkInfo(); return new Promise((resolve, reject) => { - integration.setupOnce(async (eventProcessor) => { + integration.setupOnce(async eventProcessor => { try { const processedEvent = await eventProcessor(mockedEvent, mockedHint); resolve(processedEvent); diff --git a/test/integrations/viewhierarchy.test.ts b/test/integrations/viewhierarchy.test.ts index 9390b0bf87..d136bd8403 100644 --- a/test/integrations/viewhierarchy.test.ts +++ b/test/integrations/viewhierarchy.test.ts @@ -23,16 +23,18 @@ describe('ViewHierarchy', () => { }); it('integration event processor does not throw on native error', async () => { - (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation(() => { throw new Error('Test Error') }); + (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation(() => { + throw new Error('Test Error'); + }); const mockHint: EventHint = {}; await executeIntegrationFor(mockEvent, mockHint); expect(mockHint).toEqual({}); }); it('returns unchanged event', async () => { - (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation( - (() => Promise.resolve(new Uint8Array([]))) - ); + (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation(( + (() => Promise.resolve(new Uint8Array([]))) + )); await executeIntegrationFor(mockEvent); expect(mockEvent).toEqual({ @@ -47,32 +49,36 @@ describe('ViewHierarchy', () => { }); it('adds view hierarchy attachment in event hint', async () => { - (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation( - (() => Promise.resolve((new Uint8Array([ 1, 2, 3 ])))) - ); + (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation(( + (() => Promise.resolve(new Uint8Array([1, 2, 3]))) + )); const mockHint: EventHint = {}; await executeIntegrationFor(mockEvent, mockHint); expect(mockHint).toEqual({ - attachments: [{ - filename: 'view-hierarchy.json', - contentType: 'application/json', - attachmentType: 'event.view_hierarchy', - data: new Uint8Array([ 1, 2, 3 ]), - }], + attachments: [ + { + filename: 'view-hierarchy.json', + contentType: 'application/json', + attachmentType: 'event.view_hierarchy', + data: new Uint8Array([1, 2, 3]), + }, + ], }); }); it('does not modify existing event hint attachments', async () => { - (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation( - (() => Promise.resolve((new Uint8Array([1, 2, 3])))) - ); + (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation(( + (() => Promise.resolve(new Uint8Array([1, 2, 3]))) + )); const mockHint: EventHint = { - attachments: [{ - filename: 'test-attachment.txt', - contentType: 'text/plain', - data: new Uint8Array([4, 5, 6]), - }], + attachments: [ + { + filename: 'test-attachment.txt', + contentType: 'text/plain', + data: new Uint8Array([4, 5, 6]), + }, + ], }; await executeIntegrationFor(mockEvent, mockHint); @@ -94,9 +100,9 @@ describe('ViewHierarchy', () => { }); it('does not create empty view hierarchy attachment in event hint', async () => { - (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation( - (() => Promise.resolve(null)) - ); + (NATIVE.fetchViewHierarchy as jest.Mock).mockImplementation(( + (() => Promise.resolve(null)) + )); const mockHint: EventHint = {}; await executeIntegrationFor(mockEvent, mockHint); @@ -105,7 +111,7 @@ describe('ViewHierarchy', () => { function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint = {}): Promise { return new Promise((resolve, reject) => { - integration.setupOnce(async (eventProcessor) => { + integration.setupOnce(async eventProcessor => { try { const processedEvent = await eventProcessor(mockedEvent, mockedHint); resolve(processedEvent); diff --git a/test/measurements.test.ts b/test/measurements.test.ts index 3c472fc584..76c46a4906 100644 --- a/test/measurements.test.ts +++ b/test/measurements.test.ts @@ -1,4 +1,4 @@ -import type { Carrier} from '@sentry/core'; +import type { Carrier } from '@sentry/core'; import { getCurrentHub, getMainCarrier } from '@sentry/core'; import type { Transaction } from '@sentry/tracing'; import type { Hub } from '@sentry/types'; @@ -48,11 +48,13 @@ describe('Tracing extensions', () => { const transaction: Transaction = startTransaction?.apply(hub, [{ op: 'custom' }]); const span = transaction?.startChild({ op: 'custom' }); - expect(span).toEqual(expect.objectContaining({ - transaction, - parentSpanId: transaction.spanId, - sampled: transaction.sampled, - traceId: transaction.traceId, - })); + expect(span).toEqual( + expect.objectContaining({ + transaction, + parentSpanId: transaction.spanId, + sampled: transaction.sampled, + traceId: transaction.traceId, + }), + ); }); }); diff --git a/test/misc.test.ts b/test/misc.test.ts index 337b44a7c0..a442c2b8fd 100644 --- a/test/misc.test.ts +++ b/test/misc.test.ts @@ -11,7 +11,7 @@ describe('misc', () => { exception: { values: [{}], }, - }) + }), ).toBe(false); }); test('handled true is not a hard crash', () => { @@ -27,7 +27,7 @@ describe('misc', () => { }, ], }, - }) + }), ).toBe(false); }); test('any handled false is a hard crash', () => { @@ -50,7 +50,7 @@ describe('misc', () => { }, ], }, - }) + }), ).toBe(true); }); }); diff --git a/test/scope.test.ts b/test/scope.test.ts index 7a6b060390..c9fd079253 100644 --- a/test/scope.test.ts +++ b/test/scope.test.ts @@ -8,18 +8,22 @@ jest.mock('../src/js/wrapper'); describe('Scope', () => { describe('addBreadcrumb', () => { it('addBreadcrumb without level', () => { - (NATIVE.addBreadcrumb as jest.Mock).mockImplementationOnce(() => { return; }); + (NATIVE.addBreadcrumb as jest.Mock).mockImplementationOnce(() => { + return; + }); const scope = new ReactNativeScope() as ReactNativeScope & { _breadcrumbs: Breadcrumb[] }; const breadcrumb = { message: 'test', timestamp: 1234, }; scope.addBreadcrumb(breadcrumb); - expect(scope._breadcrumbs).toEqual([{ - message: 'test', - timestamp: 1234, - level: 'info', - }]); + expect(scope._breadcrumbs).toEqual([ + { + message: 'test', + timestamp: 1234, + level: 'info', + }, + ]); }); }); }); diff --git a/test/sdk.test.ts b/test/sdk.test.ts index db13cf396a..089e178143 100644 --- a/test/sdk.test.ts +++ b/test/sdk.test.ts @@ -53,13 +53,13 @@ jest.mock('@sentry/hub', () => { jest.mock('../src/js/scope', () => { return { - ReactNativeScope: class ReactNativeScopeMock { }, + ReactNativeScope: class ReactNativeScopeMock {}, }; }); jest.mock('../src/js/client', () => { return { - ReactNativeClient: class ReactNativeClientMock { }, + ReactNativeClient: class ReactNativeClientMock {}, }; }); @@ -80,7 +80,7 @@ import { firstArg, secondArg } from './testutils'; const mockedInitAndBind = initAndBind as jest.MockedFunction; const usedOptions = (): ClientOptions | undefined => { return mockedInitAndBind.mock.calls[0]?.[1]; -} +}; afterEach(() => { jest.clearAllMocks(); @@ -98,18 +98,16 @@ describe('Tests the SDK functionality', () => { return options.integrations; } return []; - } + }; const autoPerformanceIsEnabled = (): boolean => { - return usedOptions().some( - (integration) => integration.name === ReactNativeTracing.id - ); + return usedOptions().some(integration => integration.name === ReactNativeTracing.id); }; const reactNavigationInstrumentation = (): ReactNativeTracing => { const nav = new ReactNavigationInstrumentation(); return new ReactNativeTracing({ routingInstrumentation: nav }); - } + }; it('Auto Performance is enabled when tracing is enabled (tracesSampler)', () => { init({ @@ -138,8 +136,8 @@ describe('Tests the SDK functionality', () => { }); const options = usedOptions(); - expect(options.filter((integration) => integration.name === ReactNativeTracing.id).length).toBe(1); - expect(options.some((integration) => integration === tracing)).toBe(true); + expect(options.filter(integration => integration.name === ReactNativeTracing.id).length).toBe(1); + expect(options.some(integration => integration === tracing)).toBe(true); }); it('Do not overwrite user defined integrations when passing defaultIntegrations', () => { @@ -151,8 +149,8 @@ describe('Tests the SDK functionality', () => { }); const options = usedOptions(); - expect(options.filter((integration) => integration.name === ReactNativeTracing.id).length).toBe(1); - expect(options.some((integration) => integration === tracing)).toBe(true); + expect(options.filter(integration => integration.name === ReactNativeTracing.id).length).toBe(1); + expect(options.some(integration => integration === tracing)).toBe(true); }); }); @@ -184,9 +182,7 @@ describe('Tests the SDK functionality', () => { expect(mockClient.flush).toBeCalled(); expect(flushResult).toBe(false); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(logger.error).toBeCalledWith( - 'Failed to flush the event queue.' - ); + expect(logger.error).toBeCalledWith('Failed to flush the event queue.'); } }); }); @@ -258,7 +254,9 @@ describe('Tests the SDK functionality', () => { describe('initIsSafe', () => { test('initialScope callback is safe after init', () => { - const mockInitialScope = jest.fn(() => { throw 'Test error' }); + const mockInitialScope = jest.fn(() => { + throw 'Test error'; + }); init({ initialScope: mockInitialScope }); @@ -268,7 +266,9 @@ describe('Tests the SDK functionality', () => { expect(mockInitialScope).toBeCalledTimes(1); }); test('beforeBreadcrumb callback is safe after init', () => { - const mockBeforeBreadcrumb = jest.fn(() => { throw 'Test error' }); + const mockBeforeBreadcrumb = jest.fn(() => { + throw 'Test error'; + }); init({ beforeBreadcrumb: mockBeforeBreadcrumb }); @@ -279,7 +279,9 @@ describe('Tests the SDK functionality', () => { }); test('integrations callback should not crash init', () => { - const mockIntegrations = jest.fn(() => { throw 'Test error' }); + const mockIntegrations = jest.fn(() => { + throw 'Test error'; + }); expect(() => { init({ integrations: mockIntegrations }); @@ -288,7 +290,9 @@ describe('Tests the SDK functionality', () => { }); test('tracesSampler callback is safe after init', () => { - const mockTraceSampler = jest.fn(() => { throw 'Test error' }); + const mockTraceSampler = jest.fn(() => { + throw 'Test error'; + }); init({ tracesSampler: mockTraceSampler }); @@ -301,7 +305,9 @@ describe('Tests the SDK functionality', () => { describe('withScope', () => { test('withScope callback does not throw', () => { - const mockScopeCallback = jest.fn(() => { throw 'Test error' }); + const mockScopeCallback = jest.fn(() => { + throw 'Test error'; + }); withScope(mockScopeCallback); @@ -314,7 +320,9 @@ describe('Tests the SDK functionality', () => { describe('configureScope', () => { test('configureScope callback does not throw', () => { - const mockScopeCallback = jest.fn(() => { throw 'Test error' }); + const mockScopeCallback = jest.fn(() => { + throw 'Test error'; + }); configureScope(mockScopeCallback); @@ -364,7 +372,7 @@ describe('Tests the SDK functionality', () => { integrations: [ { name: 'HttpClient', - setupOnce: () => { }, + setupOnce: () => {}, isUserDefined: true, }, ], @@ -373,10 +381,14 @@ describe('Tests the SDK functionality', () => { const actualOptions = mockedInitAndBind.mock.calls[0][secondArg] as ReactNativeClientOptions; const actualIntegrations = actualOptions.integrations; - expect(actualIntegrations).toEqual(expect.arrayContaining([expect.objectContaining({ - name: 'HttpClient', - isUserDefined: true, - })])); + expect(actualIntegrations).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: 'HttpClient', + isUserDefined: true, + }), + ]), + ); expect(actualIntegrations.filter(integration => integration.name === 'HttpClient')).toHaveLength(1); }); @@ -406,7 +418,9 @@ describe('Tests the SDK functionality', () => { const actualOptions = mockedInitAndBind.mock.calls[0][secondArg] as ReactNativeClientOptions; const actualIntegrations = actualOptions.integrations; - expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'ViewHierarchy' })])); + expect(actualIntegrations).toEqual( + expect.not.arrayContaining([expect.objectContaining({ name: 'ViewHierarchy' })]), + ); }); it('adds view hierarchy integration', () => { @@ -442,8 +456,7 @@ describe('Tests the SDK functionality', () => { const actualOptions = mockedInitAndBind.mock.calls[0][secondArg] as ReactNativeClientOptions; const actualIntegrations = actualOptions.integrations; - expect(actualIntegrations) - .toEqual(expect.arrayContaining([mockIntegration, mockDefaultIntegration])); // order doesn't matter + expect(actualIntegrations).toEqual(expect.arrayContaining([mockIntegration, mockDefaultIntegration])); // order doesn't matter expect(actualIntegrations.length).toBe(2); // there should be no extra unexpected integrations }); @@ -456,8 +469,7 @@ describe('Tests the SDK functionality', () => { const actualOptions = mockedInitAndBind.mock.calls[0][secondArg] as ReactNativeClientOptions; const actualIntegrations = actualOptions.integrations; - expect(actualIntegrations) - .toEqual(expect.arrayContaining([mockIntegration])); + expect(actualIntegrations).toEqual(expect.arrayContaining([mockIntegration])); expect(actualIntegrations.length).toBeGreaterThan(1); // there should be default integrations + the test one }); @@ -515,8 +527,9 @@ describe('Tests the SDK functionality', () => { const actualOptions = mockedInitAndBind.mock.calls[0][secondArg] as ReactNativeClientOptions; const actualIntegrations = actualOptions.integrations; - expect(actualIntegrations) - .toEqual(expect.arrayContaining([expect.objectContaining({ name: 'MockedDefaultReactIntegration' })])); + expect(actualIntegrations).toEqual( + expect.arrayContaining([expect.objectContaining({ name: 'MockedDefaultReactIntegration' })]), + ); }); }); }); diff --git a/test/testutils.ts b/test/testutils.ts index 05393c2fbd..2470d72d15 100644 --- a/test/testutils.ts +++ b/test/testutils.ts @@ -5,9 +5,7 @@ import { rejectedSyncPromise } from '@sentry/utils'; import { getBlankTransactionContext } from '../src/js/tracing/utils'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function mockFunction any>( - fn: T -): jest.MockedFunction { +export function mockFunction any>(fn: T): jest.MockedFunction { return fn as jest.MockedFunction; } diff --git a/test/tools/collectModules.test.ts b/test/tools/collectModules.test.ts index ce1a151bec..866465b2ac 100644 --- a/test/tools/collectModules.test.ts +++ b/test/tools/collectModules.test.ts @@ -3,7 +3,7 @@ import { existsSync, readFileSync, rmdirSync, unlinkSync } from 'fs'; import { dirname } from 'path'; jest.mock('@sentry/utils'); -(logger.enable as jest.Mock).mockImplementation(() => { }); +(logger.enable as jest.Mock).mockImplementation(() => {}); import ModulesCollector from '../../src/js/tools/ModulesCollector'; @@ -17,10 +17,7 @@ describe('collectModules', () => { `${__dirname}/fixtures/root-module/modules/module2/module2.js`, `${__dirname}/fixtures/root-module/modules/@organization/module3/module3.js`, ], - [ - `${__dirname}/fixtures/root-module/modules`, - `${__dirname}/fixtures`, - ], + [`${__dirname}/fixtures/root-module/modules`, `${__dirname}/fixtures`], ); expect(modules).toEqual({ @@ -39,24 +36,17 @@ describe('collectModules', () => { `${__dirname}/fixtures/root-module/modules/module1/modules/not-collected/lib/notCollected.js`, `${__dirname}/fixtures/root-module/modules/module2/module2.js`, ], - [ - `${__dirname}/fixtures/root-module/modules`, - ], + [`${__dirname}/fixtures/root-module/modules`], ); expect(modules).toEqual({ 'module-1': 'module-1-version', - 'module-2': 'unknown' + 'module-2': 'unknown', }); }); test('should skip non string source value', () => { - const modules = ModulesCollector.collect( - [1, {}], - [ - `${__dirname}/fixtures/root-module/modules`, - ], - ); + const modules = ModulesCollector.collect([1, {}], [`${__dirname}/fixtures/root-module/modules`]); expect(modules).toEqual({}); }); @@ -66,9 +56,7 @@ describe('collectModules', () => { ModulesCollector.run({ sourceMapPath: 'not-exist', outputModulesPath: `${__dirname}/fixtures/mock.json`, - modulesPaths: [ - `${__dirname}/fixtures/root-module/modules`, - ], + modulesPaths: [`${__dirname}/fixtures/root-module/modules`], collect: mockCollect, }); @@ -80,10 +68,7 @@ describe('collectModules', () => { ModulesCollector.run({ sourceMapPath: `${__dirname}/fixtures/mock.map`, outputModulesPath: `${__dirname}/fixtures/mock.json`, - modulesPaths: [ - `${__dirname}/fixtures/root-module/modules`, - 'not-exist', - ], + modulesPaths: [`${__dirname}/fixtures/root-module/modules`, 'not-exist'], collect: mockCollect, }); @@ -107,9 +92,7 @@ describe('collectModules', () => { ModulesCollector.run({ sourceMapPath: `${__dirname}/fixtures/mock.map`, outputModulesPath, - modulesPaths: [ - `${__dirname}/fixtures/root-module/modules`, - ], + modulesPaths: [`${__dirname}/fixtures/root-module/modules`], }); expect(existsSync(outputModulesPath)).toEqual(true); diff --git a/test/tracing/gesturetracing.test.ts b/test/tracing/gesturetracing.test.ts index bb74433dec..3e40681e49 100644 --- a/test/tracing/gesturetracing.test.ts +++ b/test/tracing/gesturetracing.test.ts @@ -11,12 +11,10 @@ import { sentryTraceGesture, } from '../../src/js/tracing/gesturetracing'; import { ReactNativeTracing } from '../../src/js/tracing/reactnativetracing'; -import type { - MockedRoutingInstrumentation -} from './mockedrountinginstrumention'; +import type { MockedRoutingInstrumentation } from './mockedrountinginstrumention'; import { createMockedRoutingInstrumentation, - mockedConfirmedRouteTransactionContext + mockedConfirmedRouteTransactionContext, } from './mockedrountinginstrumention'; jest.mock('../../src/js/wrapper', () => { @@ -46,7 +44,7 @@ const getMockScope = () => { // Placeholder }, getUser: () => scopeUser, - } + }; }; const mockAddBreadcrumb = jest.fn(); @@ -58,7 +56,7 @@ const getMockHub = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any mockHub.getScope = () => mockScope as any; // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockHub.configureScope = jest.fn((callback) => callback(mockScope as any)); + mockHub.configureScope = jest.fn(callback => callback(mockScope as any)); mockHub.addBreadcrumb = mockAddBreadcrumb; @@ -107,8 +105,8 @@ describe('GestureTracing', () => { }); tracing.setupOnce(jest.fn(), jest.fn().mockReturnValue(mockedHub)); // client.addIntegration uses global getCurrentHub, so we don't use it to keep the mockedHub - (mockedHub.getClient() as unknown as { _integrations: IntegrationIndex }) - ._integrations[ReactNativeTracing.name] = tracing; + (mockedHub.getClient() as unknown as { _integrations: IntegrationIndex })._integrations[ReactNativeTracing.name] = + tracing; mockedRoutingInstrumentation.registeredOnConfirmRoute!(mockedConfirmedRouteTransactionContext); mockedGesture = { handlers: { @@ -131,10 +129,12 @@ describe('GestureTracing', () => { jest.runAllTimers(); const transactionContext = transaction?.toContext(); - expect(transactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - op: `${UI_ACTION}.mock`, - })); + expect(transactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + op: `${UI_ACTION}.mock`, + }), + ); }); it('gesture interaction transaction falls back on invalid handler name', () => { @@ -145,10 +145,12 @@ describe('GestureTracing', () => { jest.runAllTimers(); const transactionContext = transaction?.toContext(); - expect(transactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - op: `${UI_ACTION}.gesture`, - })); + expect(transactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + op: `${UI_ACTION}.gesture`, + }), + ); }); it('gesture cancel previous interaction transaction', () => { @@ -170,14 +172,18 @@ describe('GestureTracing', () => { const touchTransactionContext = touchTransaction?.toContext(); const gestureTransactionContext = gestureTransaction?.toContext(); - expect(touchTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - op: 'mocked.op', - sampled: true, - })); - expect(gestureTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - })); + expect(touchTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + op: 'mocked.op', + sampled: true, + }), + ); + expect(gestureTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + }), + ); }); it('gesture original on begin handler is called', () => { @@ -231,11 +237,13 @@ describe('GestureTracing', () => { jest.runAllTimers(); expect(mockAddBreadcrumb).toHaveBeenCalledTimes(1); - expect(mockAddBreadcrumb).toHaveBeenCalledWith(expect.objectContaining({ - category: DEFAULT_GESTURE_BREADCRUMB_CATEGORY, - type: DEFAULT_GESTURE_BREADCRUMB_TYPE, - level: 'info', - })); + expect(mockAddBreadcrumb).toHaveBeenCalledWith( + expect.objectContaining({ + category: DEFAULT_GESTURE_BREADCRUMB_CATEGORY, + type: DEFAULT_GESTURE_BREADCRUMB_TYPE, + level: 'info', + }), + ); }); it('wrapped gesture creates breadcrumb on end', () => { @@ -244,11 +252,13 @@ describe('GestureTracing', () => { jest.runAllTimers(); expect(mockAddBreadcrumb).toHaveBeenCalledTimes(1); - expect(mockAddBreadcrumb).toHaveBeenCalledWith(expect.objectContaining({ - category: DEFAULT_GESTURE_BREADCRUMB_CATEGORY, - type: DEFAULT_GESTURE_BREADCRUMB_TYPE, - level: 'info', - })); + expect(mockAddBreadcrumb).toHaveBeenCalledWith( + expect.objectContaining({ + category: DEFAULT_GESTURE_BREADCRUMB_CATEGORY, + type: DEFAULT_GESTURE_BREADCRUMB_TYPE, + level: 'info', + }), + ); }); it('wrapped gesture creates breadcrumb only with selected event keys', () => { @@ -257,12 +267,14 @@ describe('GestureTracing', () => { jest.runAllTimers(); expect(mockAddBreadcrumb).toHaveBeenCalledTimes(1); - expect(mockAddBreadcrumb).toHaveBeenCalledWith(expect.objectContaining({ - data: { - scale: 1, - gesture: 'mock', - }, - })); + expect(mockAddBreadcrumb).toHaveBeenCalledWith( + expect.objectContaining({ + data: { + scale: 1, + gesture: 'mock', + }, + }), + ); }); }); }); diff --git a/test/tracing/mockedrountinginstrumention.ts b/test/tracing/mockedrountinginstrumention.ts index 25cd3e5dd6..a3797e5030 100644 --- a/test/tracing/mockedrountinginstrumention.ts +++ b/test/tracing/mockedrountinginstrumention.ts @@ -1,27 +1,25 @@ import type { RoutingInstrumentation } from '../../src/js'; -import type { OnConfirmRoute,TransactionCreator } from '../../src/js/tracing/routingInstrumentation'; +import type { OnConfirmRoute, TransactionCreator } from '../../src/js/tracing/routingInstrumentation'; import type { BeforeNavigate } from '../../src/js/tracing/types'; export interface MockedRoutingInstrumentation extends RoutingInstrumentation { - registeredListener?: TransactionCreator, - registeredBeforeNavigate?: BeforeNavigate, - registeredOnConfirmRoute?: OnConfirmRoute, + registeredListener?: TransactionCreator; + registeredBeforeNavigate?: BeforeNavigate; + registeredOnConfirmRoute?: OnConfirmRoute; } export const createMockedRoutingInstrumentation = (): MockedRoutingInstrumentation => { const mock: MockedRoutingInstrumentation = { name: 'TestRoutingInstrumentationInstance', onRouteWillChange: jest.fn(), - registerRoutingInstrumentation: jest.fn(( - listener: TransactionCreator, - beforeNavigate: BeforeNavigate, - onConfirmRoute: OnConfirmRoute, - ) => { - mock.registeredListener = listener; - mock.registeredBeforeNavigate = beforeNavigate; - mock.registeredOnConfirmRoute = onConfirmRoute; - }), - } + registerRoutingInstrumentation: jest.fn( + (listener: TransactionCreator, beforeNavigate: BeforeNavigate, onConfirmRoute: OnConfirmRoute) => { + mock.registeredListener = listener; + mock.registeredBeforeNavigate = beforeNavigate; + mock.registeredOnConfirmRoute = onConfirmRoute; + }, + ), + }; return mock; }; diff --git a/test/tracing/nativeframes.test.ts b/test/tracing/nativeframes.test.ts index 9cc5cea65b..2b7b0429f1 100644 --- a/test/tracing/nativeframes.test.ts +++ b/test/tracing/nativeframes.test.ts @@ -16,7 +16,7 @@ jest.mock('../../src/js/wrapper', () => { }); describe('NativeFramesInstrumentation', () => { - it('Sets start frames to trace context on transaction start.', (done) => { + it('Sets start frames to trace context on transaction start.', done => { const startFrames = { totalFrames: 100, slowFrames: 20, @@ -27,8 +27,8 @@ describe('NativeFramesInstrumentation', () => { const instance = new NativeFramesInstrumentation( // eslint-disable-next-line @typescript-eslint/no-empty-function - (_eventProcessor) => { }, - () => true + _eventProcessor => {}, + () => true, ); const transaction = new Transaction({ name: 'test' }); @@ -38,15 +38,13 @@ describe('NativeFramesInstrumentation', () => { setImmediate(() => { expect(transaction.data.__startFrames).toMatchObject(startFrames); - expect(transaction.getTraceContext().data?.__startFrames).toMatchObject( - startFrames - ); + expect(transaction.getTraceContext().data?.__startFrames).toMatchObject(startFrames); done(); }); }); - it('Sets measurements on the transaction event and removes startFrames from trace context.', (done) => { + it('Sets measurements on the transaction event and removes startFrames from trace context.', done => { const startFrames = { totalFrames: 100, slowFrames: 20, @@ -63,10 +61,10 @@ describe('NativeFramesInstrumentation', () => { let eventProcessor: EventProcessor; const instance = new NativeFramesInstrumentation( // eslint-disable-next-line @typescript-eslint/no-empty-function - (_eventProcessor) => { + _eventProcessor => { eventProcessor = _eventProcessor; }, - () => true + () => true, ); const transaction = new Transaction({ name: 'test' }); @@ -84,16 +82,19 @@ describe('NativeFramesInstrumentation', () => { try { expect(eventProcessor).toBeDefined(); if (eventProcessor) { - const event = await eventProcessor({ - event_id: '0', - type: 'transaction', - transaction: transaction.name, - contexts: { - trace: transaction.getTraceContext(), + const event = await eventProcessor( + { + event_id: '0', + type: 'transaction', + transaction: transaction.name, + contexts: { + trace: transaction.getTraceContext(), + }, + start_timestamp: finishTimestamp - 10, + timestamp: finishTimestamp, }, - start_timestamp: finishTimestamp - 10, - timestamp: finishTimestamp, - }, {}); + {}, + ); // This setImmediate needs to be here for the assertions to not be caught by the promise handler. @@ -103,18 +104,14 @@ describe('NativeFramesInstrumentation', () => { expect(event.measurements).toBeDefined(); if (event.measurements) { - expect(event.measurements.frames_total.value).toBe( - finishFrames.totalFrames - startFrames.totalFrames - ); + expect(event.measurements.frames_total.value).toBe(finishFrames.totalFrames - startFrames.totalFrames); expect(event.measurements.frames_total.unit).toBe('none'); - expect(event.measurements.frames_slow.value).toBe( - finishFrames.slowFrames - startFrames.slowFrames - ); + expect(event.measurements.frames_slow.value).toBe(finishFrames.slowFrames - startFrames.slowFrames); expect(event.measurements.frames_slow.unit).toBe('none'); expect(event.measurements.frames_frozen.value).toBe( - finishFrames.frozenFrames - startFrames.frozenFrames + finishFrames.frozenFrames - startFrames.frozenFrames, ); expect(event.measurements.frames_frozen.unit).toBe('none'); } @@ -124,7 +121,7 @@ describe('NativeFramesInstrumentation', () => { if (event.contexts?.trace?.data) { expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any - (event.contexts.trace.data as any).__startFrames + (event.contexts.trace.data as any).__startFrames, ).toBeUndefined(); } } @@ -137,7 +134,7 @@ describe('NativeFramesInstrumentation', () => { }); }); - it('Does not set measurements on transactions without startFrames.', (done) => { + it('Does not set measurements on transactions without startFrames.', done => { const finishFrames = { totalFrames: 200, slowFrames: 40, @@ -149,10 +146,10 @@ describe('NativeFramesInstrumentation', () => { let eventProcessor: EventProcessor; const instance = new NativeFramesInstrumentation( // eslint-disable-next-line @typescript-eslint/no-empty-function - (_eventProcessor) => { + _eventProcessor => { eventProcessor = _eventProcessor; }, - () => true + () => true, ); const transaction = new Transaction({ name: 'test' }); @@ -166,17 +163,20 @@ describe('NativeFramesInstrumentation', () => { setImmediate(async () => { expect(eventProcessor).toBeDefined(); if (eventProcessor) { - const event = await eventProcessor({ - event_id: '0', - type: 'transaction', - transaction: transaction.name, - contexts: { - trace: transaction.getTraceContext(), + const event = await eventProcessor( + { + event_id: '0', + type: 'transaction', + transaction: transaction.name, + contexts: { + trace: transaction.getTraceContext(), + }, + start_timestamp: finishTimestamp - 10, + timestamp: finishTimestamp, + measurements: {}, }, - start_timestamp: finishTimestamp - 10, - timestamp: finishTimestamp, - measurements: {}, - }, {}); + {}, + ); // This setImmediate needs to be here for the assertions to not be caught by the promise handler. setImmediate(() => { @@ -196,7 +196,7 @@ describe('NativeFramesInstrumentation', () => { if (event.contexts?.trace?.data) { expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any - (event.contexts.trace.data as any).__startFrames + (event.contexts.trace.data as any).__startFrames, ).toBeUndefined(); } } @@ -208,7 +208,7 @@ describe('NativeFramesInstrumentation', () => { }); }); - it('Sets measurements on the transaction event and removes startFrames if finishFrames is null.', (done) => { + it('Sets measurements on the transaction event and removes startFrames if finishFrames is null.', done => { const startFrames = { totalFrames: 100, slowFrames: 20, @@ -221,10 +221,10 @@ describe('NativeFramesInstrumentation', () => { let eventProcessor: EventProcessor; const instance = new NativeFramesInstrumentation( // eslint-disable-next-line @typescript-eslint/no-empty-function - (_eventProcessor) => { + _eventProcessor => { eventProcessor = _eventProcessor; }, - () => true + () => true, ); const transaction = new Transaction({ name: 'test' }); @@ -242,16 +242,19 @@ describe('NativeFramesInstrumentation', () => { try { expect(eventProcessor).toBeDefined(); if (eventProcessor) { - const event = await eventProcessor({ - event_id: '0', - type: 'transaction', - transaction: transaction.name, - contexts: { - trace: transaction.getTraceContext(), + const event = await eventProcessor( + { + event_id: '0', + type: 'transaction', + transaction: transaction.name, + contexts: { + trace: transaction.getTraceContext(), + }, + start_timestamp: finishTimestamp - 10, + timestamp: finishTimestamp, }, - start_timestamp: finishTimestamp - 10, - timestamp: finishTimestamp, - }, {}); + {}, + ); expect(event).toBeDefined(); @@ -263,7 +266,7 @@ describe('NativeFramesInstrumentation', () => { if (event.contexts?.trace?.data) { expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any - (event.contexts.trace.data as any).__startFrames + (event.contexts.trace.data as any).__startFrames, ).toBeUndefined(); } } @@ -277,7 +280,7 @@ describe('NativeFramesInstrumentation', () => { }); }); - it('Does not set measurements on the transaction event and removes startFrames if finishFrames times out.', (done) => { + it('Does not set measurements on the transaction event and removes startFrames if finishFrames times out.', done => { const startFrames = { totalFrames: 100, slowFrames: 20, @@ -289,10 +292,10 @@ describe('NativeFramesInstrumentation', () => { let eventProcessor: EventProcessor; const instance = new NativeFramesInstrumentation( // eslint-disable-next-line @typescript-eslint/no-empty-function - (_eventProcessor) => { + _eventProcessor => { eventProcessor = _eventProcessor; }, - () => true + () => true, ); const transaction = new Transaction({ name: 'test' }); @@ -303,7 +306,7 @@ describe('NativeFramesInstrumentation', () => { // eslint-disable-next-line @typescript-eslint/unbound-method mockFunction(NATIVE.fetchNativeFrames).mockImplementation( // eslint-disable-next-line @typescript-eslint/no-empty-function - async () => new Promise(() => { }) + async () => new Promise(() => {}), ); const finishTimestamp = Date.now() / 1000; @@ -313,16 +316,19 @@ describe('NativeFramesInstrumentation', () => { try { expect(eventProcessor).toBeDefined(); if (eventProcessor) { - const event = await eventProcessor({ - event_id: '0', - type: 'transaction', - transaction: transaction.name, - contexts: { - trace: transaction.getTraceContext(), + const event = await eventProcessor( + { + event_id: '0', + type: 'transaction', + transaction: transaction.name, + contexts: { + trace: transaction.getTraceContext(), + }, + start_timestamp: finishTimestamp - 10, + timestamp: finishTimestamp, }, - start_timestamp: finishTimestamp - 10, - timestamp: finishTimestamp, - }, {}); + {}, + ); expect(event).toBeDefined(); @@ -334,7 +340,7 @@ describe('NativeFramesInstrumentation', () => { if (event.contexts?.trace?.data) { expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any - (event.contexts.trace.data as any).__startFrames + (event.contexts.trace.data as any).__startFrames, ).toBeUndefined(); } } diff --git a/test/tracing/reactnativenavigation.test.ts b/test/tracing/reactnativenavigation.test.ts index 4445ea1b22..640e6441ed 100644 --- a/test/tracing/reactnativenavigation.test.ts +++ b/test/tracing/reactnativenavigation.test.ts @@ -6,10 +6,9 @@ import type { BottomTabPressedEvent, ComponentWillAppearEvent, EventsRegistry, - NavigationDelegate} from '../../src/js/tracing/reactnativenavigation'; -import { - ReactNativeNavigationInstrumentation, + NavigationDelegate, } from '../../src/js/tracing/reactnativenavigation'; +import { ReactNativeNavigationInstrumentation } from '../../src/js/tracing/reactnativenavigation'; import type { TransactionCreator } from '../../src/js/tracing/routingInstrumentation'; import { getMockTransaction } from '../testutils'; @@ -32,9 +31,7 @@ const mockEventsRegistry: MockEventsRegistry = { onBottomTabPressed(event) { this.bottomTabPressedListener?.(event); }, - registerComponentWillAppearListener( - callback: (event: ComponentWillAppearEvent) => void - ) { + registerComponentWillAppearListener(callback: (event: ComponentWillAppearEvent) => void) { this.componentWillAppearListener = callback; return { // eslint-disable-next-line @typescript-eslint/no-empty-function @@ -52,7 +49,7 @@ const mockEventsRegistry: MockEventsRegistry = { this.bottomTabPressedListener = callback; return { // eslint-disable-next-line @typescript-eslint/no-empty-function - remove() { }, + remove() {}, } as EmitterSubscription; }, }; @@ -69,19 +66,15 @@ describe('React Native Navigation Instrumentation', () => { let mockTransaction: Transaction; beforeEach(() => { - instrumentation = new ReactNativeNavigationInstrumentation( - mockNavigationDelegate - ); + instrumentation = new ReactNativeNavigationInstrumentation(mockNavigationDelegate); - mockTransaction = getMockTransaction( - ReactNativeNavigationInstrumentation.instrumentationName - ); + mockTransaction = getMockTransaction(ReactNativeNavigationInstrumentation.instrumentationName); tracingListener = jest.fn((_context: TransactionContext) => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener, - (context) => context, - () => {} + context => context, + () => {}, ); }); @@ -102,40 +95,42 @@ describe('React Native Navigation Instrumentation', () => { }; mockEventsRegistry.onComponentWillAppear(mockEvent); - expect(mockTransaction).toEqual(expect.objectContaining(>{ - name: 'Test', - tags: { - 'routing.instrumentation': 'react-native-navigation', - 'routing.route.name': 'Test', - }, - data: { - route: { - componentId: '0', - componentName: 'Test', - componentType: 'Component', - passProps: {}, - name: 'Test', - hasBeenSeen: false, + expect(mockTransaction).toEqual( + expect.objectContaining(>{ + name: 'Test', + tags: { + 'routing.instrumentation': 'react-native-navigation', + 'routing.route.name': 'Test', }, - previousRoute: null, - }, - metadata: expect.objectContaining({ - source: 'component', + data: { + route: { + componentId: '0', + componentName: 'Test', + componentType: 'Component', + passProps: {}, + name: 'Test', + hasBeenSeen: false, + }, + previousRoute: null, + }, + metadata: expect.objectContaining({ + source: 'component', + }), }), - })); + ); }); test('Transaction context is changed with beforeNavigate', () => { instrumentation.registerRoutingInstrumentation( tracingListener, - (context) => { + context => { context.sampled = false; context.description = 'Description'; context.name = 'New Name'; return context; }, - () => {} + () => {}, ); mockEventsRegistry.onCommand('root', {}); @@ -150,29 +145,31 @@ describe('React Native Navigation Instrumentation', () => { }; mockEventsRegistry.onComponentWillAppear(mockEvent); - expect(mockTransaction).toEqual(expect.objectContaining(>{ - name: 'New Name', - description: 'Description', - sampled: false, - tags: { - 'routing.instrumentation': 'react-native-navigation', - 'routing.route.name': 'Test', - }, - data: { - route: { - componentId: '0', - componentName: 'Test', - componentType: 'Component', - passProps: {}, - name: 'Test', - hasBeenSeen: false, + expect(mockTransaction).toEqual( + expect.objectContaining(>{ + name: 'New Name', + description: 'Description', + sampled: false, + tags: { + 'routing.instrumentation': 'react-native-navigation', + 'routing.route.name': 'Test', }, - previousRoute: null, - }, - metadata: expect.objectContaining({ - source: 'custom', + data: { + route: { + componentId: '0', + componentName: 'Test', + componentType: 'Component', + passProps: {}, + name: 'Test', + hasBeenSeen: false, + }, + previousRoute: null, + }, + metadata: expect.objectContaining({ + source: 'custom', + }), }), - })); + ); }); test('Transaction not sent on a cancelled route change', () => { @@ -216,11 +213,13 @@ describe('React Native Navigation Instrumentation', () => { describe('tab change', () => { beforeEach(() => { - instrumentation = new ReactNativeNavigationInstrumentation(mockNavigationDelegate, { enableTabsInstrumentation: true }); + instrumentation = new ReactNativeNavigationInstrumentation(mockNavigationDelegate, { + enableTabsInstrumentation: true, + }); instrumentation.registerRoutingInstrumentation( tracingListener, - (context) => context, - () => { }, + context => context, + () => {}, ); }); @@ -233,38 +232,39 @@ describe('React Native Navigation Instrumentation', () => { passProps: {}, }); - expect(mockTransaction.toContext()).toEqual(expect.objectContaining(>{ - name: 'TestScreenName', - tags: { - 'routing.instrumentation': 'react-native-navigation', - 'routing.route.name': 'TestScreenName', - }, - data: { - route: { - componentId: '0', - componentName: 'TestScreenName', - componentType: 'Component', - passProps: {}, - name: 'TestScreenName', - hasBeenSeen: false, + expect(mockTransaction.toContext()).toEqual( + expect.objectContaining(>{ + name: 'TestScreenName', + tags: { + 'routing.instrumentation': 'react-native-navigation', + 'routing.route.name': 'TestScreenName', }, - previousRoute: null, - }, - })); + data: { + route: { + componentId: '0', + componentName: 'TestScreenName', + componentType: 'Component', + passProps: {}, + name: 'TestScreenName', + hasBeenSeen: false, + }, + previousRoute: null, + }, + }), + ); }); test('not instrument tabs if disabled', () => { jest.useFakeTimers(); - instrumentation = new ReactNativeNavigationInstrumentation( - mockNavigationDelegate, - { enableTabsInstrumentation: false }, - ); + instrumentation = new ReactNativeNavigationInstrumentation(mockNavigationDelegate, { + enableTabsInstrumentation: false, + }); tracingListener = jest.fn((_context: TransactionContext) => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener, - (context) => context, - () => { }, + context => context, + () => {}, ); mockEventsRegistry.onBottomTabPressed({ tabIndex: 0 }); @@ -289,10 +289,10 @@ describe('React Native Navigation Instrumentation', () => { beforeEach(() => { instrumentation.registerRoutingInstrumentation( tracingListener, - (context) => context, - (context) => { + context => context, + context => { confirmedContext = context; - } + }, ); }); @@ -319,17 +319,19 @@ describe('React Native Navigation Instrumentation', () => { }; mockEventsRegistry.onComponentWillAppear(mockEvent2); - expect(confirmedContext).toEqual(expect.objectContaining(>{ - name: 'Test 2', - data: { - route: expect.objectContaining({ - name: 'Test 2', - }), - previousRoute: expect.objectContaining({ - name: 'Test 1', - }), - }, - })); + expect(confirmedContext).toEqual( + expect.objectContaining(>{ + name: 'Test 2', + data: { + route: expect.objectContaining({ + name: 'Test 2', + }), + previousRoute: expect.objectContaining({ + name: 'Test 1', + }), + }, + }), + ); }); test('onRouteConfirmed clears transaction', () => { @@ -353,9 +355,11 @@ describe('React Native Navigation Instrumentation', () => { }; mockEventsRegistry.onComponentWillAppear(mockEvent2); - expect(confirmedContext).toEqual(expect.objectContaining(>{ - name: 'Test 1', - })); + expect(confirmedContext).toEqual( + expect.objectContaining(>{ + name: 'Test 1', + }), + ); }); }); }); diff --git a/test/tracing/reactnativetracing.test.ts b/test/tracing/reactnativetracing.test.ts index b950fa52a5..85aa369550 100644 --- a/test/tracing/reactnativetracing.test.ts +++ b/test/tracing/reactnativetracing.test.ts @@ -46,7 +46,7 @@ const getMockScope = () => { // Placeholder }, getUser: () => scopeUser, - } + }; }; const getMockHub = () => { @@ -56,7 +56,7 @@ const getMockHub = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any mockHub.getScope = () => mockScope as any; // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockHub.configureScope = jest.fn((callback) => callback(mockScope as any)); + mockHub.configureScope = jest.fn(callback => callback(mockScope as any)); return mockHub; }; @@ -75,7 +75,10 @@ import { getTimeOriginMilliseconds } from '../../src/js/tracing/utils'; import { NATIVE } from '../../src/js/wrapper'; import { firstArg, mockFunction } from '../testutils'; import type { MockedRoutingInstrumentation } from './mockedrountinginstrumention'; -import { createMockedRoutingInstrumentation, mockedConfirmedRouteTransactionContext } from './mockedrountinginstrumention'; +import { + createMockedRoutingInstrumentation, + mockedConfirmedRouteTransactionContext, +} from './mockedrountinginstrumention'; const DEFAULT_IDLE_TIMEOUT = 1000; @@ -90,7 +93,7 @@ afterEach(() => { describe('ReactNativeTracing', () => { describe('App Start', () => { describe('Without routing instrumentation', () => { - it('Starts route transaction (cold)', (done) => { + it('Starts route transaction (cold)', done => { const integration = new ReactNativeTracing({ enableNativeFramesTracking: false, }); @@ -103,13 +106,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: false, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -122,25 +121,24 @@ describe('ReactNativeTracing', () => { expect(transaction).toBeDefined(); if (transaction) { - expect(transaction.startTimestamp).toBe( - appStartTimeMilliseconds / 1000 - ); + expect(transaction.startTimestamp).toBe(appStartTimeMilliseconds / 1000); expect(transaction.op).toBe(UI_LOAD); expect( // @ts-ignore access private for test - transaction._measurements[APP_START_COLD].value + transaction._measurements[APP_START_COLD].value, ).toEqual(timeOriginMilliseconds - appStartTimeMilliseconds); expect( // @ts-ignore access private for test - transaction._measurements[APP_START_COLD].unit).toBe('millisecond'); + transaction._measurements[APP_START_COLD].unit, + ).toBe('millisecond'); done(); } }); }); - it('Starts route transaction (warm)', (done) => { + it('Starts route transaction (warm)', done => { const integration = new ReactNativeTracing(); const timeOriginMilliseconds = Date.now(); @@ -151,13 +149,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: false, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -169,25 +163,24 @@ describe('ReactNativeTracing', () => { expect(transaction).toBeDefined(); if (transaction) { - expect(transaction.startTimestamp).toBe( - appStartTimeMilliseconds / 1000 - ); + expect(transaction.startTimestamp).toBe(appStartTimeMilliseconds / 1000); expect(transaction.op).toBe(UI_LOAD); expect( // @ts-ignore access private for test - transaction._measurements[APP_START_WARM].value + transaction._measurements[APP_START_WARM].value, ).toEqual(timeOriginMilliseconds - appStartTimeMilliseconds); expect( // @ts-ignore access private for test - transaction._measurements[APP_START_WARM].unit).toBe('millisecond'); + transaction._measurements[APP_START_WARM].unit, + ).toBe('millisecond'); done(); } }); }); - it('Does not add app start measurement if more than 60s', (done) => { + it('Does not add app start measurement if more than 60s', done => { const integration = new ReactNativeTracing(); const timeOriginMilliseconds = Date.now(); @@ -198,13 +191,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: false, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -218,12 +207,12 @@ describe('ReactNativeTracing', () => { if (transaction) { expect( // @ts-ignore access private for test - transaction._measurements[APP_START_WARM] + transaction._measurements[APP_START_WARM], ).toBeUndefined(); expect( // @ts-ignore access private for test - transaction._measurements[APP_START_COLD] + transaction._measurements[APP_START_COLD], ).toBeUndefined(); done(); @@ -231,7 +220,7 @@ describe('ReactNativeTracing', () => { }); }); - it('Does not create app start transaction if didFetchAppStart == true', (done) => { + it('Does not create app start transaction if didFetchAppStart == true', done => { const integration = new ReactNativeTracing(); const timeOriginMilliseconds = Date.now(); @@ -242,13 +231,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: true, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -288,13 +273,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: false, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -317,13 +298,11 @@ describe('ReactNativeTracing', () => { // @ts-ignore access private for test expect(routeTransaction._measurements[APP_START_COLD].value).toBe( - timeOriginMilliseconds - appStartTimeMilliseconds + timeOriginMilliseconds - appStartTimeMilliseconds, ); expect(routeTransaction.op).toBe(UI_LOAD); - expect(routeTransaction.startTimestamp).toBe( - appStartTimeMilliseconds / 1000 - ); + expect(routeTransaction.startTimestamp).toBe(appStartTimeMilliseconds / 1000); const spanRecorder = routeTransaction.spanRecorder; expect(spanRecorder).toBeDefined(); @@ -351,13 +330,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: false, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -380,13 +355,11 @@ describe('ReactNativeTracing', () => { // @ts-ignore access private for test expect(routeTransaction._measurements[APP_START_WARM].value).toBe( - timeOriginMilliseconds - appStartTimeMilliseconds + timeOriginMilliseconds - appStartTimeMilliseconds, ); expect(routeTransaction.op).toBe(UI_LOAD); - expect(routeTransaction.startTimestamp).toBe( - appStartTimeMilliseconds / 1000 - ); + expect(routeTransaction.startTimestamp).toBe(appStartTimeMilliseconds / 1000); const spanRecorder = routeTransaction.spanRecorder; expect(spanRecorder).toBeDefined(); @@ -414,13 +387,9 @@ describe('ReactNativeTracing', () => { didFetchAppStart: true, }; - mockFunction(getTimeOriginMilliseconds).mockReturnValue( - timeOriginMilliseconds - ); + mockFunction(getTimeOriginMilliseconds).mockReturnValue(timeOriginMilliseconds); // eslint-disable-next-line @typescript-eslint/unbound-method - mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue( - mockAppStartResponse - ); + mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(mockAppStartResponse); const mockHub = getMockHub(); integration.setupOnce(addGlobalEventProcessor, () => mockHub); @@ -445,9 +414,7 @@ describe('ReactNativeTracing', () => { expect(routeTransaction._measurements).toMatchObject({}); expect(routeTransaction.op).not.toBe(UI_LOAD); - expect(routeTransaction.startTimestamp).not.toBe( - appStartTimeMilliseconds / 1000 - ); + expect(routeTransaction.startTimestamp).not.toBe(appStartTimeMilliseconds / 1000); const spanRecorder = routeTransaction.spanRecorder; expect(spanRecorder).toBeDefined(); @@ -455,7 +422,7 @@ describe('ReactNativeTracing', () => { }); }); - it('Does not instrument app start if app start is disabled', (done) => { + it('Does not instrument app start if app start is disabled', done => { const integration = new ReactNativeTracing({ enableAppStartTracking: false, }); @@ -474,7 +441,7 @@ describe('ReactNativeTracing', () => { }); }); - it('Does not instrument app start if native is disabled', (done) => { + it('Does not instrument app start if native is disabled', done => { NATIVE.enableNative = false; const integration = new ReactNativeTracing(); @@ -493,7 +460,7 @@ describe('ReactNativeTracing', () => { }); }); - it('Does not instrument app start if fetchNativeAppStart returns null', (done) => { + it('Does not instrument app start if fetchNativeAppStart returns null', done => { // eslint-disable-next-line @typescript-eslint/unbound-method mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(null); @@ -515,7 +482,7 @@ describe('ReactNativeTracing', () => { }); describe('Native Frames', () => { - it('Initialize native frames instrumentation if flag is true', (done) => { + it('Initialize native frames instrumentation if flag is true', done => { const integration = new ReactNativeTracing({ enableNativeFramesTracking: true, }); @@ -530,7 +497,7 @@ describe('ReactNativeTracing', () => { done(); }); }); - it('Does not initialize native frames instrumentation if flag is false', (done) => { + it('Does not initialize native frames instrumentation if flag is false', done => { const integration = new ReactNativeTracing({ enableNativeFramesTracking: false, }); @@ -571,9 +538,9 @@ describe('ReactNativeTracing', () => { setTag: jest.fn(), // Not relevant to test - setSpan: () => { }, - getTransaction: () => { }, - clearTransaction: () => { }, + setSpan: () => {}, + getTransaction: () => {}, + clearTransaction: () => {}, }; const mockHub = { @@ -585,12 +552,12 @@ describe('ReactNativeTracing', () => { getScope: () => mockScope, getClient: () => ({ getOptions: () => ({}), - recordDroppedEvent: () => { }, + recordDroppedEvent: () => {}, }), }; integration.setupOnce( - () => { }, - () => mockHub as any + () => {}, + () => mockHub as any, ); const routeContext = { @@ -606,10 +573,7 @@ describe('ReactNativeTracing', () => { }; routing.onRouteWillChange(routeContext); - expect(mockScope.setTag).toBeCalledWith( - 'routing.route.name', - routeContext.name - ); + expect(mockScope.setTag).toBeCalledWith('routing.route.name', routeContext.name); expect(mockScope.addBreadcrumb).toBeCalledWith({ type: 'navigation', category: 'navigation', @@ -675,7 +639,7 @@ describe('ReactNativeTracing', () => { let mockedScope: Scope; let mockedHub: Hub; let tracing: ReactNativeTracing; - let mockedUserInteractionId: { elementId: string | undefined; op: string; }; + let mockedUserInteractionId: { elementId: string | undefined; op: string }; let mockedRoutingInstrumentation: MockedRoutingInstrumentation; beforeEach(() => { @@ -720,10 +684,12 @@ describe('ReactNativeTracing', () => { const actualTransaction = mockFunction(mockedScope.setSpan).mock.calls[0][firstArg]; const actualTransactionContext = actualTransaction?.toContext(); expect(tracing.options.enableUserInteractionTracing).toBeTruthy(); - expect(actualTransactionContext).toEqual(expect.objectContaining({ - name: 'mockedRouteName.mockedElementId', - op: 'mocked.op', - })); + expect(actualTransactionContext).toEqual( + expect.objectContaining({ + name: 'mockedRouteName.mockedElementId', + op: 'mocked.op', + }), + ); }); test('UI event transaction not sampled if no child spans', () => { @@ -746,10 +712,12 @@ describe('ReactNativeTracing', () => { jest.runAllTimers(); const actualTransactionContext = actualTransaction?.toContext(); - expect(actualTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - status: 'mocked_status', - })); + expect(actualTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + status: 'mocked_status', + }), + ); }); test('same UI event and same element does not reschedule idle timeout', () => { @@ -779,17 +747,20 @@ describe('ReactNativeTracing', () => { const firstTransactionContext = firstTransaction?.toContext(); const secondTransactionContext = secondTransaction?.toContext(); - expect(firstTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - op: 'mocked.op', - sampled: true, - })); - expect(secondTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - op: 'different.op', - })); - expect(firstTransactionContext!.endTimestamp) - .toBeGreaterThanOrEqual(secondTransactionContext!.startTimestamp!); + expect(firstTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + op: 'mocked.op', + sampled: true, + }), + ); + expect(secondTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + op: 'different.op', + }), + ); + expect(firstTransactionContext!.endTimestamp).toBeGreaterThanOrEqual(secondTransactionContext!.startTimestamp!); }); test('different UI event and same element finish first transaction with last span', () => { @@ -804,11 +775,13 @@ describe('ReactNativeTracing', () => { childFirstTransaction?.finish(); const firstTransactionContext = firstTransaction?.toContext(); - expect(firstTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - op: 'mocked.op', - sampled: true, - })); + expect(firstTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + op: 'mocked.op', + sampled: true, + }), + ); }); test('same ui event after UI event transaction finished', () => { @@ -852,15 +825,20 @@ describe('ReactNativeTracing', () => { const interactionTransactionContext = interactionTransaction?.toContext(); const routingTransactionContext = routingTransaction?.toContext(); - expect(interactionTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - status: 'cancelled', - })); - expect(routingTransactionContext).toEqual(expect.objectContaining({ - endTimestamp: expect.any(Number), - })); - expect(interactionTransactionContext!.endTimestamp) - .toBeLessThanOrEqual(routingTransactionContext!.startTimestamp!); + expect(interactionTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + status: 'cancelled', + }), + ); + expect(routingTransactionContext).toEqual( + expect.objectContaining({ + endTimestamp: expect.any(Number), + }), + ); + expect(interactionTransactionContext!.endTimestamp).toBeLessThanOrEqual( + routingTransactionContext!.startTimestamp!, + ); }); test('UI event transaction calls lifecycle callbacks', () => { @@ -880,5 +858,5 @@ describe('ReactNativeTracing', () => { expect(tracing.onTransactionFinish).toBeCalledWith(actualTransaction); }); }); - }) + }); }); diff --git a/test/tracing/reactnavigation.test.ts b/test/tracing/reactnavigation.test.ts index 8f81ae9a41..6df65eeb11 100644 --- a/test/tracing/reactnavigation.test.ts +++ b/test/tracing/reactnavigation.test.ts @@ -2,12 +2,8 @@ import { Transaction } from '@sentry/tracing'; import type { TransactionContext } from '@sentry/types'; -import type { - NavigationRoute} from '../../src/js/tracing/reactnavigation'; -import { - BLANK_TRANSACTION_CONTEXT, - ReactNavigationInstrumentation, -} from '../../src/js/tracing/reactnavigation'; +import type { NavigationRoute } from '../../src/js/tracing/reactnavigation'; +import { BLANK_TRANSACTION_CONTEXT, ReactNavigationInstrumentation } from '../../src/js/tracing/reactnavigation'; import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide'; const dummyRoute = { @@ -18,11 +14,9 @@ const dummyRoute = { class MockNavigationContainer { currentRoute: NavigationRoute | undefined = dummyRoute; listeners: Record void> = {}; - addListener: any = jest.fn( - (eventType: string, listener: (e: any) => void): void => { - this.listeners[eventType] = listener; - } - ); + addListener: any = jest.fn((eventType: string, listener: (e: any) => void): void => { + this.listeners[eventType] = listener; + }); getCurrentRoute(): NavigationRoute | undefined { return this.currentRoute; } @@ -51,17 +45,15 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); expect(mockTransaction.name).toBe(dummyRoute.name); expect(mockTransaction.tags).toStrictEqual({ @@ -91,24 +83,22 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => transactionRef.current); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); const mockTransaction = getMockTransaction(); transactionRef.current = mockTransaction; mockNavigationContainerRef.current.listeners['__unsafe_action__']({}); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { const route = { name: 'New Route', @@ -160,30 +150,28 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => transactionRef.current); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => { + context => { context.sampled = false; context.description = 'Description'; context.name = 'New Name'; return context; }, - () => {} + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); const mockTransaction = getMockTransaction(); transactionRef.current = mockTransaction; mockNavigationContainerRef.current.listeners['__unsafe_action__']({}); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { const route = { name: 'DoNotSend', @@ -212,32 +200,26 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => transactionRef.current); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); const mockTransaction = getMockTransaction(); transactionRef.current = mockTransaction; mockNavigationContainerRef.current.listeners['__unsafe_action__']({}); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { expect(mockTransaction.sampled).toBe(false); - expect(mockTransaction.name).toStrictEqual( - BLANK_TRANSACTION_CONTEXT.name - ); - expect(mockTransaction.tags).toStrictEqual( - BLANK_TRANSACTION_CONTEXT.tags - ); + expect(mockTransaction.name).toStrictEqual(BLANK_TRANSACTION_CONTEXT.name); + expect(mockTransaction.tags).toStrictEqual(BLANK_TRANSACTION_CONTEXT.tags); expect(mockTransaction.data).toStrictEqual({}); resolve(); }, 1100); @@ -255,17 +237,15 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => transactionRef.current); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); const mockTransaction1 = getMockTransaction(); transactionRef.current = mockTransaction1; @@ -277,7 +257,7 @@ describe('ReactNavigationInstrumentation', () => { mockNavigationContainerRef.current.listeners['__unsafe_action__']({}); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { expect(mockTransaction1.sampled).toBe(false); expect(mockTransaction2.sampled).toBe(false); @@ -297,17 +277,9 @@ describe('ReactNavigationInstrumentation', () => { expect(RN_GLOBAL_OBJ.__sentry_rn_v5_registered).toBe(true); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith( - 1, - '__unsafe_action__', - expect.any(Function) - ); + expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith(1, '__unsafe_action__', expect.any(Function)); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith( - 2, - 'state', - expect.any(Function) - ); + expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith(2, 'state', expect.any(Function)); }); test('registers navigation container direct ref', () => { @@ -318,17 +290,9 @@ describe('ReactNavigationInstrumentation', () => { expect(RN_GLOBAL_OBJ.__sentry_rn_v5_registered).toBe(true); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith( - 1, - '__unsafe_action__', - expect.any(Function) - ); + expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith(1, '__unsafe_action__', expect.any(Function)); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith( - 2, - 'state', - expect.any(Function) - ); + expect(mockNavigationContainer.addListener).toHaveBeenNthCalledWith(2, 'state', expect.any(Function)); }); test('does not register navigation container if there is an existing one', () => { @@ -358,11 +322,11 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { expect(mockTransaction.sampled).not.toBe(false); resolve(); @@ -381,19 +345,17 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - return new Promise((resolve) => { + return new Promise(resolve => { setTimeout(() => { - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); expect(mockTransaction.sampled).toBe(true); expect(mockTransaction.name).toBe(dummyRoute.name); @@ -412,19 +374,17 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - return new Promise((resolve) => { + return new Promise(resolve => { setTimeout(() => { - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); expect(mockTransaction.sampled).toBe(false); resolve(); @@ -446,19 +406,17 @@ describe('ReactNavigationInstrumentation', () => { const tracingListener = jest.fn(() => transactionRef.current); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - (context) => { + context => context, + context => { confirmedContext = context; - } + }, ); const mockNavigationContainerRef = { current: new MockNavigationContainer(), }; - instrumentation.registerNavigationContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerNavigationContainer(mockNavigationContainerRef as any); const mockTransaction = getMockTransaction(); transactionRef.current = mockTransaction; diff --git a/test/tracing/reactnavigationv4.test.ts b/test/tracing/reactnavigationv4.test.ts index 249decac3d..7038e8f151 100644 --- a/test/tracing/reactnavigationv4.test.ts +++ b/test/tracing/reactnavigationv4.test.ts @@ -5,7 +5,8 @@ import type { TransactionContext } from '@sentry/types'; import type { AppContainerInstance, NavigationRouteV4, - NavigationStateV4} from '../../src/js/tracing/reactnavigationv4'; + NavigationStateV4, +} from '../../src/js/tracing/reactnavigationv4'; import { INITIAL_TRANSACTION_CONTEXT_V4, ReactNavigationV4Instrumentation, @@ -34,20 +35,14 @@ class MockAppContainer implements AppContainerInstance { state: NavigationStateV4; router: { dispatchAction: (action: any) => void; - getStateForAction: ( - action: any, - state: NavigationStateV4 - ) => NavigationStateV4; + getStateForAction: (action: any, state: NavigationStateV4) => NavigationStateV4; }; }; constructor() { const router = { dispatchAction: (action: any) => { - const newState = router.getStateForAction( - action, - this._navigation.state - ); + const newState = router.getStateForAction(action, this._navigation.state); this._navigation.state = newState; }, @@ -99,8 +94,8 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockAppContainerRef = { @@ -109,21 +104,17 @@ describe('ReactNavigationV4Instrumentation', () => { instrumentation.registerAppContainer(mockAppContainerRef as any); - const firstRoute = mockAppContainerRef.current._navigation.state - .routes[0] as NavigationRouteV4; + const firstRoute = mockAppContainerRef.current._navigation.state.routes[0] as NavigationRouteV4; // eslint-disable-next-line @typescript-eslint/unbound-method expect(instrumentation.onRouteWillChange).toHaveBeenCalledTimes(1); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(instrumentation.onRouteWillChange).toHaveBeenLastCalledWith( - INITIAL_TRANSACTION_CONTEXT_V4 - ); + expect(instrumentation.onRouteWillChange).toHaveBeenLastCalledWith(INITIAL_TRANSACTION_CONTEXT_V4); expect(mockTransaction.name).toBe(firstRoute.routeName); expect(mockTransaction.tags).toStrictEqual({ - 'routing.instrumentation': - ReactNavigationV4Instrumentation.instrumentationName, + 'routing.instrumentation': ReactNavigationV4Instrumentation.instrumentationName, 'routing.route.name': firstRoute.routeName, }); expect(mockTransaction.data).toStrictEqual({ @@ -148,8 +139,8 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockAppContainerRef = { @@ -175,8 +166,7 @@ describe('ReactNavigationV4Instrumentation', () => { name: action.routeName, op: 'navigation', tags: { - 'routing.instrumentation': - ReactNavigationV4Instrumentation.instrumentationName, + 'routing.instrumentation': ReactNavigationV4Instrumentation.instrumentationName, 'routing.route.name': action.routeName, }, data: { @@ -207,7 +197,7 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => { + context => { context.sampled = false; context.description = 'Description'; context.name = 'New Name'; @@ -215,7 +205,7 @@ describe('ReactNavigationV4Instrumentation', () => { return context; }, - () => {} + () => {}, ); const mockAppContainerRef = { @@ -273,8 +263,8 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockAppContainerRef = { @@ -301,8 +291,8 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockAppContainer = new MockAppContainer(); @@ -326,8 +316,8 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockAppContainer = new MockAppContainer(); @@ -351,8 +341,8 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockAppContainer = new MockAppContainer(); @@ -360,7 +350,7 @@ describe('ReactNavigationV4Instrumentation', () => { expect(RN_GLOBAL_OBJ.__sentry_rn_v4_registered).toBe(true); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { expect(mockTransaction.sampled).toBe(false); resolve(); @@ -378,11 +368,11 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); - await new Promise((resolve) => { + await new Promise(resolve => { setTimeout(() => { expect(mockTransaction.sampled).toBe(true); resolve(); @@ -401,19 +391,17 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockAppContainer(), }; - return new Promise((resolve) => { + return new Promise(resolve => { setTimeout(() => { - instrumentation.registerAppContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerAppContainer(mockNavigationContainerRef as any); expect(mockTransaction.sampled).toBe(true); expect(mockTransaction.name).toBe(initialRoute.routeName); @@ -432,19 +420,17 @@ describe('ReactNavigationV4Instrumentation', () => { const tracingListener = jest.fn(() => mockTransaction); instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - () => {} + context => context, + () => {}, ); const mockNavigationContainerRef = { current: new MockAppContainer(), }; - return new Promise((resolve) => { + return new Promise(resolve => { setTimeout(() => { - instrumentation.registerAppContainer( - mockNavigationContainerRef as any - ); + instrumentation.registerAppContainer(mockNavigationContainerRef as any); expect(mockTransaction.sampled).toBe(false); resolve(); @@ -464,10 +450,10 @@ describe('ReactNavigationV4Instrumentation', () => { let confirmedContext: TransactionContext | undefined; instrumentation.registerRoutingInstrumentation( tracingListener as any, - (context) => context, - (context) => { + context => context, + context => { confirmedContext = context; - } + }, ); const mockAppContainerRef = { @@ -503,9 +489,7 @@ describe('ReactNavigationV4Instrumentation', () => { expect(confirmedContext.data.route.name).toBe(route2.routeName); expect(confirmedContext.data.previousRoute).toBeDefined(); if (confirmedContext.data.previousRoute) { - expect(confirmedContext.data.previousRoute.name).toBe( - route1.routeName - ); + expect(confirmedContext.data.previousRoute.name).toBe(route1.routeName); } } } diff --git a/test/tracing/stalltracking.test.ts b/test/tracing/stalltracking.test.ts index 708f4c2f4d..422015f11d 100644 --- a/test/tracing/stalltracking.test.ts +++ b/test/tracing/stalltracking.test.ts @@ -31,7 +31,7 @@ beforeEach(() => { describe('StallTracking', () => { const localHub: Hub = mockHub as unknown as Hub; - it('Stall tracking detects a JS stall', (done) => { + it('Stall tracking detects a JS stall', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -56,10 +56,10 @@ describe('StallTracking', () => { expect(measurements).toBeDefined(); if (measurements) { expect(measurements.stall_count.value).toBeGreaterThan(0); - expect(measurements.stall_count.unit).toBe('none') + expect(measurements.stall_count.unit).toBe('none'); expect(measurements.stall_longest_time.value).toBeGreaterThan(0); - expect(measurements.stall_longest_time.unit).toBe('millisecond') + expect(measurements.stall_longest_time.unit).toBe('millisecond'); expect(measurements.stall_total_time.value).toBeGreaterThan(0); expect(measurements.stall_total_time.unit).toBe('millisecond'); @@ -69,7 +69,7 @@ describe('StallTracking', () => { }, 500); }); - it('Stall tracking detects multiple JS stalls', (done) => { + it('Stall tracking detects multiple JS stalls', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -128,7 +128,7 @@ describe('StallTracking', () => { expect(stallTracking.isTracking).toBe(false); }); - it('Stall tracking timeout is stopped after finishing all transactions (multiple)', (done) => { + it('Stall tracking timeout is stopped after finishing all transactions (multiple)', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction0 = new Transaction( @@ -232,7 +232,7 @@ describe('StallTracking', () => { expect(measurements).toBeUndefined(); }); - it('Stall tracking supports endTimestamp that is from the last span (trimEnd case)', (done) => { + it('Stall tracking supports endTimestamp that is from the last span (trimEnd case)', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -270,9 +270,7 @@ describe('StallTracking', () => { if (measurements) { expect(measurements.stall_count.value).toEqual(expect.any(Number)); - expect(measurements.stall_longest_time.value).toEqual( - expect.any(Number) - ); + expect(measurements.stall_longest_time.value).toEqual(expect.any(Number)); expect(measurements.stall_total_time.value).toEqual(expect.any(Number)); } @@ -280,7 +278,7 @@ describe('StallTracking', () => { }, 400); }); - it('Stall tracking rejects endTimestamp that is from the last span if trimEnd is false (trimEnd case)', (done) => { + it('Stall tracking rejects endTimestamp that is from the last span if trimEnd is false (trimEnd case)', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -320,7 +318,7 @@ describe('StallTracking', () => { }, 400); }); - it('Stall tracking rejects endTimestamp even if it is a span time (custom endTimestamp case)', (done) => { + it('Stall tracking rejects endTimestamp even if it is a span time (custom endTimestamp case)', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -391,7 +389,7 @@ describe('StallTracking', () => { await Promise.resolve(); jest.advanceTimersByTime(100); - stallTracking.onTransactionFinish(idleTransaction, + 0.015); + stallTracking.onTransactionFinish(idleTransaction, +0.015); idleTransaction.finish(); const measurements = getLastEvent()?.measurements; @@ -399,16 +397,14 @@ describe('StallTracking', () => { expect(measurements).toBeDefined(); expect(measurements?.stall_count.value).toEqual(expect.any(Number)); - expect(measurements?.stall_longest_time.value).toEqual( - expect.any(Number) - ); + expect(measurements?.stall_longest_time.value).toEqual(expect.any(Number)); expect(measurements?.stall_total_time.value).toEqual(expect.any(Number)); jest.runOnlyPendingTimers(); jest.useRealTimers(); }); - it('Stall tracking ignores unfinished spans in normal transactions', (done) => { + it('Stall tracking ignores unfinished spans in normal transactions', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -446,9 +442,7 @@ describe('StallTracking', () => { if (measurements) { expect(measurements.stall_count.value).toEqual(expect.any(Number)); - expect(measurements.stall_longest_time.value).toEqual( - expect.any(Number) - ); + expect(measurements.stall_longest_time.value).toEqual(expect.any(Number)); expect(measurements.stall_total_time.value).toEqual(expect.any(Number)); } @@ -456,7 +450,7 @@ describe('StallTracking', () => { }, 500); }); - it('Stall tracking only measures stalls inside the final time when trimEnd is used', (done) => { + it('Stall tracking only measures stalls inside the final time when trimEnd is used', done => { const stallTracking = new StallTrackingInstrumentation(); const transaction = new Transaction( @@ -489,9 +483,7 @@ describe('StallTracking', () => { if (measurements) { expect(measurements.stall_count.value).toEqual(1); - expect(measurements.stall_longest_time.value).toEqual( - expect.any(Number) - ); + expect(measurements.stall_longest_time.value).toEqual(expect.any(Number)); expect(measurements.stall_total_time.value).toEqual(expect.any(Number)); } @@ -533,7 +525,7 @@ describe('StallTracking', () => { const measurements1 = getLastEvent()?.measurements; expect(measurements1).toBeDefined(); - transactions.slice(2).forEach((transaction) => { + transactions.slice(2).forEach(transaction => { stallTracking.onTransactionFinish(transaction); transaction.finish(); }); diff --git a/test/utils/safe.test.ts b/test/utils/safe.test.ts index 40ef2454b8..a2e887122d 100644 --- a/test/utils/safe.test.ts +++ b/test/utils/safe.test.ts @@ -21,12 +21,14 @@ describe('safe', () => { expect(actualSafeFunction).not.toBeDefined(); }); test('passes object trough', () => { - const actualSafeFunction = safeFactory({ 'foo': 'bar' }); - expect(actualSafeFunction).toEqual({ 'foo': 'bar' }); + const actualSafeFunction = safeFactory({ foo: 'bar' }); + expect(actualSafeFunction).toEqual({ foo: 'bar' }); }); test('returns input object if function failed', () => { - const mockFn = jest.fn(() => { throw 'Test error' }); - const actualSafeFunction = safeFactory(<(foo:string) => string>mockFn); + const mockFn = jest.fn(() => { + throw 'Test error'; + }); + const actualSafeFunction = safeFactory(<(foo: string) => string>mockFn); const actualResult = actualSafeFunction('foo'); expect(mockFn).toBeCalledTimes(1); expect(actualResult).toEqual('foo'); @@ -52,7 +54,9 @@ describe('safe', () => { expect(actualSafeFunction).not.toBeDefined(); }); test('returns input object if function failed', () => { - const mockFn = jest.fn(() => { throw 'Test error' }); + const mockFn = jest.fn(() => { + throw 'Test error'; + }); const actualSafeFunction = safeTracesSampler(mockFn); const actualResult = actualSafeFunction?.({ transactionContext: { name: 'foo' } }); expect(mockFn).toBeCalledTimes(1); diff --git a/test/vendor/buffer/utf8ToBytes.test.ts b/test/vendor/buffer/utf8ToBytes.test.ts index 3d1f086a4d..0589ceb0da 100644 --- a/test/vendor/buffer/utf8ToBytes.test.ts +++ b/test/vendor/buffer/utf8ToBytes.test.ts @@ -8,7 +8,6 @@ import { utf8ToBytes } from '../../../src/js/vendor'; * License: MIT (https://github.com/LinusU/encode-utf8) */ describe('Buffer utf8 tests', () => { - const testCases = [ '゚・✿ヾ╲(。◕‿◕。)╱✿・゚', '𝌆', @@ -18,62 +17,62 @@ describe('Buffer utf8 tests', () => { 'Hello, World!', 'Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗', '𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌', - '사회과학원 어학연구소' + '사회과학원 어학연구소', ]; const badStrings = [ { input: 'abc123', expected: [0x61, 0x62, 0x63, 0x31, 0x32, 0x33], - name: 'Sanity check' + name: 'Sanity check', }, { input: '\uD800', expected: [0xef, 0xbf, 0xbd], - name: 'Surrogate half (low)' + name: 'Surrogate half (low)', }, { input: '\uDC00', expected: [0xef, 0xbf, 0xbd], - name: 'Surrogate half (high)' + name: 'Surrogate half (high)', }, { input: 'abc\uD800123', expected: [0x61, 0x62, 0x63, 0xef, 0xbf, 0xbd, 0x31, 0x32, 0x33], - name: 'Surrogate half (low), in a string' + name: 'Surrogate half (low), in a string', }, { input: 'abc\uDC00123', expected: [0x61, 0x62, 0x63, 0xef, 0xbf, 0xbd, 0x31, 0x32, 0x33], - name: 'Surrogate half (high), in a string' + name: 'Surrogate half (high), in a string', }, { input: '\uDC00\uD800', expected: [0xef, 0xbf, 0xbd, 0xef, 0xbf, 0xbd], - name: 'Wrong order' - } + name: 'Wrong order', + }, ]; describe('test strings', () => { for (const input of testCases) { it(`should encode "${input}"`, () => { // @ts-ignore The test run in node where Buffer is available - const actual = Buffer.from(utf8ToBytes(input)) + const actual = Buffer.from(utf8ToBytes(input)); // @ts-ignore The test run in node where Buffer is available - const expected = Buffer.from(input, 'utf8') + const expected = Buffer.from(input, 'utf8'); expect(actual).toEqual(expected); - }) + }); } - }) + }); describe('web platform test', () => { for (const testCase of badStrings) { it(testCase.name, () => { - const actual = Array.from(new Uint8Array(utf8ToBytes(testCase.input))) + const actual = Array.from(new Uint8Array(utf8ToBytes(testCase.input))); expect(actual).toEqual(testCase.expected); - }) + }); } - }) + }); }); diff --git a/test/vendor/buffer/utf8ToBytesSize.test.ts b/test/vendor/buffer/utf8ToBytesSize.test.ts index 14060c3142..9712fec885 100644 --- a/test/vendor/buffer/utf8ToBytesSize.test.ts +++ b/test/vendor/buffer/utf8ToBytesSize.test.ts @@ -1,9 +1,7 @@ import { utf8ToBytes } from '../../../src/js/vendor'; describe('Buffer utf8 tests - size', () => { - test('should return the correct size in bytes', () => { expect(utf8ToBytes('🥔').length).toEqual(4); }); - }); diff --git a/test/wrapper.test.ts b/test/wrapper.test.ts index c262985dd5..d71b9e6fbe 100644 --- a/test/wrapper.test.ts +++ b/test/wrapper.test.ts @@ -23,14 +23,14 @@ jest.mock( someContext: { someValue: 0, }, - }) + }), ), fetchNativeRelease: jest.fn(() => Promise.resolve({ build: '1.0.0.1', id: 'test-mock', version: '1.0.0', - }) + }), ), setContext: jest.fn(), setExtra: jest.fn(), @@ -38,7 +38,7 @@ jest.mock( setUser: jest.fn(() => { return; }), - initNativeSdk: jest.fn((options) => { + initNativeSdk: jest.fn(options => { initPayload = options; return Promise.resolve(true); @@ -58,7 +58,7 @@ jest.mock( }; }, /* virtual allows us to mock modules that aren't in package.json */ - { virtual: true } + { virtual: true }, ); const RNSentry = RN.NativeModules.RNSentry as Spec; @@ -77,15 +77,14 @@ const callAllScopeMethods = () => { id: 'setUser', }); NATIVE.setTag('key', 'value'); - NATIVE.setContext('key', - { - value: 'value', - data: { - map: { a: 1 }, - array: [1, 2, 3], - unique: 123, - }, - }); + NATIVE.setContext('key', { + value: 'value', + data: { + map: { a: 1 }, + array: [1, 2, 3], + unique: 123, + }, + }); NATIVE.setExtra('key', 'value'); }; @@ -113,7 +112,7 @@ describe('Tests Native Wrapper', () => { expect(RNSentry.initNativeSdk).not.toBeCalled(); expect(logger.warn).toHaveBeenLastCalledWith( - 'Warning: No DSN was provided. The Sentry SDK will be disabled. Native SDK will also not be initalized.' + 'Warning: No DSN was provided. The Sentry SDK will be disabled. Native SDK will also not be initalized.', ); }); @@ -128,9 +127,7 @@ describe('Tests Native Wrapper', () => { expect(RNSentry.initNativeSdk).not.toBeCalled(); expect(NATIVE.enableNative).toBe(false); - expect(logger.warn).toHaveBeenLastCalledWith( - 'Note: Native Sentry SDK is disabled.' - ); + expect(logger.warn).toHaveBeenLastCalledWith('Note: Native Sentry SDK is disabled.'); }); test('does not initialize with autoInitializeNativeSdk: false', async () => { @@ -160,7 +157,7 @@ describe('Tests Native Wrapper', () => { { id: 'setUser', }, - {} + {}, ); expect(RNSentry.setTag).toBeCalledWith('key', 'value'); expect(RNSentry.setContext).toBeCalledWith('key', { @@ -215,9 +212,10 @@ describe('Tests Native Wrapper', () => { await NATIVE.sendEnvelope(env); expect(RNSentry.captureEnvelope).toBeCalledWith( - utf8ToBytes('{"event_id":"event0","sent_at":"123"}\n' - + '{"type":"event","content_type":"application/json","length":87}\n' - + '{"event_id":"event0","message":"test","sdk":{"name":"test-sdk-name","version":"2.1.3"}}\n' + utf8ToBytes( + '{"event_id":"event0","sent_at":"123"}\n' + + '{"type":"event","content_type":"application/json","length":87}\n' + + '{"event_id":"event0","message":"test","sdk":{"name":"test-sdk-name","version":"2.1.3"}}\n', ), { store: false }, ); @@ -244,9 +242,10 @@ describe('Tests Native Wrapper', () => { await NATIVE.sendEnvelope(env); expect(RNSentry.captureEnvelope).toBeCalledWith( - utf8ToBytes('{"event_id":"event0","sent_at":"123"}\n' - + '{"type":"event","content_type":"application/json","length":93}\n' - + '{"event_id":"event0","sdk":{"name":"test-sdk-name","version":"2.1.3"},"instance":{"value":0}}\n' + utf8ToBytes( + '{"event_id":"event0","sent_at":"123"}\n' + + '{"type":"event","content_type":"application/json","length":93}\n' + + '{"event_id":"event0","sdk":{"name":"test-sdk-name","version":"2.1.3"},"instance":{"value":0}}\n', ), { store: false }, ); @@ -257,7 +256,6 @@ describe('Tests Native Wrapper', () => { // @ts-ignore for testing, does not accept an empty class. await NATIVE.sendEnvelope({}); - } catch (error) { // @ts-ignore it is an error but it does not know the type. expect(error.message).toMatch('Native is disabled'); @@ -279,9 +277,10 @@ describe('Tests Native Wrapper', () => { await NATIVE.sendEnvelope(env); expect(RNSentry.captureEnvelope).toBeCalledWith( - utf8ToBytes('{"event_id":"event0","sent_at":"123"}\n' - + '{"type":"event","content_type":"application/json","length":50}\n' - + '{"event_id":"event0","message":{"message":"test"}}\n' + utf8ToBytes( + '{"event_id":"event0","sent_at":"123"}\n' + + '{"type":"event","content_type":"application/json","length":50}\n' + + '{"event_id":"event0","message":{"message":"test"}}\n', ), { store: false }, ); @@ -315,9 +314,10 @@ describe('Tests Native Wrapper', () => { await NATIVE.sendEnvelope(env); expect(RNSentry.captureEnvelope).toBeCalledWith( - utf8ToBytes('{"event_id":"event0","sent_at":"123"}\n' - + '{"type":"event","content_type":"application/json","length":104}\n' - + '{"event_id":"event0","exception":{"values":[{"mechanism":{"handled":true,"type":""}}]},"breadcrumbs":[]}\n' + utf8ToBytes( + '{"event_id":"event0","sent_at":"123"}\n' + + '{"type":"event","content_type":"application/json","length":104}\n' + + '{"event_id":"event0","exception":{"values":[{"mechanism":{"handled":true,"type":""}}]},"breadcrumbs":[]}\n', ), { store: false }, ); @@ -341,9 +341,10 @@ describe('Tests Native Wrapper', () => { await NATIVE.sendEnvelope(env); expect(RNSentry.captureEnvelope).toBeCalledWith( - utf8ToBytes('{"event_id":"event0","sent_at":"123"}\n' - + '{"type":"event","content_type":"application/json","length":38}\n' - + '{"event_id":"event0","breadcrumbs":[]}\n' + utf8ToBytes( + '{"event_id":"event0","sent_at":"123"}\n' + + '{"type":"event","content_type":"application/json","length":38}\n' + + '{"event_id":"event0","breadcrumbs":[]}\n', ), { store: false }, ); @@ -377,9 +378,10 @@ describe('Tests Native Wrapper', () => { await NATIVE.sendEnvelope(env); expect(RNSentry.captureEnvelope).toBeCalledWith( - utf8ToBytes('{"event_id":"event0","sent_at":"123"}\n' - + '{"type":"event","content_type":"application/json","length":125}\n' - + '{"event_id":"event0","exception":{"values":[{"mechanism":{"handled":false,"type":""}}]},"breadcrumbs":[{"message":"crumb!"}]}\n' + utf8ToBytes( + '{"event_id":"event0","sent_at":"123"}\n' + + '{"type":"event","content_type":"application/json","length":125}\n' + + '{"event_id":"event0","exception":{"values":[{"mechanism":{"handled":false,"type":""}}]},"breadcrumbs":[{"message":"crumb!"}]}\n', ), { store: true }, ); @@ -411,9 +413,7 @@ describe('Tests Native Wrapper', () => { test('returns empty object on android', async () => { NATIVE.platform = 'android'; - await expect(NATIVE.fetchNativeDeviceContexts()).resolves.toMatchObject( - {} - ); + await expect(NATIVE.fetchNativeDeviceContexts()).resolves.toMatchObject({}); expect(RNSentry.fetchNativeDeviceContexts).not.toBeCalled(); }); @@ -455,7 +455,7 @@ describe('Tests Native Wrapper', () => { }, { unique: '123', - } + }, ); }); @@ -468,7 +468,7 @@ describe('Tests Native Wrapper', () => { { id: 'Hello', }, - {} + {}, ); }); }); From d0bf49472b8e02ea40eab48e2e861b603450233e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Wold=C5=99ich?= <31292499+krystofwoldrich@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:00:16 +0200 Subject: [PATCH 2/2] chore(vendor): Update license and attribution style (#2949) --- src/js/vendor/buffer/LICENSE | 23 ------------------- src/js/vendor/buffer/utf8ToBytes.ts | 29 +++++++++++++++++++----- test/vendor/buffer/utf8ToBytes.test.ts | 31 ++++++++++++++++++++------ 3 files changed, 48 insertions(+), 35 deletions(-) delete mode 100644 src/js/vendor/buffer/LICENSE diff --git a/src/js/vendor/buffer/LICENSE b/src/js/vendor/buffer/LICENSE deleted file mode 100644 index 1cd6eec5ff..0000000000 --- a/src/js/vendor/buffer/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -# From: https://github.com/feross/buffer/blob/795bbb5bda1b39f1370ebd784bea6107b087e3a7/LICENSE - -The MIT License (MIT) - -Copyright (c) Feross Aboukhadijeh, and other contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/js/vendor/buffer/utf8ToBytes.ts b/src/js/vendor/buffer/utf8ToBytes.ts index e7d77bc530..a8a743f483 100644 --- a/src/js/vendor/buffer/utf8ToBytes.ts +++ b/src/js/vendor/buffer/utf8ToBytes.ts @@ -1,12 +1,31 @@ +// Adapted from https://github.com/feross/buffer/blob/795bbb5bda1b39f1370ebd784bea6107b087e3a7/index.js#L1956 + +// The MIT License (MIT) + +// Copyright (c) Feross Aboukhadijeh, and other contributors. + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + /* eslint-disable */ /** * Convert a string to a byte array - * - * This is a utf8ToBytes function from the buffer module (with added types) - * https://github.com/feross/buffer/blob/795bbb5bda1b39f1370ebd784bea6107b087e3a7/index.js#L1956 - * - * License: MIT (https://github.com/feross/buffer) */ export function utf8ToBytes(string: string, units?: number): number[] { units = units || Infinity; diff --git a/test/vendor/buffer/utf8ToBytes.test.ts b/test/vendor/buffer/utf8ToBytes.test.ts index 0589ceb0da..ff7b82f0a0 100644 --- a/test/vendor/buffer/utf8ToBytes.test.ts +++ b/test/vendor/buffer/utf8ToBytes.test.ts @@ -1,12 +1,29 @@ +// Adapted from https://github.com/feross/buffer/blob/795bbb5bda1b39f1370ebd784bea6107b087e3a7/index.js#L1956 + +// The MIT License (MIT) + +// Copyright (c) Feross Aboukhadijeh, and other contributors. + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + import { utf8ToBytes } from '../../../src/js/vendor'; -/** - * These test are taken over from encode-utf8 library to test the utf8ToBytes function - * - * https://github.com/LinusU/encode-utf8/blob/9c112ab99827e07667f9a349ca5498157479f68e/test.js - * - * License: MIT (https://github.com/LinusU/encode-utf8) - */ describe('Buffer utf8 tests', () => { const testCases = [ '゚・✿ヾ╲(。◕‿◕。)╱✿・゚',