lion/packages-node/providence-analytics/test-helpers/mock-project-helpers.js
2023-11-08 19:02:51 +01:00

158 lines
5.5 KiB
JavaScript

import path from 'path';
// eslint-disable-next-line import/no-extraneous-dependencies
import { mockFsAndRequire } from './mock-fs-and-require.js';
export const mock = mockFsAndRequire;
/**
* Makes sure that, whenever the main program (providence) calls
* "InputDataService.createDataObject", it gives back a mocked response.
* @param {string[]|object} files all the code that will be run trhough AST
* @param {object} [cfg]
* @param {string} [cfg.projectName='fictional-project']
* @param {string} [cfg.projectPath='/fictional/project']
* @param {string[]} [cfg.filePaths=`[/fictional/project/test-file-${i}.js]`] The indexes of the file
* paths match with the indexes of the files
* @param {object} existingMock config for mock-fs, so the previous config is not overridden
*/
function getMockObjectForProject(files, cfg = {}, existingMock = {}) {
const projName = cfg.projectName || 'fictional-project';
const projPath = cfg.projectPath || '/fictional/project';
// Create obj structure for mock-fs
/**
* @param {object} files
*/
// eslint-disable-next-line no-shadow
function createFilesObjForFolder(files) {
let projFilesObj = {};
if (Array.isArray(files)) {
projFilesObj = files.reduce((res, code, i) => {
const fileName = (cfg.filePaths && cfg.filePaths[i]) || `./test-file-${i}.js`;
const localFileName = path.resolve(projPath, fileName);
res[localFileName] = code;
return res;
}, {});
} else {
Object.keys(files).forEach(f => {
const localFileName = path.resolve(projPath, f);
projFilesObj[localFileName] = files[f];
});
}
return projFilesObj;
}
const optionalPackageJson = {};
const hasPackageJson =
(cfg.filePaths && cfg.filePaths.includes('./package.json')) || files['./package.json'];
if (!hasPackageJson) {
optionalPackageJson[projPath] = {
'package.json': `{ "name": "${projName}" , "version": "${cfg.version || '0.1.0-mock'}" }`,
};
}
const totalMock = {
...optionalPackageJson,
...existingMock, // can only add to mock-fs, not expand existing config?
...createFilesObjForFolder(files),
};
return totalMock;
}
/**
* Makes sure that, whenever the main program (providence) calls
* "InputDataService.createDataObject", it gives back a mocked response.
* @param {string[]|object} files all the code that will be run trhough AST
* @param {object} [cfg]
* @param {string} [cfg.projectName='fictional-project']
* @param {string} [cfg.projectPath='/fictional/project']
* @param {string[]} [cfg.filePaths=`[/fictional/project/test-file-${i}.js]`] The indexes of the file
* paths match with the indexes of the files
* @param {object} existingMock config for mock-fs, so the previous config is not overridden
*/
export function mockProject(files, cfg = {}, existingMock = {}) {
const obj = getMockObjectForProject(files, cfg, existingMock);
mockFsAndRequire(obj);
return obj;
}
export function restoreMockedProjects() {
mockFsAndRequire.restore();
}
export function getEntry(queryResult, index = 0) {
return queryResult.queryOutput[index];
}
export function getEntries(queryResult) {
return queryResult.queryOutput;
}
function createPackageJson({ filePaths, codeSnippets, projectName, refProjectName, refVersion }) {
const targetHasPackageJson = filePaths.includes('./package.json');
// Make target depend on ref
if (targetHasPackageJson) {
return;
}
const pkgJson = {
name: projectName,
version: '1.0.0',
};
if (refProjectName && refVersion) {
pkgJson.dependencies = { [refProjectName]: refVersion };
}
codeSnippets.push(JSON.stringify(pkgJson));
filePaths.push('./package.json');
}
/**
* Requires two config objects (see match-imports and match-subclasses tests)
* and based on those, will use mock-fs package to mock them in the file system.
* All missing information (like target depending on ref, version numbers, project names
* and paths will be auto generated when not specified.)
* When a non imported ref dependency or a wrong version of a dev dependency needs to be
* tested, please explicitly provide a ./package.json that does so.
*/
export function mockTargetAndReferenceProject(searchTargetProject, referenceProject) {
const targetProjectName = searchTargetProject.name || 'fictional-target-project';
const refProjectName = referenceProject.name || 'fictional-ref-project';
const targetcodeSnippets = searchTargetProject.files.map(f => f.code);
const targetFilePaths = searchTargetProject.files.map(f => f.file);
const refVersion = referenceProject.version || '1.0.0';
const refcodeSnippets = referenceProject.files.map(f => f.code);
const refFilePaths = referenceProject.files.map(f => f.file);
createPackageJson({
filePaths: targetFilePaths,
codeSnippets: targetcodeSnippets,
projectName: targetProjectName,
refProjectName,
refVersion,
});
createPackageJson({
filePaths: refFilePaths,
codeSnippets: refcodeSnippets,
projectName: refProjectName,
});
// Create target mock
const targetMock = getMockObjectForProject(targetcodeSnippets, {
filePaths: targetFilePaths,
projectName: targetProjectName,
projectPath: searchTargetProject.path || 'fictional/target/project',
});
// Append ref mock
mockProject(
referenceProject.files.map(f => f.code),
{
filePaths: referenceProject.files.map(f => f.file),
projectName: refProjectName,
projectPath: referenceProject.path || 'fictional/ref/project',
version: refVersion,
},
targetMock,
);
}