Skip to content

Commit e632424

Browse files
gnoffAndyPengc12
authored andcommitted
[devtools][tests] add support for @GATE pragma (facebook#28479)
Adds support for `// @gate` pragma in devtools tests Adds a couple gate test assertions to ensure they continue to work
1 parent d0605bb commit e632424

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

.eslintrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,13 @@ module.exports = {
381381
'jest/valid-expect-in-promise': ERROR,
382382
},
383383
},
384+
{
385+
// disable no focused tests for test setup helper files even if they are inside __tests__ directory
386+
files: ['**/setupTests.js'],
387+
rules: {
388+
'jest/no-focused-tests': OFF,
389+
},
390+
},
384391
{
385392
files: [
386393
'**/__tests__/**/*.js',
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
describe('gate', () => {
11+
//@gate false
12+
it('should expect an error for this test', () => {
13+
throw new Error('This test should fail');
14+
});
15+
16+
//@gate true
17+
it('should not an error for this test', () => {});
18+
});

packages/react-devtools-shared/src/__tests__/setupTests.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
BackendBridge,
1414
FrontendBridge,
1515
} from 'react-devtools-shared/src/bridge';
16+
const {getTestFlags} = require('../../../../scripts/jest/TestFlags');
1617

1718
// Argument is serialized when passed from jest-cli script through to setupTests.
1819
const compactConsole = process.env.compactConsole === 'true';
@@ -32,6 +33,76 @@ if (compactConsole) {
3233
global.console = new CustomConsole(process.stdout, process.stderr, formatter);
3334
}
3435

36+
const expectTestToFail = async (callback, error) => {
37+
if (callback.length > 0) {
38+
throw Error(
39+
'Gated test helpers do not support the `done` callback. Return a ' +
40+
'promise instead.',
41+
);
42+
}
43+
try {
44+
const maybePromise = callback();
45+
if (
46+
maybePromise !== undefined &&
47+
maybePromise !== null &&
48+
typeof maybePromise.then === 'function'
49+
) {
50+
await maybePromise;
51+
}
52+
} catch (testError) {
53+
return;
54+
}
55+
throw error;
56+
};
57+
58+
const gatedErrorMessage = 'Gated test was expected to fail, but it passed.';
59+
global._test_gate = (gateFn, testName, callback) => {
60+
let shouldPass;
61+
try {
62+
const flags = getTestFlags();
63+
shouldPass = gateFn(flags);
64+
} catch (e) {
65+
test(testName, () => {
66+
throw e;
67+
});
68+
return;
69+
}
70+
if (shouldPass) {
71+
test(testName, callback);
72+
} else {
73+
const error = new Error(gatedErrorMessage);
74+
Error.captureStackTrace(error, global._test_gate);
75+
test(`[GATED, SHOULD FAIL] ${testName}`, () =>
76+
expectTestToFail(callback, error));
77+
}
78+
};
79+
global._test_gate_focus = (gateFn, testName, callback) => {
80+
let shouldPass;
81+
try {
82+
const flags = getTestFlags();
83+
shouldPass = gateFn(flags);
84+
} catch (e) {
85+
test.only(testName, () => {
86+
throw e;
87+
});
88+
return;
89+
}
90+
if (shouldPass) {
91+
test.only(testName, callback);
92+
} else {
93+
const error = new Error(gatedErrorMessage);
94+
Error.captureStackTrace(error, global._test_gate_focus);
95+
test.only(`[GATED, SHOULD FAIL] ${testName}`, () =>
96+
expectTestToFail(callback, error));
97+
}
98+
};
99+
100+
// Dynamic version of @gate pragma
101+
global.gate = fn => {
102+
const flags = getTestFlags();
103+
return fn(flags);
104+
};
105+
35106
beforeEach(() => {
36107
global.mockClipboardCopy = jest.fn();
37108

0 commit comments

Comments
 (0)