testcafe
Version:
Automated browser testing for the modern web development stack.
196 lines • 27.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const fs_1 = require("fs");
const strip_bom_1 = __importDefault(require("strip-bom"));
const nanoid_1 = require("nanoid");
const base_1 = __importDefault(require("./base"));
const test_file_1 = __importDefault(require("../../api/structure/test-file"));
const fixture_1 = __importDefault(require("../../api/structure/fixture"));
const test_1 = __importDefault(require("../../api/structure/test"));
const runtime_1 = require("../../errors/runtime");
const stack_cleaning_hook_1 = __importDefault(require("../../errors/stack-cleaning-hook"));
const node_modules_folder_name_1 = __importDefault(require("../../utils/node-modules-folder-name"));
const cache_proxy_1 = __importDefault(require("./cache-proxy"));
const exportable_lib_1 = __importDefault(require("../../api/exportable-lib"));
const add_export_api_1 = __importDefault(require("./add-export-api"));
const url_1 = __importDefault(require("url"));
const prevent_module_caching_suffix_1 = __importDefault(require("../prevent-module-caching-suffix"));
const { register } = require('node:module');
const { pathToFileURL } = require('node:url');
const semver = require('semver');
const CWD = process.cwd();
const FIXTURE_RE = /(^|;|\s+)fixture\s*(\.|\(|`)/;
const TEST_RE = /(^|;|\s+)test\s*(\.|\()/;
const TESTCAFE_LIB_FOLDER_NAME = 'lib';
const Module = module.constructor;
const errRequireEsmErrorCode = 'ERR_REQUIRE_ESM';
class APIBasedTestFileCompilerBase extends base_1.default {
constructor({ baseUrl, esm }) {
super({ baseUrl });
this.cache = Object.create(null);
this.origRequireExtensions = Object.create(null);
this.cachePrefix = (0, nanoid_1.nanoid)(7);
this.esm = esm;
}
static _getNodeModulesLookupPath(filename) {
const dir = (0, path_1.dirname)(filename);
return Module._nodeModulePaths(dir);
}
static _isNodeModulesDep(filename) {
return (0, path_1.relative)(CWD, filename)
.split(path_1.sep)
.includes(node_modules_folder_name_1.default);
}
static _isTestCafeLibDep(filename) {
return (0, path_1.relative)(CWD, filename)
.split(path_1.sep)
.includes(TESTCAFE_LIB_FOLDER_NAME);
}
async _execAsModule(code, filename) {
if (this.esm) {
if (semver.satisfies(process.version, '18.19.0 - 18.x || >=20.8.0'))
register('../esm-loader.js', pathToFileURL(__filename));
const fileUrl = url_1.default.pathToFileURL(filename);
//NOTE: It is necessary to prevent module caching during live mode.
// eslint-disable-next-line no-eval
await eval(`import('${fileUrl}?${prevent_module_caching_suffix_1.default}=${Date.now()}')`);
}
else {
const mod = new Module(filename, module.parent);
mod.filename = filename;
mod.paths = APIBasedTestFileCompilerBase._getNodeModulesLookupPath(filename);
cache_proxy_1.default.startExternalCaching(this.cachePrefix);
mod._compile(code, filename);
cache_proxy_1.default.stopExternalCaching();
}
}
_compileCode(code, filename) {
if (this.canPrecompile)
return this._precompileCode([{ code, filename }])[0];
throw new Error('Not implemented');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_precompileCode(testFilesInfo) {
throw new Error('Not implemented');
}
_getRequireCompilers() {
throw new Error('Not implemented');
}
_compileExternalModule(mod, filename, requireCompiler, origExt) {
if (APIBasedTestFileCompilerBase._isNodeModulesDep(filename) && origExt)
origExt(mod, filename);
else
this._compileModule(mod, filename, requireCompiler, origExt);
}
_compileModule(mod, filename, requireCompiler) {
const code = (0, fs_1.readFileSync)(filename).toString();
const compiledCode = requireCompiler((0, strip_bom_1.default)(code), filename);
mod.paths = APIBasedTestFileCompilerBase._getNodeModulesLookupPath(filename);
mod._compile(compiledCode, filename);
}
_setupRequireHook(testFile) {
const requireCompilers = this._getRequireCompilers();
this.origRequireExtensions = Object.create(null);
Object.keys(requireCompilers).forEach(ext => {
const origExt = require.extensions[ext];
this.origRequireExtensions[ext] = origExt;
require.extensions[ext] = (mod, filename) => {
const hadGlobalAPI = this._hasGlobalAPI();
// NOTE: remove global API so that it will be unavailable for the dependencies
if (APIBasedTestFileCompilerBase._isNodeModulesDep(filename) && hadGlobalAPI)
this._removeGlobalAPI();
this._compileExternalModule(mod, filename, requireCompilers[ext], origExt);
if (hadGlobalAPI && !this._hasGlobalAPI())
this._addGlobalAPI(testFile);
};
});
}
_removeRequireHook() {
Object.keys(this.origRequireExtensions).forEach(ext => {
require.extensions[ext] = this.origRequireExtensions[ext];
});
}
_compileCodeForTestFiles(testFilesInfo) {
stack_cleaning_hook_1.default.enabled = true;
try {
if (this.canPrecompile)
return this._precompileCode(testFilesInfo);
return testFilesInfo.map(({ code, filename }) => this._compileCode(code, filename));
}
catch (err) {
throw new runtime_1.TestCompilationError(stack_cleaning_hook_1.default.cleanError(err));
}
finally {
stack_cleaning_hook_1.default.enabled = false;
}
}
_addGlobalAPI(testFile) {
Object.defineProperty(global, 'fixture', {
get: () => new fixture_1.default(testFile, this.baseUrl),
configurable: true,
});
Object.defineProperty(global, 'test', {
get: () => new test_1.default(testFile, this.baseUrl),
configurable: true,
});
}
_addExportAPI(testFile) {
(0, add_export_api_1.default)(testFile, exportable_lib_1.default, { baseUrl: this.baseUrl });
}
_removeGlobalAPI() {
delete global.fixture;
delete global.test;
}
_hasGlobalAPI() {
return global.fixture && global.test;
}
async _runCompiledCode(compiledCode, filename) {
const testFile = new test_file_1.default(filename);
this._addGlobalAPI(testFile);
this._addExportAPI(testFile);
stack_cleaning_hook_1.default.enabled = true;
this._setupRequireHook(testFile);
try {
await this._execAsModule(compiledCode, filename);
}
catch (err) {
if (err.code === errRequireEsmErrorCode)
throw new runtime_1.ImportESMInCommonJSError(err, filename);
if (!(err instanceof runtime_1.APIError))
throw new runtime_1.TestCompilationError(stack_cleaning_hook_1.default.cleanError(err));
throw err;
}
finally {
this._removeRequireHook();
stack_cleaning_hook_1.default.enabled = false;
if (!this.esm)
this._removeGlobalAPI();
}
return testFile.getTests();
}
precompile(testFilesInfo) {
return this._compileCodeForTestFiles(testFilesInfo);
}
execute(compiledCode, filename) {
return this._runCompiledCode(compiledCode, filename);
}
async compile(code, filename) {
const [compiledCode] = await this.precompile([{ code, filename }]);
if (compiledCode)
return this.execute(compiledCode, filename);
return Promise.resolve();
}
_hasTests(code) {
return FIXTURE_RE.test(code) && TEST_RE.test(code);
}
cleanUp() {
this.cache = {};
}
}
exports.default = APIBasedTestFileCompilerBase;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLWJhc2VkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBpbGVyL3Rlc3QtZmlsZS9hcGktYmFzZWQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSwrQkFJYztBQUVkLDJCQUFrQztBQUNsQywwREFBaUM7QUFDakMsbUNBQWdDO0FBQ2hDLGtEQUEwQztBQUMxQyw4RUFBcUQ7QUFDckQsMEVBQWtEO0FBQ2xELG9FQUE0QztBQUM1QyxrREFJOEI7QUFDOUIsMkZBQWlFO0FBQ2pFLG9HQUFnRTtBQUNoRSxnRUFBdUM7QUFDdkMsOEVBQXFEO0FBQ3JELHNFQUE0QztBQUM1Qyw4Q0FBc0I7QUFDdEIscUdBQTZFO0FBRTdFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBUSxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDakQsTUFBTSxFQUFFLGFBQWEsRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUM5QyxNQUFNLE1BQU0sR0FBYyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7QUFHNUMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBRTFCLE1BQU0sVUFBVSxHQUFHLDhCQUE4QixDQUFDO0FBQ2xELE1BQU0sT0FBTyxHQUFNLHlCQUF5QixDQUFDO0FBRTdDLE1BQU0sd0JBQXdCLEdBQUcsS0FBSyxDQUFDO0FBRXZDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUM7QUFFbEMsTUFBTSxzQkFBc0IsR0FBRyxpQkFBaUIsQ0FBQztBQUVqRCxNQUFxQiw0QkFBNkIsU0FBUSxjQUFvQjtJQUMxRSxZQUFhLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRTtRQUN6QixLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBRW5CLElBQUksQ0FBQyxLQUFLLEdBQW1CLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakQsSUFB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SUFFRCxTQUFTLENBQUUsSUFBSTtRQUNYLE9BQU8sVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxPQUFPO1FBQ0gsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDcEIsQ0FBQztDQUNKO0FBeE5ELCtDQXdOQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgZGlybmFtZSxcbiAgICByZWxhdGl2ZSxcbiAgICBzZXAgYXMgcGF0aFNlcCxcbn0gZnJvbSAncGF0aCc7XG5cbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gJ2ZzJztcbmltcG9ydCBzdHJpcEJvbSBmcm9tICdzdHJpcC1ib20nO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkJztcbmltcG9ydCBUZXN0RmlsZUNvbXBpbGVyQmFzZSBmcm9tICcuL2Jhc2UnO1xuaW1wb3J0IFRlc3RGaWxlIGZyb20gJy4uLy4uL2FwaS9zdHJ1Y3R1cmUvdGVzdC1maWxlJztcbmltcG9ydCBGaXh0dXJlIGZyb20gJy4uLy4uL2FwaS9zdHJ1Y3R1cmUvZml4dHVyZSc7XG5pbXBvcnQgVGVzdCBmcm9tICcuLi8uLi9hcGkvc3RydWN0dXJlL3Rlc3QnO1xuaW1wb3J0IHtcbiAgICBUZXN0Q29tcGlsYXRpb25FcnJvcixcbiAgICBBUElFcnJvcixcbiAgICBJbXBvcnRFU01JbkNvbW1vbkpTRXJyb3IsXG59IGZyb20gJy4uLy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCBzdGFja0NsZWFuaW5nSG9vayBmcm9tICcuLi8uLi9lcnJvcnMvc3RhY2stY2xlYW5pbmctaG9vayc7XG5pbXBvcnQgTk9ERV9NT0RVTEVTIGZyb20gJy4uLy4uL3V0aWxzL25vZGUtbW9kdWxlcy1mb2xkZXItbmFtZSc7XG5pbXBvcnQgY2FjaGVQcm94eSBmcm9tICcuL2NhY2hlLXByb3h5JztcbmltcG9ydCBleHBvcnRhYmxlTGliIGZyb20gJy4uLy4uL2FwaS9leHBvcnRhYmxlLWxpYic7XG5pbXBvcnQgYWRkRXhwb3J0QVBJIGZyb20gJy4vYWRkLWV4cG9ydC1hcGknO1xuaW1wb3J0IHVybCBmcm9tICd1cmwnO1xuaW1wb3J0IFBSRVZFTlRfTU9EVUxFX0NBQ0hJTkdfU1VGRklYIGZyb20gJy4uL3ByZXZlbnQtbW9kdWxlLWNhY2hpbmctc3VmZml4JztcblxuY29uc3QgeyByZWdpc3RlciB9ICAgICAgPSByZXF1aXJlKCdub2RlOm1vZHVsZScpO1xuY29uc3QgeyBwYXRoVG9GaWxlVVJMIH0gPSByZXF1aXJlKCdub2RlOnVybCcpO1xuY29uc3Qgc2VtdmVyICAgICAgICAgICAgPSByZXF1aXJlKCdzZW12ZXInKTtcblxuXG5jb25zdCBDV0QgPSBwcm9jZXNzLmN3ZCgpO1xuXG5jb25zdCBGSVhUVVJFX1JFID0gLyhefDt8XFxzKylmaXh0dXJlXFxzKihcXC58XFwofGApLztcbmNvbnN0IFRFU1RfUkUgICAgPSAvKF58O3xcXHMrKXRlc3RcXHMqKFxcLnxcXCgpLztcblxuY29uc3QgVEVTVENBRkVfTElCX0ZPTERFUl9OQU1FID0gJ2xpYic7XG5cbmNvbnN0IE1vZHVsZSA9IG1vZHVsZS5jb25zdHJ1Y3RvcjtcblxuY29uc3QgZXJyUmVxdWlyZUVzbUVycm9yQ29kZSA9ICdFUlJfUkVRVUlSRV9FU00nO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBUElCYXNlZFRlc3RGaWxlQ29tcGlsZXJCYXNlIGV4dGVuZHMgVGVzdEZpbGVDb21waWxlckJhc2Uge1xuICAgIGNvbnN0cnVjdG9yICh7IGJhc2VVcmwsIGVzbSB9KSB7XG4gICAgICAgIHN1cGVyKHsgYmFzZVVybCB9KTtcblxuICAgICAgICB0aGlzLmNhY2hlICAgICAgICAgICAgICAgICA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMub3JpZ1JlcXVpcmVFeHRlbnNpb25zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgdGhpcy5jYWNoZVByZWZpeCAgICAgICAgICAgPSBuYW5vaWQoNyk7XG4gICAgICAgIHRoaXMuZXNtICAgICAgICAgICAgICAgICAgID0gZXNtO1xuICAgIH1cblxuICAgIHN0YXRpYyBfZ2V0Tm9kZU1vZHVsZXNMb29rdXBQYXRoIChmaWxlbmFtZSkge1xuICAgICAgICBjb25zdCBkaXIgPSBkaXJuYW1lKGZpbGVuYW1lKTtcblxuICAgICAgICByZXR1cm4gTW9kdWxlLl9ub2RlTW9kdWxlUGF0aHMoZGlyKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgX2lzTm9kZU1vZHVsZXNEZXAgKGZpbGVuYW1lKSB7XG4gICAgICAgIHJldHVybiByZWxhdGl2ZShDV0QsIGZpbGVuYW1lKVxuICAgICAgICAgICAgLnNwbGl0KHBhdGhTZXApXG4gICAgICAgICAgICAuaW5jbHVkZXMoTk9ERV9NT0RVTEVTKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgX2lzVGVzdENhZmVMaWJEZXAgKGZpbGVuYW1lKSB7XG4gICAgICAgIHJldHVybiByZWxhdGl2ZShDV0QsIGZpbGVuYW1lKVxuICAgICAgICAgICAgLnNwbGl0KHBhdGhTZXApXG4gICAgICAgICAgICAuaW5jbHVkZXMoVEVTVENBRkVfTElCX0ZPTERFUl9OQU1FKTtcbiAgICB9XG5cbiAgICBhc3luYyBfZXhlY0FzTW9kdWxlIChjb2RlLCBmaWxlbmFtZSkge1xuICAgICAgICBpZiAodGhpcy5lc20pIHtcbiAgICAgICAgICAgIGlmIChzZW12ZXIuc2F0aXNmaWVzKHByb2Nlc3MudmVyc2lvbiwgJzE4LjE5LjAgLSAxOC54IHx8ID49MjAuOC4wJykpXG4gICAgICAgICAgICAgICAgcmVnaXN0ZXIoJy4uL2VzbS1sb2FkZXIuanMnLCBwYXRoVG9GaWxlVVJMKF9fZmlsZW5hbWUpKTtcblxuICAgICAgICAgICAgY29uc3QgZmlsZVVybCA9IHVybC5wYXRoVG9GaWxlVVJMKGZpbGVuYW1lKTtcblxuICAgICAgICAgICAgLy9OT1RFOiBJdCBpcyBuZWNlc3NhcnkgdG8gcHJldmVudCBtb2R1bGUgY2FjaGluZyBkdXJpbmcgbGl2ZSBtb2RlLlxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWV2YWxcbiAgICAgICAgICAgIGF3YWl0IGV2YWwoYGltcG9ydCgnJHtmaWxlVXJsfT8ke1BSRVZFTlRfTU9EVUxFX0NBQ0hJTkdfU1VGRklYfT0ke0RhdGUubm93KCl9JylgKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG1vZCA9IG5ldyBNb2R1bGUoZmlsZW5hbWUsIG1vZHVsZS5wYXJlbnQpO1xuXG4gICAgICAgICAgICBtb2QuZmlsZW5hbWUgPSBmaWxlbmFtZTtcbiAgICAgICAgICAgIG1vZC5wYXRocyAgICA9IEFQSUJhc2VkVGVzdEZpbGVDb21waWxlckJhc2UuX2dldE5vZGVNb2R1bGVzTG9va3VwUGF0aChmaWxlbmFtZSk7XG5cbiAgICAgICAgICAgIGNhY2hlUHJveHkuc3RhcnRFeHRlcm5hbENhY2hpbmcodGhpcy5jYWNoZVByZWZpeCk7XG5cbiAgICAgICAgICAgIG1vZC5fY29tcGlsZShjb2RlLCBmaWxlbmFtZSk7XG5cbiAgICAgICAgICAgIGNhY2hlUHJveHkuc3RvcEV4dGVybmFsQ2FjaGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgX2NvbXBpbGVDb2RlIChjb2RlLCBmaWxlbmFtZSkge1xuICAgICAgICBpZiAodGhpcy5jYW5QcmVjb21waWxlKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ByZWNvbXBpbGVDb2RlKFt7IGNvZGUsIGZpbGVuYW1lIH1dKVswXTtcblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBfcHJlY29tcGlsZUNvZGUgKHRlc3RGaWxlc0luZm8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBfZ2V0UmVxdWlyZUNvbXBpbGVycyAoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgX2NvbXBpbGVFeHRlcm5hbE1vZHVsZSAobW9kLCBmaWxlbmFtZSwgcmVxdWlyZUNvbXBpbGVyLCBvcmlnRXh0KSB7XG4gICAgICAgIGlmIChBUElCYXNlZFRlc3RGaWxlQ29tcGlsZXJCYXNlLl9pc05vZGVNb2R1bGVzRGVwKGZpbGVuYW1lKSAmJiBvcmlnRXh0KVxuICAgICAgICAgICAgb3JpZ0V4dCggbW9kLCBmaWxlbmFtZSApO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLl9jb21waWxlTW9kdWxlKG1vZCwgZmlsZW5hbWUsIHJlcXVpcmVDb21waWxlciwgb3JpZ0V4dCk7XG4gICAgfVxuXG4gICAgX2NvbXBpbGVNb2R1bGUgKG1vZCwgZmlsZW5hbWUsIHJlcXVpcmVDb21waWxlcikge1xuICAgICAgICBjb25zdCBjb2RlICAgICAgICAgPSByZWFkRmlsZVN5bmMoZmlsZW5hbWUpLnRvU3RyaW5nKCk7XG4gICAgICAgIGNvbnN0IGNvbXBpbGVkQ29kZSA9IHJlcXVpcmVDb21waWxlcihzdHJpcEJvbShjb2RlKSwgZmlsZW5hbWUpO1xuXG4gICAgICAgIG1vZC5wYXRocyA9IEFQSUJhc2VkVGVzdEZpbGVDb21waWxlckJhc2UuX2dldE5vZGVNb2R1bGVzTG9va3VwUGF0aChmaWxlbmFtZSk7XG5cbiAgICAgICAgbW9kLl9jb21waWxlKGNvbXBpbGVkQ29kZSwgZmlsZW5hbWUpO1xuICAgIH1cblxuICAgIF9zZXR1cFJlcXVpcmVIb29rICh0ZXN0RmlsZSkge1xuICAgICAgICBjb25zdCByZXF1aXJlQ29tcGlsZXJzID0gdGhpcy5fZ2V0UmVxdWlyZUNvbXBpbGVycygpO1xuXG4gICAgICAgIHRoaXMub3JpZ1JlcXVpcmVFeHRlbnNpb25zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuICAgICAgICBPYmplY3Qua2V5cyhyZXF1aXJlQ29tcGlsZXJzKS5mb3JFYWNoKGV4dCA9PiB7XG4gICAgICAgICAgICBjb25zdCBvcmlnRXh0ID0gcmVxdWlyZS5leHRlbnNpb25zW2V4dF07XG5cbiAgICAgICAgICAgIHRoaXMub3JpZ1JlcXVpcmVFeHRlbnNpb25zW2V4dF0gPSBvcmlnRXh0O1xuXG4gICAgICAgICAgICByZXF1aXJlLmV4dGVuc2lvbnNbZXh0XSA9IChtb2QsIGZpbGVuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgaGFkR2xvYmFsQVBJID0gdGhpcy5faGFzR2xvYmFsQVBJKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBOT1RFOiByZW1vdmUgZ2xvYmFsIEFQSSBzbyB0aGF0IGl0IHdpbGwgYmUgdW5hdmFpbGFibGUgZm9yIHRoZSBkZXBlbmRlbmNpZXNcbiAgICAgICAgICAgICAgICBpZiAoQVBJQmFzZWRUZXN0RmlsZUNvbXBpbGVyQmFzZS5faXNOb2RlTW9kdWxlc0RlcChmaWxlbmFtZSkgJiYgaGFkR2xvYmFsQVBJKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVHbG9iYWxBUEkoKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuX2NvbXBpbGVFeHRlcm5hbE1vZHVsZShtb2QsIGZpbGVuYW1lLCByZXF1aXJlQ29tcGlsZXJzW2V4dF0sIG9yaWdFeHQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGhhZEdsb2JhbEFQSSAmJiAhdGhpcy5faGFzR2xvYmFsQVBJKCkpXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZEdsb2JhbEFQSSh0ZXN0RmlsZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfcmVtb3ZlUmVxdWlyZUhvb2sgKCkge1xuICAgICAgICBPYmplY3Qua2V5cyh0aGlzLm9yaWdSZXF1aXJlRXh0ZW5zaW9ucykuZm9yRWFjaChleHQgPT4ge1xuICAgICAgICAgICAgcmVxdWlyZS5leHRlbnNpb25zW2V4dF0gPSB0aGlzLm9yaWdSZXF1aXJlRXh0ZW5zaW9uc1tleHRdO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfY29tcGlsZUNvZGVGb3JUZXN0RmlsZXMgKHRlc3RGaWxlc0luZm8pIHtcbiAgICAgICAgc3RhY2tDbGVhbmluZ0hvb2suZW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNhblByZWNvbXBpbGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ByZWNvbXBpbGVDb2RlKHRlc3RGaWxlc0luZm8pO1xuXG4gICAgICAgICAgICByZXR1cm4gdGVzdEZpbGVzSW5mby5tYXAoKHsgY29kZSwgZmlsZW5hbWUgfSkgPT4gdGhpcy5fY29tcGlsZUNvZGUoY29kZSwgZmlsZW5hbWUpKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVGVzdENvbXBpbGF0aW9uRXJyb3Ioc3RhY2tDbGVhbmluZ0hvb2suY2xlYW5FcnJvcihlcnIpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHN0YWNrQ2xlYW5pbmdIb29rLmVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9hZGRHbG9iYWxBUEkgKHRlc3RGaWxlKSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShnbG9iYWwsICdmaXh0dXJlJywge1xuICAgICAgICAgICAgZ2V0OiAgICAgICAgICAoKSA9PiBuZXcgRml4dHVyZSh0ZXN0RmlsZSwgdGhpcy5iYXNlVXJsKSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGdsb2JhbCwgJ3Rlc3QnLCB7XG4gICAgICAgICAgICBnZXQ6ICAgICAgICAgICgpID0+IG5ldyBUZXN0KHRlc3RGaWxlLCB0aGlzLmJhc2VVcmwpLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfYWRkRXhwb3J0QVBJICh0ZXN0RmlsZSkge1xuICAgICAgICBhZGRFeHBvcnRBUEkodGVzdEZpbGUsIGV4cG9ydGFibGVMaWIsIHsgYmFzZVVybDogdGhpcy5iYXNlVXJsIH0pO1xuICAgIH1cblxuICAgIF9yZW1vdmVHbG9iYWxBUEkgKCkge1xuICAgICAgICBkZWxldGUgZ2xvYmFsLmZpeHR1cmU7XG4gICAgICAgIGRlbGV0ZSBnbG9iYWwudGVzdDtcbiAgICB9XG5cbiAgICBfaGFzR2xvYmFsQVBJICgpIHtcbiAgICAgICAgcmV0dXJuIGdsb2JhbC5maXh0dXJlICYmIGdsb2JhbC50ZXN0O1xuICAgIH1cblxuICAgIGFzeW5jIF9ydW5Db21waWxlZENvZGUgKGNvbXBpbGVkQ29kZSwgZmlsZW5hbWUpIHtcbiAgICAgICAgY29uc3QgdGVzdEZpbGUgPSBuZXcgVGVzdEZpbGUoZmlsZW5hbWUpO1xuXG4gICAgICAgIHRoaXMuX2FkZEdsb2JhbEFQSSh0ZXN0RmlsZSk7XG4gICAgICAgIHRoaXMuX2FkZEV4cG9ydEFQSSh0ZXN0RmlsZSk7XG5cbiAgICAgICAgc3RhY2tDbGVhbmluZ0hvb2suZW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5fc2V0dXBSZXF1aXJlSG9vayh0ZXN0RmlsZSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2V4ZWNBc01vZHVsZShjb21waWxlZENvZGUsIGZpbGVuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoZXJyLmNvZGUgPT09IGVyclJlcXVpcmVFc21FcnJvckNvZGUpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEltcG9ydEVTTUluQ29tbW9uSlNFcnJvcihlcnIsIGZpbGVuYW1lKTtcblxuICAgICAgICAgICAgaWYgKCEoZXJyIGluc3RhbmNlb2YgQVBJRXJyb3IpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUZXN0Q29tcGlsYXRpb25FcnJvcihzdGFja0NsZWFuaW5nSG9vay5jbGVhbkVycm9yKGVycikpO1xuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICB0aGlzLl9yZW1vdmVSZXF1aXJlSG9vaygpO1xuICAgICAgICAgICAgc3RhY2tDbGVhbmluZ0hvb2suZW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuZXNtKVxuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUdsb2JhbEFQSSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRlc3RGaWxlLmdldFRlc3RzKCk7XG4gICAgfVxuXG5cbiAgICBwcmVjb21waWxlICh0ZXN0RmlsZXNJbmZvKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb21waWxlQ29kZUZvclRlc3RGaWxlcyh0ZXN0RmlsZXNJbmZvKTtcbiAgICB9XG5cbiAgICBleGVjdXRlIChjb21waWxlZENvZGUsIGZpbGVuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ydW5Db21waWxlZENvZGUoY29tcGlsZWRDb2RlLCBmaWxlbmFtZSk7XG4gICAgfVxuXG4gICAgYXN5bmMgY29tcGlsZSAoY29kZSwgZmlsZW5hbWUpIHtcbiAgICAgICAgY29uc3QgW2NvbXBpbGVkQ29kZV0gPSBhd2FpdCB0aGlzLnByZWNvbXBpbGUoW3sgY29kZSwgZmlsZW5hbWUgfV0pO1xuXG4gICAgICAgIGlmIChjb21waWxlZENvZGUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5leGVjdXRlKGNvbXBpbGVkQ29kZSwgZmlsZW5hbWUpO1xuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBfaGFzVGVzdHMgKGNvZGUpIHtcbiAgICAgICAgcmV0dXJuIEZJWFRVUkVfUkUudGVzdChjb2RlKSAmJiBURVNUX1JFLnRlc3QoY29kZSk7XG4gICAgfVxuXG4gICAgY2xlYW5VcCAoKSB7XG4gICAgICAgIHRoaXMuY2FjaGUgPSB7fTtcbiAgICB9XG59XG4iXX0=