Merge pull request #27261 from backstage/rugvip/no-net
cli: add option to reject network requets in frontend tests
This commit is contained in:
+46
-24
@@ -23,6 +23,14 @@ const paths = require('@backstage/cli-common').findPaths(process.cwd());
|
||||
|
||||
const SRC_EXTS = ['ts', 'js', 'tsx', 'jsx', 'mts', 'cts', 'mjs', 'cjs'];
|
||||
|
||||
const FRONTEND_ROLES = [
|
||||
'frontend',
|
||||
'web-library',
|
||||
'common-library',
|
||||
'frontend-plugin',
|
||||
'frontend-plugin-module',
|
||||
];
|
||||
|
||||
const envOptions = {
|
||||
oldTests: Boolean(process.env.BACKSTAGE_OLD_TESTS),
|
||||
};
|
||||
@@ -123,24 +131,13 @@ const transformIgnorePattern = [
|
||||
|
||||
// Provides additional config that's based on the role of the target package
|
||||
function getRoleConfig(role) {
|
||||
switch (role) {
|
||||
case 'frontend':
|
||||
case 'web-library':
|
||||
case 'common-library':
|
||||
case 'frontend-plugin':
|
||||
case 'frontend-plugin-module':
|
||||
return { testEnvironment: require.resolve('jest-environment-jsdom') };
|
||||
case 'cli':
|
||||
case 'backend':
|
||||
case 'node-library':
|
||||
case 'backend-plugin':
|
||||
case 'backend-plugin-module':
|
||||
default:
|
||||
return { testEnvironment: require.resolve('jest-environment-node') };
|
||||
if (FRONTEND_ROLES.includes(role)) {
|
||||
return { testEnvironment: require.resolve('jest-environment-jsdom') };
|
||||
}
|
||||
return { testEnvironment: require.resolve('jest-environment-node') };
|
||||
}
|
||||
|
||||
async function getProjectConfig(targetPath, extraConfig) {
|
||||
async function getProjectConfig(targetPath, extraConfig, extraOptions) {
|
||||
const configJsPath = path.resolve(targetPath, 'jest.config.js');
|
||||
const configTsPath = path.resolve(targetPath, 'jest.config.ts');
|
||||
// If the package has it's own jest config, we use that instead.
|
||||
@@ -234,6 +231,17 @@ async function getProjectConfig(targetPath, extraConfig) {
|
||||
|
||||
options.setupFilesAfterEnv = options.setupFilesAfterEnv || [];
|
||||
|
||||
if (
|
||||
extraOptions.rejectFrontendNetworkRequests &&
|
||||
FRONTEND_ROLES.includes(pkgJson.backstage?.role)
|
||||
) {
|
||||
// By adding this first we ensure that it's possible to for example override
|
||||
// fetch with a mock in a custom setup file
|
||||
options.setupFilesAfterEnv.unshift(
|
||||
require.resolve('./jestRejectNetworkRequests.js'),
|
||||
);
|
||||
}
|
||||
|
||||
if (options.testEnvironment === require.resolve('jest-environment-jsdom')) {
|
||||
// FIXME https://github.com/jsdom/jsdom/issues/1724
|
||||
options.setupFilesAfterEnv.unshift(require.resolve('cross-fetch/polyfill'));
|
||||
@@ -278,21 +286,31 @@ async function getRootConfig() {
|
||||
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx,mjs,cjs}', '!**/*.d.ts'],
|
||||
};
|
||||
|
||||
const { rejectFrontendNetworkRequests, ...rootOptions } =
|
||||
rootPkgJson.jest ?? {};
|
||||
const extraRootOptions = {
|
||||
rejectFrontendNetworkRequests,
|
||||
};
|
||||
|
||||
const workspacePatterns =
|
||||
rootPkgJson.workspaces && rootPkgJson.workspaces.packages;
|
||||
|
||||
// Check if we're running within a specific monorepo package. In that case just get the single project config.
|
||||
if (!workspacePatterns || paths.targetRoot !== paths.targetDir) {
|
||||
return getProjectConfig(paths.targetDir, {
|
||||
...baseCoverageConfig,
|
||||
...(rootPkgJson.jest ?? {}),
|
||||
});
|
||||
return getProjectConfig(
|
||||
paths.targetDir,
|
||||
{
|
||||
...baseCoverageConfig,
|
||||
...rootOptions,
|
||||
},
|
||||
extraRootOptions,
|
||||
);
|
||||
}
|
||||
|
||||
const globalRootConfig = { ...baseCoverageConfig };
|
||||
const globalProjectConfig = {};
|
||||
|
||||
for (const [key, value] of Object.entries(rootPkgJson.jest ?? {})) {
|
||||
for (const [key, value] of Object.entries(rootOptions)) {
|
||||
if (projectConfigKeys.includes(key)) {
|
||||
globalProjectConfig[key] = value;
|
||||
} else {
|
||||
@@ -323,10 +341,14 @@ async function getRootConfig() {
|
||||
testScript?.includes('backstage-cli test') ||
|
||||
testScript?.includes('backstage-cli package test');
|
||||
if (testScript && isSupportedTestScript) {
|
||||
return await getProjectConfig(projectPath, {
|
||||
...globalProjectConfig,
|
||||
displayName: packageData.name,
|
||||
});
|
||||
return await getProjectConfig(
|
||||
projectPath,
|
||||
{
|
||||
...globalProjectConfig,
|
||||
displayName: packageData.name,
|
||||
},
|
||||
extraRootOptions,
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
|
||||
const errorMessage = 'Network requests are not allowed in tests';
|
||||
|
||||
const origHttpAgent = http.globalAgent;
|
||||
const origHttpsAgent = https.globalAgent;
|
||||
const origFetch = global.fetch;
|
||||
const origXMLHttpRequest = global.fetch;
|
||||
|
||||
http.globalAgent = new http.Agent({
|
||||
lookup() {
|
||||
throw new Error(errorMessage);
|
||||
},
|
||||
});
|
||||
|
||||
https.globalAgent = new https.Agent({
|
||||
lookup() {
|
||||
throw new Error(errorMessage);
|
||||
},
|
||||
});
|
||||
|
||||
if (global.fetch) {
|
||||
global.fetch = async () => {
|
||||
throw new Error(errorMessage);
|
||||
};
|
||||
}
|
||||
|
||||
if (global.XMLHttpRequest) {
|
||||
global.XMLHttpRequest = class {
|
||||
constructor() {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Reset overrides after each suite to make sure we don't pollute the test environment
|
||||
afterAll(() => {
|
||||
http.globalAgent = origHttpAgent;
|
||||
https.globalAgent = origHttpsAgent;
|
||||
global.fetch = origFetch;
|
||||
global.XMLHttpRequest = origXMLHttpRequest;
|
||||
});
|
||||
Reference in New Issue
Block a user