1
1
import type { Span } from '@sentry/core' ;
2
2
import { getActiveSpan , getCurrentScope , spanToJSON , startSpanManual } from '@sentry/core' ;
3
- import type { AppState , AppStateStatus } from 'react-native' ;
3
+ import type { AppStateStatus } from 'react-native' ;
4
+ import { AppState } from 'react-native' ;
4
5
import type { ScopeWithMaybeSpan } from '../../src/js/tracing/span' ;
5
6
import { SCOPE_SPAN_FIELD , startIdleNavigationSpan } from '../../src/js/tracing/span' ;
6
7
import { NATIVE } from '../../src/js/wrapper' ;
@@ -11,36 +12,39 @@ type MockAppState = {
11
12
listener : ( newState : AppStateStatus ) => void ;
12
13
removeSubscription : jest . Func ;
13
14
} ;
14
- const mockedAppState : AppState & MockAppState = {
15
- removeSubscription : jest . fn ( ) ,
16
- listener : jest . fn ( ) ,
17
- isAvailable : true ,
18
- currentState : 'active' ,
19
- addEventListener : ( _ , listener ) => {
20
- mockedAppState . listener = listener ;
21
- return {
22
- remove : mockedAppState . removeSubscription ,
23
- } ;
24
- } ,
25
- setState : ( state : AppStateStatus ) => {
26
- mockedAppState . currentState = state ;
27
- mockedAppState . listener ( state ) ;
28
- } ,
29
- } ;
30
- jest . mock ( 'react-native/Libraries/AppState/AppState' , ( ) => mockedAppState ) ;
15
+ jest . mock ( 'react-native' , ( ) => {
16
+ const mockedAppState : AppState & MockAppState = {
17
+ removeSubscription : jest . fn ( ) ,
18
+ listener : jest . fn ( ) ,
19
+ isAvailable : true ,
20
+ currentState : 'active' ,
21
+ addEventListener : jest . fn ( ) ,
22
+ setState : ( state : AppStateStatus ) => {
23
+ mockedAppState . currentState = state ;
24
+ mockedAppState . listener ( state ) ;
25
+ } ,
26
+ } ;
27
+ return {
28
+ AppState : mockedAppState ,
29
+ Platform : { OS : 'ios' } ,
30
+ NativeModules : {
31
+ RNSentry : { }
32
+ }
33
+ } ;
34
+ } ) ;
35
+
36
+ const mockedAppState = AppState as jest . Mocked < typeof AppState & MockAppState > ;
31
37
32
38
describe ( 'startIdleNavigationSpan' , ( ) => {
33
39
beforeEach ( ( ) => {
34
40
jest . useFakeTimers ( ) ;
35
41
NATIVE . enableNative = true ;
36
42
mockedAppState . isAvailable = true ;
37
43
mockedAppState . currentState = 'active' ;
38
- mockedAppState . addEventListener = ( _ , listener ) => {
44
+ ( mockedAppState . addEventListener as jest . Mock ) . mockImplementation ( ( _ , listener ) => {
39
45
mockedAppState . listener = listener ;
40
- return {
41
- remove : mockedAppState . removeSubscription ,
42
- } ;
43
- } ;
46
+ return { remove : mockedAppState . removeSubscription } ;
47
+ } ) ;
44
48
setupTestClient ( ) ;
45
49
} ) ;
46
50
@@ -66,9 +70,9 @@ describe('startIdleNavigationSpan', () => {
66
70
67
71
it ( 'Does not crash when AppState is not available' , async ( ) => {
68
72
mockedAppState . isAvailable = false ;
69
- mockedAppState . addEventListener = ( ( ) : void => {
73
+ ( mockedAppState . addEventListener as jest . Mock ) . mockImplementation ( ( ) => {
70
74
return undefined ;
71
- } ) as unknown as ( typeof mockedAppState ) [ 'addEventListener' ] ; // RN Web can return undefined
75
+ } ) ;
72
76
73
77
startIdleNavigationSpan ( {
74
78
name : 'test' ,
@@ -94,7 +98,7 @@ describe('startIdleNavigationSpan', () => {
94
98
95
99
// Verify it's a non-recording span
96
100
expect ( span ) . toBeDefined ( ) ;
97
- expect ( span . constructor . name ) . toBe ( 'SentryNonRecordingSpan' ) ;
101
+ expect ( span ? .constructor . name ) . toBe ( 'SentryNonRecordingSpan' ) ;
98
102
99
103
// No AppState listener should be set up for non-recording spans
100
104
expect ( mockedAppState . removeSubscription ) . not . toHaveBeenCalled ( ) ;
@@ -140,7 +144,7 @@ describe('startIdleNavigationSpan', () => {
140
144
name : 'test' ,
141
145
} ) ;
142
146
143
- firstSpan . end ( ) ;
147
+ firstSpan ? .end ( ) ;
144
148
145
149
const secondSpan = startIdleNavigationSpan ( {
146
150
name : 'test' ,
0 commit comments