UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

196 lines 27.7 kB
"use strict"; 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=