-
-
Notifications
You must be signed in to change notification settings - Fork 360
Expand file tree
/
Copy pathintegrationsexecutionorder.test.ts
More file actions
124 lines (94 loc) · 4.51 KB
/
integrationsexecutionorder.test.ts
File metadata and controls
124 lines (94 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import * as mockWrapper from '../mockWrapper';
jest.mock('../../src/js/wrapper', () => mockWrapper);
jest.mock('../../src/js/utils/environment');
import type { Integration } from '@sentry/core';
import { defaultStackParser } from '@sentry/browser';
import type { ReactNativeClientOptions } from '../../src/js/options';
import { ReactNativeClient } from '../../src/js/client';
import { getDefaultIntegrations } from '../../src/js/integrations/default';
import { isHermesEnabled, notWeb } from '../../src/js/utils/environment';
import { MOCK_DSN } from '../mockDsn';
describe('Integration execution order', () => {
describe('mobile hermes', () => {
beforeEach(() => {
(notWeb as jest.Mock).mockReturnValue(true);
(isHermesEnabled as jest.Mock).mockReturnValue(true);
});
it('NativeLinkedErrors is before RewriteFrames', async () => {
// NativeLinkedErrors has to process event before RewriteFrames
// otherwise the linked errors stack trace frames won't be rewritten
// DebugSymbolicator has to be called after RewriteFrames
// otherwise symbolicated stack will be overwritten by the RewriteFrames
// which will cause difference between Debug and Release builds where symbolication is done on Sentry Server
const client = createTestClient();
const { integrations } = client.getOptions();
const nativeLinkedErrors = spyOnIntegrationById('NativeLinkedErrors', integrations);
const rewriteFrames = spyOnIntegrationById('RewriteFrames', integrations);
const debugSymbolicator = spyOnIntegrationById('DebugSymbolicator', integrations);
client.init();
client.captureException(new Error('test'));
await client.flush();
expect(nativeLinkedErrors.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!);
expect(rewriteFrames.processEvent!).toHaveBeenCalledBefore(debugSymbolicator.processEvent!);
});
it('NativeStackRecovery is before RewriteFrames', async () => {
// NativeStackRecovery has to process event before RewriteFrames
// otherwise recovered stack trace frames won't be rewritten
const client = createTestClient();
const { integrations } = client.getOptions();
const nativeStackRecovery = spyOnIntegrationById('NativeStackRecovery', integrations);
const rewriteFrames = spyOnIntegrationById('RewriteFrames', integrations);
client.init();
client.captureException(new Error('test'));
await client.flush();
expect(nativeStackRecovery.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!);
});
});
describe('web', () => {
beforeEach(() => {
(notWeb as jest.Mock).mockReturnValue(false);
(isHermesEnabled as jest.Mock).mockReturnValue(false);
});
it('LinkedErrors is before RewriteFrames', async () => {
// LinkedErrors has to process event before RewriteFrames
// otherwise the linked errors stack trace frames won't be rewritten
const client = createTestClient();
const { integrations } = client.getOptions();
const linkedErrors = spyOnIntegrationById('LinkedErrors', integrations);
const rewriteFrames = spyOnIntegrationById('RewriteFrames', integrations);
client.init();
client.captureException(new Error('test'));
await client.flush();
expect(linkedErrors.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!);
});
});
});
interface IntegrationSpy {
name: string;
setupOnce?: Integration['setupOnce'] & jest.Mock;
preprocessEvent?: Integration['preprocessEvent'] & jest.Mock;
processEvent?: Integration['processEvent'] & jest.Mock;
}
function spyOnIntegrationById(id: string, integrations: Integration[]): IntegrationSpy {
const candidate = integrations?.find(integration => integration.name === id);
if (!candidate) {
throw new Error(`Integration ${id} not found`);
}
candidate.setupOnce && jest.spyOn(candidate, 'setupOnce');
candidate.preprocessEvent && jest.spyOn(candidate, 'preprocessEvent');
candidate.processEvent && jest.spyOn(candidate, 'processEvent');
return candidate as IntegrationSpy;
}
function createTestClient(): ReactNativeClient {
const clientOptions: ReactNativeClientOptions = {
dsn: MOCK_DSN,
transport: () => ({
send: jest.fn().mockResolvedValue(undefined),
flush: jest.fn().mockResolvedValue(true),
}),
stackParser: defaultStackParser,
integrations: [],
};
clientOptions.integrations = getDefaultIntegrations(clientOptions);
return new ReactNativeClient(clientOptions);
}