@o3r/testing
Version:
The module provides testing (e2e, unit test) utilities to help you build your own E2E pipeline integrating visual testing.
112 lines • 4.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.adjustPath = adjustPath;
const fs = require("node:fs");
const node_module_1 = require("node:module");
const path = require("node:path");
const node_vm_1 = require("node:vm");
const esbuild_1 = require("esbuild");
/**
* Get the global variables of the current process
* @returns The global variables of the current process
*/
function getNodeGlobals() {
const globals = Object.create(null);
for (const key of Object.getOwnPropertyNames(globalThis)) {
try {
const value = globalThis[key];
try {
globals[key] = structuredClone(value);
}
catch {
// Non-cloneable values (functions, symbols, etc.) - use reference
globals[key] = value;
}
}
catch {
// Some properties may throw when accessed (e.g., deprecated ones)
}
}
globals.global = globalThis;
globals.globalThis = globalThis;
return globals;
}
/**
* Load a CommonJS module from a string.
* @param code The module code to execute
* @param dirname The directory to use as the module's dirname
*/
function requireFromString(code, dirname) {
const filename = path.join(dirname, '_virtual.js');
const mainRequire = require.main;
const tempModule = new node_module_1.Module(filename, mainRequire);
tempModule.require = (0, node_module_1.createRequire)(filename);
tempModule.filename = filename;
tempModule.paths = mainRequire?.paths ?? [];
const context = (0, node_vm_1.createContext)({
...getNodeGlobals(),
module: tempModule,
exports: tempModule.exports,
require: tempModule.require.bind(tempModule),
__dirname: dirname,
__filename: filename
});
const script = new node_vm_1.Script(code, {
filename
});
script.runInContext(context);
tempModule.loaded = true;
return tempModule.exports;
}
/**
* Switch to the needed implementation of core testing, when running e2e tests
* transforms ESM into CJS when needed
* @param frameworkName Name of the framework used for e2e testing (playwright)
* @param customTransformOptions
*/
function adjustPath(frameworkName = 'playwright', customTransformOptions = {}) {
const modulesCache = Object.create(null);
// eslint-disable-next-line @typescript-eslint/unbound-method -- No need to bind the method, we are using `apply`
const originalRequire = node_module_1.Module.prototype.require;
const regex = new RegExp(`@o3r/testing/core(?!/${frameworkName})(.*)`);
node_module_1.Module.prototype.require = function (id) {
const newId = id.replace(regex, `@o3r/testing/core/${frameworkName}$1`);
try {
return Reflect.apply(originalRequire, this, [newId]);
}
catch {
const paths = []
.concat(this.paths, this.paths.map((i) => i.replace(/[/\\]node_modules$/, '')));
const filePath = require.resolve(newId, { paths });
if (!modulesCache[filePath]) {
const fileContent = fs.readFileSync(filePath);
const cwd = path.resolve(process.cwd(), 'src');
// we use ESBUILD to transform it into CJS
const trans = (0, esbuild_1.transformSync)(fileContent.toString(), {
loader: 'js',
format: 'cjs',
target: 'es2016',
sourcesContent: true,
sourceRoot: cwd,
...customTransformOptions
});
/**
* requireFromString will execute the file apart from just returning a module
* It can throw an exception which will prevent stop the execution
*
* That main blocker includes IVY-compatible libraries which have
* no compiler facade in a global scope.
*/
try {
modulesCache[filePath] = requireFromString(trans.code, path.dirname(filePath));
}
catch (ex) {
// eslint-disable-next-line no-console -- no other logger available
console.error(ex);
}
}
return modulesCache[filePath];
}
};
}
//# sourceMappingURL=path-replacement.js.map