11/* eslint-disable deprecation/deprecation */
22/* eslint-disable @typescript-eslint/no-explicit-any */
33import { getCurrentScope , getGlobalScope , getIsolationScope , SentrySpan , setCurrentClient } from '@sentry/core' ;
4- import type { StartSpanOptions } from '@sentry/types' ;
4+ import type { Event , Measurements , StartSpanOptions } from '@sentry/types' ;
55
6- import { reactNativeTracingIntegration } from '../../src/js' ;
6+ import { nativeFramesIntegration , reactNativeTracingIntegration } from '../../src/js' ;
77import { DEFAULT_NAVIGATION_SPAN_NAME } from '../../src/js/tracing/reactnativetracing' ;
88import type { NavigationRoute } from '../../src/js/tracing/reactnavigation' ;
99import { ReactNavigationInstrumentation } from '../../src/js/tracing/reactnavigation' ;
@@ -21,13 +21,15 @@ import {
2121} from '../../src/js/tracing/semanticAttributes' ;
2222import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide' ;
2323import { getDefaultTestClientOptions , TestClient } from '../mocks/client' ;
24+ import { NATIVE } from '../mockWrapper' ;
2425import { createMockNavigationAndAttachTo } from './reactnavigationutils' ;
2526
2627const dummyRoute = {
2728 name : 'Route' ,
2829 key : '0' ,
2930} ;
3031
32+ jest . mock ( '../../src/js/wrapper.ts' , ( ) => jest . requireActual ( '../mockWrapper.ts' ) ) ;
3133jest . useFakeTimers ( { advanceTimers : true } ) ;
3234
3335class MockNavigationContainer {
@@ -82,6 +84,85 @@ describe('ReactNavigationInstrumentation', () => {
8284 ) ;
8385 } ) ;
8486
87+ describe ( 'initial navigation span is created after all integrations are setup' , ( ) => {
88+ let rnTracing : ReturnType < typeof reactNativeTracingIntegration > ;
89+
90+ beforeEach ( ( ) => {
91+ const startFrames = {
92+ totalFrames : 100 ,
93+ slowFrames : 20 ,
94+ frozenFrames : 5 ,
95+ } ;
96+ const finishFrames = {
97+ totalFrames : 200 ,
98+ slowFrames : 40 ,
99+ frozenFrames : 10 ,
100+ } ;
101+ NATIVE . fetchNativeFrames . mockResolvedValueOnce ( startFrames ) . mockResolvedValueOnce ( finishFrames ) ;
102+
103+ const rNavigation = new ReactNavigationInstrumentation ( {
104+ routeChangeTimeoutMs : 200 ,
105+ } ) ;
106+ mockNavigation = createMockNavigationAndAttachTo ( rNavigation ) ;
107+
108+ rnTracing = reactNativeTracingIntegration ( {
109+ routingInstrumentation : rNavigation ,
110+ } ) ;
111+ } ) ;
112+
113+ test ( 'initial navigation span contains native frames when nativeFrames integration is after react native tracing' , async ( ) => {
114+ const options = getDefaultTestClientOptions ( {
115+ enableNativeFramesTracking : true ,
116+ enableStallTracking : false ,
117+ tracesSampleRate : 1.0 ,
118+ integrations : [ rnTracing , nativeFramesIntegration ( ) ] ,
119+ enableAppStartTracking : false ,
120+ } ) ;
121+ client = new TestClient ( options ) ;
122+ setCurrentClient ( client ) ;
123+ client . init ( ) ;
124+
125+ // Flush the init transaction, must be async to allow for the native start frames to be fetched
126+ await jest . runOnlyPendingTimersAsync ( ) ;
127+ await client . flush ( ) ;
128+
129+ expectInitNavigationSpanWithNativeFrames ( client . event ) ;
130+ } ) ;
131+
132+ test ( 'initial navigation span contains native frames when nativeFrames integration is before react native tracing' , async ( ) => {
133+ const options = getDefaultTestClientOptions ( {
134+ enableNativeFramesTracking : true ,
135+ enableStallTracking : false ,
136+ tracesSampleRate : 1.0 ,
137+ integrations : [ nativeFramesIntegration ( ) , rnTracing ] ,
138+ enableAppStartTracking : false ,
139+ } ) ;
140+ client = new TestClient ( options ) ;
141+ setCurrentClient ( client ) ;
142+ client . init ( ) ;
143+
144+ // Flush the init transaction, must be async to allow for the native start frames to be fetched
145+ await jest . runOnlyPendingTimersAsync ( ) ;
146+ await client . flush ( ) ;
147+
148+ expectInitNavigationSpanWithNativeFrames ( client . event ) ;
149+ } ) ;
150+
151+ function expectInitNavigationSpanWithNativeFrames ( event : Event ) : void {
152+ expect ( event ) . toEqual (
153+ expect . objectContaining < Event > ( {
154+ type : 'transaction' ,
155+ transaction : 'Initial Screen' ,
156+ measurements : expect . objectContaining < Measurements > ( {
157+ frames_total : expect . toBeObject ( ) ,
158+ frames_slow : expect . toBeObject ( ) ,
159+ frames_frozen : expect . toBeObject ( ) ,
160+ } ) ,
161+ } ) ,
162+ ) ;
163+ }
164+ } ) ;
165+
85166 test ( 'transaction sent on navigation' , async ( ) => {
86167 setupTestClient ( ) ;
87168 jest . runOnlyPendingTimers ( ) ; // Flush the init transaction
0 commit comments