Skip to content

Commit a76d821

Browse files
fix(tests): Flaky tests depending on execution order (client, stalltracking) (#3232)
1 parent 538cedb commit a76d821

16 files changed

+675
-627
lines changed

.eslintrc.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,15 @@ module.exports = {
1212
settings: {
1313
version: 'detect', // React version. "detect" automatically picks the version you have installed.
1414
},
15-
ignorePatterns: [
16-
'test/react-native/versions/**/*',
17-
'coverage/**/*',
18-
'test/typescript/**/*',
19-
],
15+
ignorePatterns: ['test/react-native/versions/**/*', 'coverage/**/*', 'test/typescript/**/*'],
2016
overrides: [
2117
{
2218
// Typescript Files
2319
files: ['*.ts', '*.tsx'],
2420
extends: ['plugin:react/recommended'],
2521
plugins: ['react', 'react-native'],
2622
rules: {
27-
'@typescript-eslint/typedef': [
28-
'error',
29-
{ arrowParameter: false, variableDeclarationIgnoreFunction: true },
30-
],
23+
'@typescript-eslint/typedef': ['error', { arrowParameter: false, variableDeclarationIgnoreFunction: true }],
3124
},
3225
},
3326
{
@@ -37,6 +30,7 @@ module.exports = {
3730
'@typescript-eslint/no-var-requires': 'off',
3831
'@typescript-eslint/no-empty-function': 'off',
3932
'@typescript-eslint/no-explicit-any': 'off',
33+
'@typescript-eslint/unbound-method': 'off',
4034
},
4135
},
4236
{
@@ -55,7 +49,7 @@ module.exports = {
5549
parserOptions: {
5650
ecmaVersion: 2017,
5751
},
58-
}
52+
},
5953
],
6054
rules: {
6155
// Bundle size isn't too much of an issue for React Native.

package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,21 @@
7070
"@sentry-internal/eslint-plugin-sdk": "7.61.0",
7171
"@sentry/typescript": "^5.20.1",
7272
"@sentry/wizard": "3.9.1",
73-
"@types/jest": "^29.2.5",
73+
"@types/jest": "^29.5.3",
7474
"@types/react": "^18.2.14",
75-
"babel-jest": "^29.3.1",
75+
"babel-jest": "^29.6.2",
7676
"downlevel-dts": "^0.11.0",
7777
"eslint": "^7.6.0",
7878
"eslint-plugin-react": "^7.20.6",
7979
"eslint-plugin-react-native": "^3.8.1",
80-
"jest": "^29.3.1",
81-
"jest-environment-jsdom": "^29.4.1",
80+
"jest": "^29.6.2",
81+
"jest-environment-jsdom": "^29.6.2",
8282
"prettier": "^2.0.5",
8383
"react": "18.2.0",
8484
"react-native": "0.72.3",
8585
"replace-in-file": "^7.0.1",
8686
"rimraf": "^4.1.1",
87-
"ts-jest": "^29.0.5",
87+
"ts-jest": "^29.1.1",
8888
"typescript": "4.1.3"
8989
},
9090
"rnpm": {
@@ -98,6 +98,9 @@
9898
"jest": {
9999
"collectCoverage": true,
100100
"preset": "react-native",
101+
"setupFilesAfterEnv": [
102+
"<rootDir>/test/mockConsole.ts"
103+
],
101104
"globals": {
102105
"__DEV__": true,
103106
"ts-jest": {
@@ -111,7 +114,8 @@
111114
"js"
112115
],
113116
"testPathIgnorePatterns": [
114-
"<rootDir>/test/e2e/"
117+
"<rootDir>/test/e2e/",
118+
"<rootDir>/test/react-native/versions"
115119
],
116120
"testEnvironment": "node",
117121
"testMatch": [

test/client.test.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import {
2121
getSyncPromiseRejectOnFirstCall,
2222
} from './testutils';
2323

24-
const EXAMPLE_DSN = 'https://[email protected]/148053';
25-
2624
interface MockedReactNative {
2725
NativeModules: {
2826
RNSentry: {
@@ -74,10 +72,10 @@ jest.mock(
7472
alert: jest.fn(),
7573
},
7674
}),
77-
/* virtual allows us to mock modules that aren't in package.json */
78-
{ virtual: true },
7975
);
8076

77+
const EXAMPLE_DSN = 'https://[email protected]/148053';
78+
8179
const DEFAULT_OPTIONS: ReactNativeClientOptions = {
8280
enableNative: true,
8381
enableNativeCrashHandling: true,
@@ -94,11 +92,6 @@ const DEFAULT_OPTIONS: ReactNativeClientOptions = {
9492
stackParser: jest.fn().mockReturnValue([]),
9593
};
9694

97-
afterEach(() => {
98-
jest.clearAllMocks();
99-
NATIVE.enableNative = true;
100-
});
101-
10295
describe('Tests ReactNativeClient', () => {
10396
describe('initializing the client', () => {
10497
test('client initializes', async () => {
@@ -110,7 +103,6 @@ describe('Tests ReactNativeClient', () => {
110103

111104
await expect(client.eventFromMessage('test')).resolves.toBeDefined();
112105
// @ts-ignore: Is Mocked
113-
// eslint-disable-next-line @typescript-eslint/unbound-method
114106
await expect(RN.LogBox.ignoreLogs).toBeCalled();
115107
});
116108

@@ -150,9 +142,7 @@ describe('Tests ReactNativeClient', () => {
150142
dsn: EXAMPLE_DSN,
151143
transport: myCustomTransportFn,
152144
});
153-
// eslint-disable-next-line @typescript-eslint/unbound-method
154145
expect(client.getTransport()?.flush).toBe(myFlush);
155-
// eslint-disable-next-line @typescript-eslint/unbound-method
156146
expect(client.getTransport()?.send).toBe(mySend);
157147
});
158148
});
@@ -212,6 +202,7 @@ describe('Tests ReactNativeClient', () => {
212202

213203
describe('nativeCrash', () => {
214204
test('calls NativeModules crash', () => {
205+
NATIVE.enableNative = true;
215206
const RN: MockedReactNative = require('react-native');
216207

217208
const client = new ReactNativeClient({

test/e2e/test/e2e.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,23 @@ beforeAll(async () => {
9696
}
9797
});
9898

99-
afterAll(async () => {
100-
await driver?.deleteSession();
101-
});
99+
describe('End to end tests for common events', () => {
100+
afterAll(async () => {
101+
await driver?.deleteSession();
102+
});
102103

103-
beforeEach(async () => {
104-
const element = await getElement('clearEventId');
105-
await element.click();
106-
await waitUntilEventIdIsEmpty();
107-
});
104+
beforeEach(async () => {
105+
const element = await getElement('clearEventId');
106+
await element.click();
107+
await waitUntilEventIdIsEmpty();
108+
});
108109

109-
afterEach(async () => {
110-
const testName = expect.getState().currentTestName;
111-
const fileName = `screen-${testName}.png`.replace(/[^0-9a-zA-Z-+.]/g, '_');
112-
await driver?.saveScreenshot(fileName);
113-
});
110+
afterEach(async () => {
111+
const testName = expect.getState().currentTestName;
112+
const fileName = `screen-${testName}.png`.replace(/[^0-9a-zA-Z-+.]/g, '_');
113+
await driver?.saveScreenshot(fileName);
114+
});
114115

115-
describe('End to end tests for common events', () => {
116116
test('captureMessage', async () => {
117117
const element = await getElement('captureMessage');
118118
await element.click();

test/integrations/reactnativeerrorhandlers.test.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ import type { Event, EventHint, SeverityLevel } from '@sentry/types';
4949

5050
import { ReactNativeErrorHandlers } from '../../src/js/integrations/reactnativeerrorhandlers';
5151

52-
beforeEach(() => {
53-
ErrorUtils.getGlobalHandler = () => jest.fn();
54-
});
52+
describe('ReactNativeErrorHandlers', () => {
53+
beforeEach(() => {
54+
ErrorUtils.getGlobalHandler = () => jest.fn();
55+
});
5556

56-
afterEach(() => {
57-
jest.clearAllMocks();
58-
});
57+
afterEach(() => {
58+
jest.clearAllMocks();
59+
});
5960

60-
describe('ReactNativeErrorHandlers', () => {
6161
describe('onError', () => {
6262
let errorHandlerCallback: (error: Error, isFatal: boolean) => Promise<void>;
6363

@@ -107,7 +107,6 @@ describe('ReactNativeErrorHandlers', () => {
107107

108108
function getActualCaptureEventArgs() {
109109
const hub = getCurrentHub();
110-
// eslint-disable-next-line @typescript-eslint/unbound-method
111110
const mockCall = (hub.captureEvent as jest.MockedFunction<typeof hub.captureEvent>).mock.calls[0];
112111

113112
return mockCall;

test/integrations/sdkinfo.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ jest.mock('../../src/js/wrapper', () => {
2828
};
2929
});
3030

31-
afterEach(() => {
32-
NATIVE.platform = 'ios';
33-
});
34-
3531
describe('Sdk Info', () => {
32+
afterEach(() => {
33+
NATIVE.platform = 'ios';
34+
});
35+
3636
it('Adds native package and javascript platform to event on iOS', async () => {
3737
mockedFetchNativeSdkInfo = jest.fn().mockResolvedValue(mockCocoaPackage);
3838
const mockEvent: Event = {};

test/mockConsole.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
global.console = {
2+
...console,
3+
log: jest.fn(),
4+
debug: jest.fn(),
5+
info: jest.fn(),
6+
warn: jest.fn(),
7+
error: jest.fn(),
8+
};

test/scope.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// eslint-disable @typescript-eslint/unbound-method
21
import type { Breadcrumb } from '@sentry/types';
32

43
import { ReactNativeScope } from '../src/js/scope';

test/sdk.test.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ const usedOptions = (): ClientOptions<BaseTransportOptions> | undefined => {
8282
return mockedInitAndBind.mock.calls[0]?.[1];
8383
};
8484

85-
afterEach(() => {
86-
jest.clearAllMocks();
87-
});
88-
8985
describe('Tests the SDK functionality', () => {
86+
afterEach(() => {
87+
jest.clearAllMocks();
88+
});
89+
9090
describe('init', () => {
9191
describe('enableAutoPerformanceTracing', () => {
9292
const usedOptions = (): Integration[] => {
@@ -163,7 +163,6 @@ describe('Tests the SDK functionality', () => {
163163
if (mockClient) {
164164
const flushResult = await flush();
165165

166-
// eslint-disable-next-line @typescript-eslint/unbound-method
167166
expect(mockClient.flush).toBeCalled();
168167
expect(flushResult).toBe(true);
169168
}
@@ -178,10 +177,8 @@ describe('Tests the SDK functionality', () => {
178177

179178
const flushResult = await flush();
180179

181-
// eslint-disable-next-line @typescript-eslint/unbound-method
182180
expect(mockClient.flush).toBeCalled();
183181
expect(flushResult).toBe(false);
184-
// eslint-disable-next-line @typescript-eslint/unbound-method
185182
expect(logger.error).toBeCalledWith('Failed to flush the event queue.');
186183
}
187184
});
@@ -219,7 +216,6 @@ describe('Tests the SDK functionality', () => {
219216
it('fetchTransport set and enableNative set to false', () => {
220217
(NATIVE.isNativeAvailable as jest.Mock).mockImplementation(() => false);
221218
init({});
222-
// eslint-disable-next-line @typescript-eslint/unbound-method
223219
expect(NATIVE.isNativeAvailable).toBeCalled();
224220
// @ts-ignore enableNative not publicly available here.
225221
expect(usedOptions()?.enableNative).toEqual(false);
@@ -229,7 +225,6 @@ describe('Tests the SDK functionality', () => {
229225
it('fetchTransport set and passed enableNative ignored when true', () => {
230226
(NATIVE.isNativeAvailable as jest.Mock).mockImplementation(() => false);
231227
init({ enableNative: true });
232-
// eslint-disable-next-line @typescript-eslint/unbound-method
233228
expect(NATIVE.isNativeAvailable).toBeCalled();
234229
// @ts-ignore enableNative not publicly available here.
235230
expect(usedOptions()?.enableNative).toEqual(false);
@@ -239,7 +234,6 @@ describe('Tests the SDK functionality', () => {
239234
it('fetchTransport set and isNativeAvailable not called when passed enableNative set to false', () => {
240235
(NATIVE.isNativeAvailable as jest.Mock).mockImplementation(() => false);
241236
init({ enableNative: false });
242-
// eslint-disable-next-line @typescript-eslint/unbound-method
243237
expect(NATIVE.isNativeAvailable).not.toBeCalled();
244238
// @ts-ignore enableNative not publicly available here.
245239
expect(usedOptions()?.enableNative).toEqual(false);
@@ -253,7 +247,6 @@ describe('Tests the SDK functionality', () => {
253247
transport: mockTransport,
254248
});
255249
expect(usedOptions()?.transport).toEqual(mockTransport);
256-
// eslint-disable-next-line @typescript-eslint/unbound-method
257250
expect(NATIVE.isNativeAvailable).toBeCalled();
258251
// @ts-ignore enableNative not publicly available here.
259252
expect(usedOptions()?.enableNative).toEqual(false);
@@ -284,15 +277,13 @@ describe('Tests the SDK functionality', () => {
284277
(NATIVE.isNativeAvailable as jest.Mock).mockImplementation(() => true);
285278
init({ enableNative: false });
286279
expect(usedOptions()?.transport).toEqual(makeFetchTransport);
287-
// eslint-disable-next-line @typescript-eslint/unbound-method
288280
expect(NATIVE.isNativeAvailable).not.toBeCalled();
289281
});
290282

291283
it('check both options and native availability', () => {
292284
(NATIVE.isNativeAvailable as jest.Mock).mockImplementation(() => true);
293285
init({ enableNative: true });
294286
expect(usedOptions()?.transport).toEqual(makeNativeTransport);
295-
// eslint-disable-next-line @typescript-eslint/unbound-method
296287
expect(NATIVE.isNativeAvailable).toBeCalled();
297288
});
298289
});

test/tracing/nativeframes.test.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ describe('NativeFramesInstrumentation', () => {
2222
slowFrames: 20,
2323
frozenFrames: 5,
2424
};
25-
// eslint-disable-next-line @typescript-eslint/unbound-method
2625
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(startFrames);
2726

2827
const instance = new NativeFramesInstrumentation(
@@ -55,7 +54,6 @@ describe('NativeFramesInstrumentation', () => {
5554
slowFrames: 40,
5655
frozenFrames: 10,
5756
};
58-
// eslint-disable-next-line @typescript-eslint/unbound-method
5957
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(startFrames);
6058

6159
let eventProcessor: EventProcessor;
@@ -72,7 +70,6 @@ describe('NativeFramesInstrumentation', () => {
7270
instance.onTransactionStart(transaction);
7371

7472
setImmediate(() => {
75-
// eslint-disable-next-line @typescript-eslint/unbound-method
7673
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(finishFrames);
7774

7875
const finishTimestamp = Date.now() / 1000;
@@ -140,7 +137,6 @@ describe('NativeFramesInstrumentation', () => {
140137
slowFrames: 40,
141138
frozenFrames: 10,
142139
};
143-
// eslint-disable-next-line @typescript-eslint/unbound-method
144140
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(finishFrames);
145141

146142
let eventProcessor: EventProcessor;
@@ -215,7 +211,6 @@ describe('NativeFramesInstrumentation', () => {
215211
frozenFrames: 5,
216212
};
217213
const finishFrames = null;
218-
// eslint-disable-next-line @typescript-eslint/unbound-method
219214
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(startFrames);
220215

221216
let eventProcessor: EventProcessor;
@@ -232,7 +227,6 @@ describe('NativeFramesInstrumentation', () => {
232227
instance.onTransactionStart(transaction);
233228

234229
setImmediate(() => {
235-
// eslint-disable-next-line @typescript-eslint/unbound-method
236230
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(finishFrames);
237231

238232
const finishTimestamp = Date.now() / 1000;
@@ -286,7 +280,6 @@ describe('NativeFramesInstrumentation', () => {
286280
slowFrames: 20,
287281
frozenFrames: 5,
288282
};
289-
// eslint-disable-next-line @typescript-eslint/unbound-method
290283
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValue(startFrames);
291284

292285
let eventProcessor: EventProcessor;
@@ -303,7 +296,6 @@ describe('NativeFramesInstrumentation', () => {
303296
instance.onTransactionStart(transaction);
304297

305298
setImmediate(() => {
306-
// eslint-disable-next-line @typescript-eslint/unbound-method
307299
mockFunction(NATIVE.fetchNativeFrames).mockImplementation(
308300
// eslint-disable-next-line @typescript-eslint/no-empty-function
309301
async () => new Promise(() => {}),

0 commit comments

Comments
 (0)