mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Improve community node repo code (#3767)
* 📘 Tighten `NodeRequest` * :blue: Add `AuthAgent` type * ⚡ Add constants * 📘 Namespace npm types * 🧪 Set up `createAuthAgent` * 🧪 Refactor helpers tests * 🧪 Refactor endpoints tests * ⚡ Refactor CNR helpers * ⚡ Return promises in `packageModel` * ⚡ Refactor endpoints * ✏️ Restore naming * ➕ Expose dependency `jest-mock` * 📦 Update `package-lock.json` * 📦 Update `package-lock.json` * 👕 Fix lint * 🚚 Rename namespace * 🔥 Remove outdated comment * 🐛 Fix `Promise` comparison * ⏪ Undo `ResponseHelper` change * ✏️ Document `ResponseError` * 🎨 Fix formatting
This commit is contained in:
@@ -1,330 +1,343 @@
|
||||
import { checkPackageStatus, matchPackagesWithUpdates, executeCommand, parsePackageName, matchMissingPackages, hasPackageLoadedSuccessfully, removePackageFromMissingList } from '../../src/CommunityNodes/helpers';
|
||||
import { NODE_PACKAGE_PREFIX, NPM_COMMAND_TOKENS, NPM_PACKAGE_STATUS_GOOD, RESPONSE_ERROR_MESSAGES } from '../../src/constants';
|
||||
|
||||
jest.mock('fs/promises');
|
||||
import { exec } from 'child_process';
|
||||
import { access as fsAccess, mkdir as fsMkdir } from 'fs/promises';
|
||||
|
||||
jest.mock('child_process');
|
||||
import { exec } from 'child_process';
|
||||
import { InstalledPackages } from '../../src/databases/entities/InstalledPackages';
|
||||
import { installedNodePayload, installedPackagePayload } from '../integration/shared/utils';
|
||||
import { InstalledNodes } from '../../src/databases/entities/InstalledNodes';
|
||||
import { NpmUpdatesAvailable } from '../../src/Interfaces';
|
||||
import { randomName } from '../integration/shared/random';
|
||||
|
||||
import config from '../../config';
|
||||
|
||||
jest.mock('axios');
|
||||
import axios from 'axios';
|
||||
|
||||
describe('CommunityNodesHelper', () => {
|
||||
import {
|
||||
checkNpmPackageStatus,
|
||||
matchPackagesWithUpdates,
|
||||
executeCommand,
|
||||
parseNpmPackageName,
|
||||
matchMissingPackages,
|
||||
hasPackageLoaded,
|
||||
removePackageFromMissingList,
|
||||
} from '../../src/CommunityNodes/helpers';
|
||||
import {
|
||||
NODE_PACKAGE_PREFIX,
|
||||
NPM_COMMAND_TOKENS,
|
||||
NPM_PACKAGE_STATUS_GOOD,
|
||||
RESPONSE_ERROR_MESSAGES,
|
||||
} from '../../src/constants';
|
||||
import { InstalledPackages } from '../../src/databases/entities/InstalledPackages';
|
||||
import { InstalledNodes } from '../../src/databases/entities/InstalledNodes';
|
||||
import { randomName } from '../integration/shared/random';
|
||||
import config from '../../config';
|
||||
import { installedPackagePayload, installedNodePayload } from '../integration/shared/utils';
|
||||
|
||||
describe('parsePackageName', () => {
|
||||
it('Should fail with empty package name', () => {
|
||||
expect(() => parsePackageName('')).toThrowError()
|
||||
});
|
||||
import type { CommunityPackages } from '../../src/Interfaces';
|
||||
|
||||
it('Should fail with invalid package prefix name', () => {
|
||||
expect(() => parsePackageName('INVALID_PREFIX@123')).toThrowError()
|
||||
});
|
||||
jest.mock('fs/promises');
|
||||
jest.mock('child_process');
|
||||
jest.mock('axios');
|
||||
|
||||
it('Should parse valid package name', () => {
|
||||
const validPackageName = NODE_PACKAGE_PREFIX + 'cool-package-name';
|
||||
const parsedPackageName = parsePackageName(validPackageName);
|
||||
|
||||
expect(parsedPackageName.originalString).toBe(validPackageName);
|
||||
expect(parsedPackageName.packageName).toBe(validPackageName);
|
||||
expect(parsedPackageName.scope).toBeUndefined();
|
||||
expect(parsedPackageName.version).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should parse valid package name and version', () => {
|
||||
const validPackageName = NODE_PACKAGE_PREFIX + 'cool-package-name';
|
||||
const validPackageVersion = '0.1.1';
|
||||
const fullPackageName = `${validPackageName}@${validPackageVersion}`;
|
||||
const parsedPackageName = parsePackageName(fullPackageName);
|
||||
|
||||
expect(parsedPackageName.originalString).toBe(fullPackageName);
|
||||
expect(parsedPackageName.packageName).toBe(validPackageName);
|
||||
expect(parsedPackageName.scope).toBeUndefined();
|
||||
expect(parsedPackageName.version).toBe(validPackageVersion);
|
||||
});
|
||||
|
||||
it('Should parse valid package name, scope and version', () => {
|
||||
const validPackageScope = '@n8n';
|
||||
const validPackageName = NODE_PACKAGE_PREFIX + 'cool-package-name';
|
||||
const validPackageVersion = '0.1.1';
|
||||
const fullPackageName = `${validPackageScope}/${validPackageName}@${validPackageVersion}`;
|
||||
const parsedPackageName = parsePackageName(fullPackageName);
|
||||
|
||||
expect(parsedPackageName.originalString).toBe(fullPackageName);
|
||||
expect(parsedPackageName.packageName).toBe(`${validPackageScope}/${validPackageName}`);
|
||||
expect(parsedPackageName.scope).toBe(validPackageScope);
|
||||
expect(parsedPackageName.version).toBe(validPackageVersion);
|
||||
});
|
||||
describe('parsePackageName', () => {
|
||||
test('Should fail with empty package name', () => {
|
||||
expect(() => parseNpmPackageName('')).toThrowError();
|
||||
});
|
||||
|
||||
describe('executeCommand', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
// @ts-ignore
|
||||
fsAccess.mockReset();
|
||||
// @ts-ignore
|
||||
fsMkdir.mockReset();
|
||||
// @ts-ignore
|
||||
exec.mockReset();
|
||||
});
|
||||
|
||||
it('Should call command with valid options', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
expect(args[1].cwd).toBeDefined();
|
||||
expect(args[1].env).toBeDefined();
|
||||
// PATH or NODE_PATH may be undefined depending on environment so we don't check for these keys.
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(null, { stdout: 'Done' });
|
||||
});
|
||||
|
||||
await executeCommand('ls');
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it ('Should make sure folder exists', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(null, { stdout: 'Done' });
|
||||
});
|
||||
|
||||
await executeCommand('ls');
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it ('Should try to create folder if it does not exist', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(null, { stdout: 'Done' });
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
fsAccess.mockImplementation(() => {
|
||||
throw new Error('Folder does not exist.');
|
||||
});
|
||||
|
||||
await executeCommand('ls');
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should throw especial error when package is not found', async() => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(new Error('Something went wrong - ' + NPM_COMMAND_TOKENS.NPM_PACKAGE_NOT_FOUND_ERROR + '. Aborting.'));
|
||||
});
|
||||
|
||||
await expect(async () => await executeCommand('ls')).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND);
|
||||
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
test('Should fail with invalid package prefix name', () => {
|
||||
expect(() => parseNpmPackageName('INVALID_PREFIX@123')).toThrowError();
|
||||
});
|
||||
|
||||
test('Should parse valid package name', () => {
|
||||
const validPackageName = NODE_PACKAGE_PREFIX + 'cool-package-name';
|
||||
const parsed = parseNpmPackageName(validPackageName);
|
||||
|
||||
describe('crossInformationPackage', () => {
|
||||
|
||||
it('Should return same list if availableUpdates is undefined', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const crossedData = matchPackagesWithUpdates(fakePackages);
|
||||
expect(crossedData).toEqual(fakePackages);
|
||||
});
|
||||
|
||||
it ('Should correctly match update versions for packages', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
|
||||
const updates: NpmUpdatesAvailable = {
|
||||
[fakePackages[0].packageName]: {
|
||||
current: fakePackages[0].installedVersion,
|
||||
wanted: fakePackages[0].installedVersion,
|
||||
latest: '0.2.0',
|
||||
location: fakePackages[0].packageName,
|
||||
},
|
||||
[fakePackages[1].packageName]: {
|
||||
current: fakePackages[0].installedVersion,
|
||||
wanted: fakePackages[0].installedVersion,
|
||||
latest: '0.3.0',
|
||||
location: fakePackages[0].packageName,
|
||||
}
|
||||
};
|
||||
|
||||
const crossedData = matchPackagesWithUpdates(fakePackages, updates);
|
||||
|
||||
// @ts-ignore
|
||||
expect(crossedData[0].updateAvailable).toBe('0.2.0');
|
||||
// @ts-ignore
|
||||
expect(crossedData[1].updateAvailable).toBe('0.3.0');
|
||||
|
||||
});
|
||||
|
||||
it ('Should correctly match update versions for single package', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
|
||||
const updates: NpmUpdatesAvailable = {
|
||||
[fakePackages[1].packageName]: {
|
||||
current: fakePackages[0].installedVersion,
|
||||
wanted: fakePackages[0].installedVersion,
|
||||
latest: '0.3.0',
|
||||
location: fakePackages[0].packageName,
|
||||
}
|
||||
};
|
||||
|
||||
const crossedData = matchPackagesWithUpdates(fakePackages, updates);
|
||||
|
||||
// @ts-ignore
|
||||
expect(crossedData[0].updateAvailable).toBeUndefined();
|
||||
// @ts-ignore
|
||||
expect(crossedData[1].updateAvailable).toBe('0.3.0');
|
||||
|
||||
});
|
||||
|
||||
expect(parsed.rawString).toBe(validPackageName);
|
||||
expect(parsed.packageName).toBe(validPackageName);
|
||||
expect(parsed.scope).toBeUndefined();
|
||||
expect(parsed.version).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('matchMissingPackages', () => {
|
||||
it('Should not match failed packages that do not exist', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const notFoundPackageList = `${NODE_PACKAGE_PREFIX}very-long-name-that-should-never-be-generated@1.0.0 ${NODE_PACKAGE_PREFIX}another-very-long-name-that-never-is-seen`;
|
||||
const matchedPackages = matchMissingPackages(fakePackages, notFoundPackageList);
|
||||
test('Should parse valid package name and version', () => {
|
||||
const validPackageName = NODE_PACKAGE_PREFIX + 'cool-package-name';
|
||||
const validPackageVersion = '0.1.1';
|
||||
const fullPackageName = `${validPackageName}@${validPackageVersion}`;
|
||||
const parsed = parseNpmPackageName(fullPackageName);
|
||||
|
||||
expect(matchedPackages).toEqual(fakePackages);
|
||||
expect(matchedPackages[0].failedLoading).toBeUndefined();
|
||||
expect(matchedPackages[1].failedLoading).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should match failed packages that should be present', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const notFoundPackageList = `${NODE_PACKAGE_PREFIX}very-long-name-that-should-never-be-generated@1.0.0 ${fakePackages[0].packageName}@${fakePackages[0].installedVersion}`;
|
||||
const matchedPackages = matchMissingPackages(fakePackages, notFoundPackageList);
|
||||
|
||||
expect(matchedPackages[0].failedLoading).toBe(true);
|
||||
expect(matchedPackages[1].failedLoading).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should match failed packages even if version is wrong', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const notFoundPackageList = `${NODE_PACKAGE_PREFIX}very-long-name-that-should-never-be-generated@1.0.0 ${fakePackages[0].packageName}@123.456.789`;
|
||||
const matchedPackages = matchMissingPackages(fakePackages, notFoundPackageList);
|
||||
|
||||
expect(matchedPackages[0].failedLoading).toBe(true);
|
||||
expect(matchedPackages[1].failedLoading).toBeUndefined();
|
||||
});
|
||||
expect(parsed.rawString).toBe(fullPackageName);
|
||||
expect(parsed.packageName).toBe(validPackageName);
|
||||
expect(parsed.scope).toBeUndefined();
|
||||
expect(parsed.version).toBe(validPackageVersion);
|
||||
});
|
||||
|
||||
describe('checkPackageStatus', () => {
|
||||
it('Should call axios.post', async () => {
|
||||
const packageName = NODE_PACKAGE_PREFIX + randomName();
|
||||
await checkPackageStatus(packageName);
|
||||
expect(axios.post).toHaveBeenCalled();
|
||||
});
|
||||
test('Should parse valid package name, scope and version', () => {
|
||||
const validPackageScope = '@n8n';
|
||||
const validPackageName = NODE_PACKAGE_PREFIX + 'cool-package-name';
|
||||
const validPackageVersion = '0.1.1';
|
||||
const fullPackageName = `${validPackageScope}/${validPackageName}@${validPackageVersion}`;
|
||||
const parsed = parseNpmPackageName(fullPackageName);
|
||||
|
||||
it('Should not fail if request fails', async () => {
|
||||
const packageName = NODE_PACKAGE_PREFIX + randomName();
|
||||
axios.post = jest.fn(() => {
|
||||
throw new Error('Something went wrong');
|
||||
});
|
||||
const result = await checkPackageStatus(packageName);
|
||||
expect(result.status).toBe(NPM_PACKAGE_STATUS_GOOD);
|
||||
});
|
||||
expect(parsed.rawString).toBe(fullPackageName);
|
||||
expect(parsed.packageName).toBe(`${validPackageScope}/${validPackageName}`);
|
||||
expect(parsed.scope).toBe(validPackageScope);
|
||||
expect(parsed.version).toBe(validPackageVersion);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should warn if package is banned', async () => {
|
||||
const packageName = NODE_PACKAGE_PREFIX + randomName();
|
||||
// @ts-ignore
|
||||
axios.post = jest.fn(() => {
|
||||
return { data: { status: 'Banned', reason: 'Not good' } };
|
||||
});
|
||||
const result = await checkPackageStatus(packageName);
|
||||
expect(result.status).toBe('Banned');
|
||||
expect(result.reason).toBe('Not good');
|
||||
});
|
||||
describe('executeCommand', () => {
|
||||
beforeEach(() => {
|
||||
// @ts-ignore
|
||||
fsAccess.mockReset();
|
||||
// @ts-ignore
|
||||
fsMkdir.mockReset();
|
||||
// @ts-ignore
|
||||
exec.mockReset();
|
||||
});
|
||||
|
||||
describe('hasPackageLoadedSuccessfully', () => {
|
||||
it('Should return true when failed package list does not exist', () => {
|
||||
config.set('nodes.packagesMissing', undefined);
|
||||
const result = hasPackageLoadedSuccessfully('package');
|
||||
expect(result).toBe(true);
|
||||
test('Should call command with valid options', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
expect(args[1].cwd).toBeDefined();
|
||||
expect(args[1].env).toBeDefined();
|
||||
// PATH or NODE_PATH may be undefined depending on environment so we don't check for these keys.
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(null, { stdout: 'Done' });
|
||||
});
|
||||
|
||||
it('Should return true when package is not in the list of missing packages', () => {
|
||||
config.set('nodes.packagesMissing', 'packageA@0.1.0 packgeB@0.1.0');
|
||||
const result = hasPackageLoadedSuccessfully('packageC');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('Should return false when package is in the list of missing packages', () => {
|
||||
config.set('nodes.packagesMissing', 'packageA@0.1.0 packgeB@0.1.0');
|
||||
const result = hasPackageLoadedSuccessfully('packageA');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
await executeCommand('ls');
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
describe('removePackageFromMissingList', () => {
|
||||
it('Should do nothing if key does not exist', () => {
|
||||
config.set('nodes.packagesMissing', undefined);
|
||||
|
||||
removePackageFromMissingList('packageA');
|
||||
|
||||
const packageList = config.get('nodes.packagesMissing');
|
||||
expect(packageList).toBeUndefined();
|
||||
test('Should make sure folder exists', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(null, { stdout: 'Done' });
|
||||
});
|
||||
|
||||
it('Should remove only correct package from list', () => {
|
||||
config.set('nodes.packagesMissing', 'packageA@0.1.0 packageB@0.2.0 packageBB@0.2.0');
|
||||
await executeCommand('ls');
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
removePackageFromMissingList('packageB');
|
||||
|
||||
const packageList = config.get('nodes.packagesMissing');
|
||||
expect(packageList).toBe('packageA@0.1.0 packageBB@0.2.0');
|
||||
test('Should try to create folder if it does not exist', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(null, { stdout: 'Done' });
|
||||
});
|
||||
|
||||
|
||||
it('Should not remove if package is not in the list', () => {
|
||||
const failedToLoadList = 'packageA@0.1.0 packageB@0.2.0 packageBB@0.2.0';
|
||||
config.set('nodes.packagesMissing', failedToLoadList);
|
||||
|
||||
removePackageFromMissingList('packageC');
|
||||
|
||||
const packageList = config.get('nodes.packagesMissing');
|
||||
expect(packageList).toBe(failedToLoadList);
|
||||
// @ts-ignore
|
||||
fsAccess.mockImplementation(() => {
|
||||
throw new Error('Folder does not exist.');
|
||||
});
|
||||
|
||||
await executeCommand('ls');
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should throw especial error when package is not found', async () => {
|
||||
// @ts-ignore
|
||||
exec.mockImplementation((...args) => {
|
||||
const callbackFunction = args[args.length - 1];
|
||||
callbackFunction(
|
||||
new Error(
|
||||
'Something went wrong - ' +
|
||||
NPM_COMMAND_TOKENS.NPM_PACKAGE_NOT_FOUND_ERROR +
|
||||
'. Aborting.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
await expect(async () => await executeCommand('ls')).rejects.toThrow(
|
||||
RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND,
|
||||
);
|
||||
|
||||
expect(fsAccess).toHaveBeenCalled();
|
||||
expect(exec).toHaveBeenCalled();
|
||||
expect(fsMkdir).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('crossInformationPackage', () => {
|
||||
test('Should return same list if availableUpdates is undefined', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const crossedData = matchPackagesWithUpdates(fakePackages);
|
||||
expect(crossedData).toEqual(fakePackages);
|
||||
});
|
||||
|
||||
test('Should correctly match update versions for packages', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
|
||||
const updates: CommunityPackages.AvailableUpdates = {
|
||||
[fakePackages[0].packageName]: {
|
||||
current: fakePackages[0].installedVersion,
|
||||
wanted: fakePackages[0].installedVersion,
|
||||
latest: '0.2.0',
|
||||
location: fakePackages[0].packageName,
|
||||
},
|
||||
[fakePackages[1].packageName]: {
|
||||
current: fakePackages[0].installedVersion,
|
||||
wanted: fakePackages[0].installedVersion,
|
||||
latest: '0.3.0',
|
||||
location: fakePackages[0].packageName,
|
||||
},
|
||||
};
|
||||
|
||||
const crossedData = matchPackagesWithUpdates(fakePackages, updates);
|
||||
|
||||
// @ts-ignore
|
||||
expect(crossedData[0].updateAvailable).toBe('0.2.0');
|
||||
// @ts-ignore
|
||||
expect(crossedData[1].updateAvailable).toBe('0.3.0');
|
||||
});
|
||||
|
||||
test('Should correctly match update versions for single package', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
|
||||
const updates: CommunityPackages.AvailableUpdates = {
|
||||
[fakePackages[1].packageName]: {
|
||||
current: fakePackages[0].installedVersion,
|
||||
wanted: fakePackages[0].installedVersion,
|
||||
latest: '0.3.0',
|
||||
location: fakePackages[0].packageName,
|
||||
},
|
||||
};
|
||||
|
||||
const crossedData = matchPackagesWithUpdates(fakePackages, updates);
|
||||
|
||||
// @ts-ignore
|
||||
expect(crossedData[0].updateAvailable).toBeUndefined();
|
||||
// @ts-ignore
|
||||
expect(crossedData[1].updateAvailable).toBe('0.3.0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('matchMissingPackages', () => {
|
||||
test('Should not match failed packages that do not exist', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const notFoundPackageList = `${NODE_PACKAGE_PREFIX}very-long-name-that-should-never-be-generated@1.0.0 ${NODE_PACKAGE_PREFIX}another-very-long-name-that-never-is-seen`;
|
||||
const matchedPackages = matchMissingPackages(fakePackages, notFoundPackageList);
|
||||
|
||||
expect(matchedPackages).toEqual(fakePackages);
|
||||
expect(matchedPackages[0].failedLoading).toBeUndefined();
|
||||
expect(matchedPackages[1].failedLoading).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Should match failed packages that should be present', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const notFoundPackageList = `${NODE_PACKAGE_PREFIX}very-long-name-that-should-never-be-generated@1.0.0 ${fakePackages[0].packageName}@${fakePackages[0].installedVersion}`;
|
||||
const matchedPackages = matchMissingPackages(fakePackages, notFoundPackageList);
|
||||
|
||||
expect(matchedPackages[0].failedLoading).toBe(true);
|
||||
expect(matchedPackages[1].failedLoading).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Should match failed packages even if version is wrong', () => {
|
||||
const fakePackages = generateListOfFakeInstalledPackages();
|
||||
const notFoundPackageList = `${NODE_PACKAGE_PREFIX}very-long-name-that-should-never-be-generated@1.0.0 ${fakePackages[0].packageName}@123.456.789`;
|
||||
const matchedPackages = matchMissingPackages(fakePackages, notFoundPackageList);
|
||||
|
||||
expect(matchedPackages[0].failedLoading).toBe(true);
|
||||
expect(matchedPackages[1].failedLoading).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkNpmPackageStatus', () => {
|
||||
test('Should call axios.post', async () => {
|
||||
const packageName = NODE_PACKAGE_PREFIX + randomName();
|
||||
await checkNpmPackageStatus(packageName);
|
||||
expect(axios.post).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Should not fail if request fails', async () => {
|
||||
const packageName = NODE_PACKAGE_PREFIX + randomName();
|
||||
axios.post = jest.fn(() => {
|
||||
throw new Error('Something went wrong');
|
||||
});
|
||||
const result = await checkNpmPackageStatus(packageName);
|
||||
expect(result.status).toBe(NPM_PACKAGE_STATUS_GOOD);
|
||||
});
|
||||
|
||||
test('Should warn if package is banned', async () => {
|
||||
const packageName = NODE_PACKAGE_PREFIX + randomName();
|
||||
// @ts-ignore
|
||||
axios.post = jest.fn(() => {
|
||||
return { data: { status: 'Banned', reason: 'Not good' } };
|
||||
});
|
||||
const result = await checkNpmPackageStatus(packageName);
|
||||
expect(result.status).toBe('Banned');
|
||||
expect(result.reason).toBe('Not good');
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasPackageLoadedSuccessfully', () => {
|
||||
test('Should return true when failed package list does not exist', () => {
|
||||
config.set('nodes.packagesMissing', undefined);
|
||||
const result = hasPackageLoaded('package');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test('Should return true when package is not in the list of missing packages', () => {
|
||||
config.set('nodes.packagesMissing', 'packageA@0.1.0 packgeB@0.1.0');
|
||||
const result = hasPackageLoaded('packageC');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test('Should return false when package is in the list of missing packages', () => {
|
||||
config.set('nodes.packagesMissing', 'packageA@0.1.0 packgeB@0.1.0');
|
||||
const result = hasPackageLoaded('packageA');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removePackageFromMissingList', () => {
|
||||
test('Should do nothing if key does not exist', () => {
|
||||
config.set('nodes.packagesMissing', undefined);
|
||||
|
||||
removePackageFromMissingList('packageA');
|
||||
|
||||
const packageList = config.get('nodes.packagesMissing');
|
||||
expect(packageList).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Should remove only correct package from list', () => {
|
||||
config.set('nodes.packagesMissing', 'packageA@0.1.0 packageB@0.2.0 packageBB@0.2.0');
|
||||
|
||||
removePackageFromMissingList('packageB');
|
||||
|
||||
const packageList = config.get('nodes.packagesMissing');
|
||||
expect(packageList).toBe('packageA@0.1.0 packageBB@0.2.0');
|
||||
});
|
||||
|
||||
test('Should not remove if package is not in the list', () => {
|
||||
const failedToLoadList = 'packageA@0.1.0 packageB@0.2.0 packageBB@0.2.0';
|
||||
config.set('nodes.packagesMissing', failedToLoadList);
|
||||
|
||||
removePackageFromMissingList('packageC');
|
||||
|
||||
const packageList = config.get('nodes.packagesMissing');
|
||||
expect(packageList).toBe(failedToLoadList);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Generates a list with 2 packages, one with a single node and
|
||||
* another with 2 nodes
|
||||
* @returns
|
||||
* Generate a list with 2 packages, one with a single node and another with 2 nodes
|
||||
*/
|
||||
function generateListOfFakeInstalledPackages(): InstalledPackages[] {
|
||||
const fakeInstalledPackage1 = new InstalledPackages();
|
||||
Object.assign(fakeInstalledPackage1, installedPackagePayload());
|
||||
|
||||
const fakeInstalledNode1 = new InstalledNodes();
|
||||
Object.assign(fakeInstalledNode1, installedNodePayload(fakeInstalledPackage1.packageName));
|
||||
|
||||
fakeInstalledPackage1.installedNodes = [fakeInstalledNode1];
|
||||
|
||||
const fakeInstalledPackage2 = new InstalledPackages();
|
||||
Object.assign(fakeInstalledPackage2, installedPackagePayload());
|
||||
|
||||
const fakeInstalledNode2 = new InstalledNodes();
|
||||
Object.assign(fakeInstalledNode2, installedNodePayload(fakeInstalledPackage2.packageName));
|
||||
|
||||
const fakeInstalledNode3 = new InstalledNodes();
|
||||
Object.assign(fakeInstalledNode3, installedNodePayload(fakeInstalledPackage2.packageName));
|
||||
|
||||
fakeInstalledPackage2.installedNodes = [fakeInstalledNode2, fakeInstalledNode3];
|
||||
|
||||
return [fakeInstalledPackage1, fakeInstalledPackage2];
|
||||
|
||||
Reference in New Issue
Block a user