Merge pull request #20037 from davidfestal/fix-tests-on-windows

Fix `backend-plugin-manager` unit tests failures on Windows
This commit is contained in:
Patrik Oldsberg
2023-09-20 13:09:26 +02:00
committed by GitHub
4 changed files with 183 additions and 95 deletions
@@ -174,20 +174,23 @@ describe('backend-plugin-manager', () => {
meta: {
name: 'Error',
message: expect.stringContaining(
`Cannot find module '${url.fileURLToPath(
location,
)}/dist/index.cjs.js' from `,
`Cannot find module '${path.resolve(
url.fileURLToPath(location),
'dist/index.cjs.js',
)}' from `,
),
_originalMessage: expect.stringContaining(
`Cannot find module '${url.fileURLToPath(
location,
)}/dist/index.cjs.js' from `,
`Cannot find module '${path.resolve(
url.fileURLToPath(location),
'dist/index.cjs.js',
)}' from `,
),
code: 'MODULE_NOT_FOUND',
hint: '',
moduleName: `${url.fileURLToPath(
location,
)}/dist/index.cjs.js`,
moduleName: `${path.resolve(
url.fileURLToPath(location),
'dist/index.cjs.js',
)}`,
siblingWithSimilarExtensionFound: false,
requireStack: undefined,
},
@@ -351,7 +354,9 @@ describe('backend-plugin-manager', () => {
},
])('$name', async (tc: TestCase): Promise<void> => {
const plugin: ScannedPluginPackage = {
location: new URL(`file:///node_modules/jest-tests/${randomUUID()}`),
location: url.pathToFileURL(
path.resolve(`/node_modules/jest-tests/${randomUUID()}`),
),
manifest: tc.packageManifest,
};
@@ -462,8 +467,8 @@ describe('backend-plugin-manager', () => {
.spyOn(PluginScanner.prototype, 'scanRoot')
.mockImplementation(async () => [
{
location: new URL(
'file:///somewhere/dynamic-plugins-root/a-dynamic-plugin',
location: url.pathToFileURL(
path.resolve('/somewhere/dynamic-plugins-root/a-dynamic-plugin'),
),
manifest: {
name: 'test',
@@ -528,10 +533,12 @@ describe('backend-plugin-manager', () => {
expect(scanRootSpier).toHaveBeenCalled();
expect(mockedModuleLoader.bootstrap).toHaveBeenCalledWith(
findPaths(__dirname).targetRoot,
['/somewhere-else/a-dynamic-plugin'],
[path.resolve('/somewhere-else/a-dynamic-plugin')],
);
expect(mockedModuleLoader.load).toHaveBeenCalledWith(
'/somewhere/dynamic-plugins-root/a-dynamic-plugin/dist/index.cjs.js',
path.resolve(
'/somewhere/dynamic-plugins-root/a-dynamic-plugin/dist/index.cjs.js',
),
);
});
});
@@ -15,7 +15,7 @@
*/
import { PluginScanner } from './plugin-scanner';
import { Logs, MockedLogger } from '../__testUtils__/testUtils';
import { LogContent, Logs, MockedLogger } from '../__testUtils__/testUtils';
import { Config, ConfigReader } from '@backstage/config';
import path, { join } from 'path';
import { ScannedPluginPackage } from './types';
@@ -126,10 +126,16 @@ describe('plugin-scanner', () => {
expect(logger.logs).toEqual<Logs>({
infos: [
{
message: `rootDirectory changed (addDir - ${backstageRootDirectory}/first-dir/test-backend-plugin): scanning plugins again`,
message: `rootDirectory changed (addDir - ${path.resolve(
backstageRootDirectory,
'first-dir/test-backend-plugin',
)}): scanning plugins again`,
},
{
message: `rootDirectory changed (add - ${backstageRootDirectory}/first-dir/test-backend-plugin/package.json): scanning plugins again`,
message: `rootDirectory changed (add - ${path.resolve(
backstageRootDirectory,
'first-dir/test-backend-plugin/package.json',
)}): scanning plugins again`,
},
],
});
@@ -151,7 +157,10 @@ describe('plugin-scanner', () => {
expect(logger.logs).toEqual<Logs>({
infos: [
{
message: `rootDirectory changed in Config from '${backstageRootDirectory}/first-dir' to '${backstageRootDirectory}/second-dir'`,
message: `rootDirectory changed in Config from '${path.resolve(
backstageRootDirectory,
'first-dir',
)}' to '${path.resolve(backstageRootDirectory, 'second-dir')}'`,
},
],
});
@@ -204,10 +213,16 @@ describe('plugin-scanner', () => {
expect(logger.logs).toEqual<Logs>({
infos: [
{
message: `rootDirectory changed (addDir - ${backstageRootDirectory}/second-dir/second-test-backend-plugin): scanning plugins again`,
message: `rootDirectory changed (addDir - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin',
)}): scanning plugins again`,
},
{
message: `rootDirectory changed (add - ${backstageRootDirectory}/second-dir/second-test-backend-plugin/package.json): scanning plugins again`,
message: `rootDirectory changed (add - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/package.json',
)}): scanning plugins again`,
},
],
});
@@ -263,22 +278,41 @@ describe('plugin-scanner', () => {
expect(debug).toHaveBeenCalledTimes(4);
});
expect(logger.logs).toEqual<Logs>({
debugs: [
{
message: `rootDirectory changed (addDir - ${backstageRootDirectory}/second-dir/second-test-backend-plugin/sub-directory): no need to scan plugins again`,
},
{
message: `rootDirectory changed (add - ${backstageRootDirectory}/second-dir/second-test-backend-plugin/not-package.json): no need to scan plugins again`,
},
{
message: `rootDirectory changed (unlink - ${backstageRootDirectory}/second-dir/second-test-backend-plugin/not-package.json): no need to scan plugins again`,
},
{
message: `rootDirectory changed (unlinkDir - ${backstageRootDirectory}/second-dir/second-test-backend-plugin/sub-directory): no need to scan plugins again`,
},
],
});
const onWindows = path.sep === '\\';
// Order of events is not fixed on Windows.
// Windows sometimes even adds a 'change' event when a file is unlinked.
// So let's not try to tes the detail of received events on Windows
if (!onWindows) {
// eslint-disable-next-line
expect(logger.logs).toEqual<Logs>({
debugs: [
{
message: `rootDirectory changed (addDir - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/sub-directory',
)}): no need to scan plugins again`,
},
{
message: `rootDirectory changed (add - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/not-package.json',
)}): no need to scan plugins again`,
},
{
message: `rootDirectory changed (unlink - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/not-package.json',
)}): no need to scan plugins again`,
},
{
message: `rootDirectory changed (unlinkDir - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/sub-directory',
)}): no need to scan plugins again`,
},
],
});
}
logger.logs = {};
// Now check that removal of some plugin home directory triggers a new scan of plugins
@@ -299,26 +333,39 @@ describe('plugin-scanner', () => {
expect(scannedPlugins).toEqual([]);
});
expect(logger.logs).toEqual<Logs>({
infos: [
if (!onWindows) {
// eslint-disable-next-line
expect(logger.logs.infos).toEqual<LogContent[] | undefined>([
{
message: `rootDirectory changed (unlink - ${backstageRootDirectory}/second-dir/second-test-backend-plugin/package.json): scanning plugins again`,
message: `rootDirectory changed (unlink - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/package.json',
)}): scanning plugins again`,
},
],
errors: [
{
message: `failed to load dynamic plugin manifest from '${backstageRootDirectory}/second-dir/second-test-backend-plugin'`,
meta: {
code: 'ENOENT',
errno: -2,
message: `ENOENT: no such file or directory, open '${backstageRootDirectory}/second-dir/second-test-backend-plugin/package.json'`,
name: 'Error',
path: `${backstageRootDirectory}/second-dir/second-test-backend-plugin/package.json`,
syscall: 'open',
},
]);
}
expect(logger.logs.errors).toEqual<LogContent[] | undefined>([
{
message: `failed to load dynamic plugin manifest from '${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin',
)}'`,
meta: {
code: 'ENOENT',
errno: path.sep === '\\' ? -4058 : -2,
message: `ENOENT: no such file or directory, open '${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/package.json',
)}'`,
name: 'Error',
path: `${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin/package.json',
)}`,
syscall: 'open',
},
],
});
},
]);
logger.logs = {};
await rm(
@@ -334,13 +381,19 @@ describe('plugin-scanner', () => {
});
rootDirectorySubscriber.mockClear();
expect(logger.logs).toEqual<Logs>({
infos: [
{
message: `rootDirectory changed (unlinkDir - ${backstageRootDirectory}/second-dir/second-test-backend-plugin): scanning plugins again`,
},
],
});
if (!onWindows) {
// eslint-disable-next-line
expect(logger.logs).toEqual<Logs>({
infos: [
{
message: `rootDirectory changed (unlinkDir - ${path.resolve(
backstageRootDirectory,
'second-dir/second-test-backend-plugin',
)}): scanning plugins again`,
},
],
});
}
logger.logs = {};
getOptional.mockReturnValue({
@@ -353,8 +406,16 @@ describe('plugin-scanner', () => {
{
message: 'failed to apply new config for dynamic plugins',
meta: {
message: `Dynamic plugins under '/somewhere-else/second-dir' cannot access backstage modules in '${backstageRootDirectory}/node_modules'.
Please add '${backstageRootDirectory}/node_modules' to the 'NODE_PATH' when running the backstage backend.`,
message: `Dynamic plugins under '${path.resolve(
'/somewhere-else/second-dir',
)}' cannot access backstage modules in '${path.resolve(
backstageRootDirectory,
'node_modules',
)}'.
Please add '${path.resolve(
backstageRootDirectory,
'node_modules',
)}' to the 'NODE_PATH' when running the backstage backend.`,
name: 'Error',
},
},
@@ -20,6 +20,7 @@ import { JsonObject } from '@backstage/types';
import { Logs, MockedLogger } from '../__testUtils__/testUtils';
import { ConfigReader } from '@backstage/config';
import path from 'path';
import * as url from 'url';
import { ScannedPluginPackage } from './types';
describe('plugin-scanner', () => {
@@ -73,7 +74,7 @@ describe('plugin-scanner', () => {
rootDirectory: 'dist-dynamic',
},
},
expectedRootDirectory: '/backstageRoot/dist-dynamic',
expectedRootDirectory: path.resolve('/backstageRoot/dist-dynamic'),
},
{
name: 'valid config with absolute root directory path inside the backstage root',
@@ -90,7 +91,7 @@ describe('plugin-scanner', () => {
rootDirectory: '/backstageRoot/dist-dynamic',
},
},
expectedRootDirectory: '/backstageRoot/dist-dynamic',
expectedRootDirectory: path.resolve('/backstageRoot/dist-dynamic'),
},
{
name: 'valid config with absolute root directory path outside the backstage root',
@@ -107,8 +108,14 @@ describe('plugin-scanner', () => {
rootDirectory: '/somewhere/dist-dynamic',
},
},
expectedError: `Dynamic plugins under '/somewhere/dist-dynamic' cannot access backstage modules in '/backstageRoot/node_modules'.
Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the backstage backend.`,
expectedError: `Dynamic plugins under '${path.resolve(
'/somewhere/dist-dynamic',
)}' cannot access backstage modules in '${path.resolve(
'/backstageRoot/node_modules',
)}'.
Please add '${path.resolve(
'/backstageRoot/node_modules',
)}' to the 'NODE_PATH' when running the backstage backend.`,
},
{
name: 'valid config with absolute root directory path outside the backstage root but with backstage root included in NODE_PATH',
@@ -126,9 +133,13 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
},
},
environment: {
NODE_PATH: `/somewhere-else${path.delimiter}/backstageRoot/node_modules${path.delimiter}/anywhere-else`,
NODE_PATH: `${path.resolve('/somewhere-else')}${
path.delimiter
}${path.resolve('/backstageRoot', 'node_modules')}${
path.delimiter
}${path.resolve('anywhere-else')}`,
},
expectedRootDirectory: '/somewhere/dist-dynamic',
expectedRootDirectory: path.resolve('/somewhere/dist-dynamic'),
},
{
name: 'invalid config: dynamicPlugins not an object',
@@ -273,8 +284,8 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
},
expectedPluginPackages: [
{
location: new URL(
'file:///backstageRoot/dist-dynamic/test-backend-plugin',
location: url.pathToFileURL(
path.resolve('/backstageRoot/dist-dynamic/test-backend-plugin'),
),
manifest: {
name: 'test-backend-plugin-dynamic',
@@ -318,8 +329,8 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
},
expectedPluginPackages: [
{
location: new URL(
'file:///backstageRoot/dist-dynamic/test-backend-plugin',
location: url.pathToFileURL(
path.resolve('/backstageRoot/dist-dynamic/test-backend-plugin'),
),
manifest: {
name: 'test-backend-plugin-dynamic',
@@ -347,8 +358,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
infos: [
{
message:
"skipping '/backstageRoot/dist-dynamic/test-backend-plugin' since it is not a directory",
message: `skipping '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin',
)}' since it is not a directory`,
},
],
},
@@ -377,8 +389,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
infos: [
{
message:
"skipping '/backstageRoot/dist-dynamic/test-backend-plugin' since it is not a directory",
message: `skipping '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin',
)}' since it is not a directory`,
},
],
},
@@ -421,8 +434,8 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
},
expectedPluginPackages: [
{
location: new URL(
'file:///backstageRoot/dist-dynamic/test-backend-plugin',
location: url.pathToFileURL(
path.resolve('/backstageRoot/dist-dynamic/test-backend-plugin'),
),
manifest: {
name: 'test-backend-plugin-dynamic',
@@ -471,8 +484,10 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
},
expectedPluginPackages: [
{
location: new URL(
'file:///backstageRoot/dist-dynamic/test-backend-plugin/alpha',
location: url.pathToFileURL(
path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin/alpha',
),
),
manifest: {
name: 'test-backend-plugin-dynamic',
@@ -511,8 +526,8 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
},
expectedPluginPackages: [
{
location: new URL(
'file:///backstageRoot/dist-dynamic/test-backend-plugin',
location: url.pathToFileURL(
path.resolve('/backstageRoot/dist-dynamic/test-backend-plugin'),
),
manifest: {
name: 'test-backend-plugin-dynamic',
@@ -525,8 +540,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
warns: [
{
message:
"skipping '/backstageRoot/dist-dynamic/test-backend-plugin/alpha' since it is not a directory",
message: `skipping '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin/alpha',
)}' since it is not a directory`,
},
],
},
@@ -567,8 +583,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
errors: [
{
message:
"failed to load dynamic plugin manifest from '/backstageRoot/dist-dynamic/test-backend-plugin/alpha'",
message: `failed to load dynamic plugin manifest from '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin/alpha',
)}'`,
meta: {
name: 'SyntaxError',
message: 'Unexpected token i in JSON at position 0',
@@ -600,8 +617,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
errors: [
{
message:
"failed to load dynamic plugin manifest from '/backstageRoot/dist-dynamic/test-backend-plugin'",
message: `failed to load dynamic plugin manifest from '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin',
)}'`,
meta: {
name: 'SyntaxError',
message: 'Unexpected token i in JSON at position 0',
@@ -637,8 +655,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
errors: [
{
message:
"failed to load dynamic plugin manifest from '/backstageRoot/dist-dynamic/test-backend-plugin'",
message: `failed to load dynamic plugin manifest from '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin',
)}'`,
meta: {
name: 'Error',
message: "field 'backstage.role' not found in 'package.json'",
@@ -674,8 +693,9 @@ Please add '/backstageRoot/node_modules' to the 'NODE_PATH' when running the bac
expectedLogs: {
errors: [
{
message:
"failed to load dynamic plugin manifest from '/backstageRoot/dist-dynamic/test-backend-plugin'",
message: `failed to load dynamic plugin manifest from '${path.resolve(
'/backstageRoot/dist-dynamic/test-backend-plugin',
)}'`,
meta: {
name: 'Error',
message: "field 'main' not found in 'package.json'",
@@ -84,13 +84,13 @@ export class PluginScanner {
}
const dynamicPluginsRootPath = path.isAbsolute(dynamicPlugins.rootDirectory)
? dynamicPlugins.rootDirectory
? path.resolve(dynamicPlugins.rootDirectory)
: path.resolve(this.backstageRoot, dynamicPlugins.rootDirectory);
if (
!path
.dirname(path.normalize(dynamicPluginsRootPath))
.startsWith(path.normalize(this.backstageRoot))
.dirname(dynamicPluginsRootPath)
.startsWith(path.resolve(this.backstageRoot))
) {
const nodePath = process.env.NODE_PATH;
const backstageNodeModules = path.resolve(