Skip to content

Commit

Permalink
[devtools][tests] add support for @GATE pragma (#28479)
Browse files Browse the repository at this point in the history
Adds support for `// @gate` pragma in devtools tests
Adds a couple gate test assertions to ensure they continue to work
  • Loading branch information
gnoff authored Mar 1, 2024
1 parent 11828bf commit 30ae0ba
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@ module.exports = {
'jest/valid-expect-in-promise': ERROR,
},
},
{
// disable no focused tests for test setup helper files even if they are inside __tests__ directory
files: ['**/setupTests.js'],
rules: {
'jest/no-focused-tests': OFF,
},
},
{
files: [
'**/__tests__/**/*.js',
Expand Down
18 changes: 18 additions & 0 deletions packages/react-devtools-shared/src/__tests__/gate-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

describe('gate', () => {
//@gate false
it('should expect an error for this test', () => {
throw new Error('This test should fail');
});

//@gate true
it('should not an error for this test', () => {});
});
71 changes: 71 additions & 0 deletions packages/react-devtools-shared/src/__tests__/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
BackendBridge,
FrontendBridge,
} from 'react-devtools-shared/src/bridge';
const {getTestFlags} = require('../../../../scripts/jest/TestFlags');

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

const expectTestToFail = async (callback, error) => {
if (callback.length > 0) {
throw Error(
'Gated test helpers do not support the `done` callback. Return a ' +
'promise instead.',
);
}
try {
const maybePromise = callback();
if (
maybePromise !== undefined &&
maybePromise !== null &&
typeof maybePromise.then === 'function'
) {
await maybePromise;
}
} catch (testError) {
return;
}
throw error;
};

const gatedErrorMessage = 'Gated test was expected to fail, but it passed.';
global._test_gate = (gateFn, testName, callback) => {
let shouldPass;
try {
const flags = getTestFlags();
shouldPass = gateFn(flags);
} catch (e) {
test(testName, () => {
throw e;
});
return;
}
if (shouldPass) {
test(testName, callback);
} else {
const error = new Error(gatedErrorMessage);
Error.captureStackTrace(error, global._test_gate);
test(`[GATED, SHOULD FAIL] ${testName}`, () =>
expectTestToFail(callback, error));
}
};
global._test_gate_focus = (gateFn, testName, callback) => {
let shouldPass;
try {
const flags = getTestFlags();
shouldPass = gateFn(flags);
} catch (e) {
test.only(testName, () => {
throw e;
});
return;
}
if (shouldPass) {
test.only(testName, callback);
} else {
const error = new Error(gatedErrorMessage);
Error.captureStackTrace(error, global._test_gate_focus);
test.only(`[GATED, SHOULD FAIL] ${testName}`, () =>
expectTestToFail(callback, error));
}
};

// Dynamic version of @gate pragma
global.gate = fn => {
const flags = getTestFlags();
return fn(flags);
};

beforeEach(() => {
global.mockClipboardCopy = jest.fn();

Expand Down

0 comments on commit 30ae0ba

Please sign in to comment.