Skip to content

Commit 03d8368

Browse files
acdliteAndyPengc12
authored andcommitted
Update gate pragma to detect global error events (facebook#28591)
If a global error event is dispatched during a test, Jest reports that test as a failure. Our `@gate` pragma feature should account for this — if the gate condition is false, and the global error event is dispatched, then the test should be reported as a success. The solution is to install an error event handler right before invoking the test function. Because we install our own handler, Jest will not report the test as a failure if a global error event is dispatched; it's conceptually as if we wrapped the whole test event in a try-catch.
1 parent 1d755cf commit 03d8368

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

scripts/babel/__tests__/transform-test-gate-pragma-test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,15 @@ describe('transform test-gate-pragma: actual runtime', () => {
203203
console.error('Stop that!');
204204
throw Error('I told you to stop!');
205205
});
206+
207+
// @gate false
208+
test('a global error event is treated as a test failure', () => {
209+
dispatchEvent(
210+
new ErrorEvent('error', {
211+
error: new Error('Oops!'),
212+
})
213+
);
214+
});
206215
});
207216

208217
describe('dynamic gate method', () => {

scripts/jest/setupTests.js

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,13 +241,30 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
241241
global.Error = ErrorProxy;
242242
}
243243

244-
const expectTestToFail = async (callback, error) => {
244+
const expectTestToFail = async (callback, errorToThrowIfTestSucceeds) => {
245245
if (callback.length > 0) {
246246
throw Error(
247247
'Gated test helpers do not support the `done` callback. Return a ' +
248248
'promise instead.'
249249
);
250250
}
251+
252+
// Install a global error event handler. We treat global error events as
253+
// test failures, same as Jest's default behavior.
254+
//
255+
// Becaused we installed our own error event handler, Jest will not report a
256+
// test failure. Conceptually it's as if we wrapped the entire test event in
257+
// a try-catch.
258+
let didError = false;
259+
const errorEventHandler = () => {
260+
didError = true;
261+
};
262+
// eslint-disable-next-line no-restricted-globals
263+
if (typeof addEventListener === 'function') {
264+
// eslint-disable-next-line no-restricted-globals
265+
addEventListener('error', errorEventHandler);
266+
}
267+
251268
try {
252269
const maybePromise = callback();
253270
if (
@@ -262,11 +279,20 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
262279
// throws, we won't have captured it.
263280
flushAllUnexpectedConsoleCalls();
264281
} catch (testError) {
265-
// Failed as expected
266-
resetAllUnexpectedConsoleCalls();
267-
return;
282+
didError = true;
283+
}
284+
resetAllUnexpectedConsoleCalls();
285+
// eslint-disable-next-line no-restricted-globals
286+
if (typeof removeEventListener === 'function') {
287+
// eslint-disable-next-line no-restricted-globals
288+
removeEventListener('error', errorEventHandler);
289+
}
290+
291+
if (!didError) {
292+
// The test did not error like we expected it to. Report this to Jest as
293+
// a failure.
294+
throw errorToThrowIfTestSucceeds;
268295
}
269-
throw error;
270296
};
271297

272298
const gatedErrorMessage = 'Gated test was expected to fail, but it passed.';

0 commit comments

Comments
 (0)