"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TestFileParserBase = exports.Test = exports.Fixture = void 0; const promisified_functions_1 = require("../../utils/promisified-functions"); const util_1 = require("util"); const runtime_1 = require("../../errors/runtime"); const types_1 = require("../../errors/types"); const METHODS_SPECIFYING_NAME = ['only', 'skip']; const COMPUTED_NAME_TEXT_TMP = '(line: %s)'; const SKIP_PROPERTY_NAME = 'skip'; function getLoc(loc) { // NOTE: Don't modify the Babel's parser data structure const locCopy = Object.assign({}, loc); // NOTE: 'fileName' and 'identifierName' fields with 'undefined' values added in the SourceLocation class constructor. // https://github.com/babel/babel/blob/d51aa6d76177b544590cdfe3868f9f4d33d8813d/packages/babel-parser/src/util/location.js#L22 // Since this is useless information, we remove it. delete locCopy.filename; delete locCopy.identifierName; delete locCopy.start.index; delete locCopy.end.index; return locCopy; } class Fixture { constructor(name, start, end, loc, meta, isSkipped) { this.name = name; this.loc = getLoc(loc); this.start = start; this.end = end; this.meta = meta; this.tests = []; this.isSkipped = !!isSkipped; } } exports.Fixture = Fixture; class Test { constructor(name, start, end, loc, meta, isSkipped) { this.name = name; this.loc = getLoc(loc); this.start = start; this.end = end; this.meta = meta; this.isSkipped = !!isSkipped; } } exports.Test = Test; class TestFileParserBase { constructor(tokenType) { this.tokenType = tokenType; } static formatComputedName(line) { return (0, util_1.format)(COMPUTED_NAME_TEXT_TMP, line); } isAsyncFn( /* token */) { throw new Error('Not implemented'); } getRValue( /* token */) { throw new Error('Not implemented'); } getFunctionBody( /* token */) { throw new Error('Not implemented'); } formatFnData( /* name, value, token */) { throw new Error('Not implemented'); } analyzeMemberExp( /* token */) { throw new Error('Not implemented'); } formatFnArg( /* arg */) { throw new Error('Not implemented'); } getFnCall( /* token */) { throw new Error('Not implemented'); } getTaggedTemplateExp( /* token */) { throw new Error('Not implemented'); } analyzeFnCall( /* token */) { throw new Error('Not implemented'); } parse( /* filePath, code */) { throw new Error('Not implemented'); } getTokenType( /* token */) { throw new Error('Not implemented'); } getCalleeToken( /* token */) { throw new Error('Not implemented'); } getMemberFnName() { throw new Error('Not implemented'); } getKeyValue() { throw new Error('Not implemented'); } getStringValue() { throw new Error('Not implemented'); } isApiFn(fn) { return fn === 'fixture' || fn === 'test'; } serializeObjExp(token) { if (this.getTokenType(token) !== this.tokenType.ObjectLiteralExpression) return {}; return token.properties.reduce((obj, prop) => { const { key, value } = this.getKeyValue(prop); if (typeof value !== 'string') return {}; obj[key] = value; return obj; }, {}); } processMetaArgs(token) { if (this.getTokenType(token) !== this.tokenType.CallExpression) return null; const args = token.arguments; let meta = {}; if (args.length === 2) { const value = this.getStringValue(args[1]); if (typeof value !== 'string') return {}; meta = { [this.formatFnArg(args[0])]: value }; } else if (args.length === 1) meta = this.serializeObjExp(args[0]); return meta; } getMetaInfo(callStack) { return callStack.reduce((metaCalls, exp) => { if (this.getTokenType(exp) !== this.tokenType.CallExpression) return metaCalls; const callee = this.getCalleeToken(exp); const calleeType = this.getTokenType(callee); const isCalleeMemberExp = calleeType === this.tokenType.PropertyAccessExpression; if (isCalleeMemberExp && this.getMemberFnName(exp) === 'meta') return [this.processMetaArgs(exp)].concat(metaCalls); return metaCalls; }, []); } static isSkipped(originalToken, token = originalToken) { var _a, _b; const needSkip = ((_a = token === null || token === void 0 ? void 0 : token.property) === null || _a === void 0 ? void 0 : _a.name) === SKIP_PROPERTY_NAME || ((_b = token === null || token === void 0 ? void 0 : token.name) === null || _b === void 0 ? void 0 : _b.text) === SKIP_PROPERTY_NAME; if (!needSkip) { token = token.callee || token.tag || token.object || token.expression; return token ? TestFileParserBase.isSkipped(originalToken, token) : false; } return true; } checkExpDefineTargetName(type, apiFn) { //NOTE: fixture('fixtureName').chainFn or test('testName').chainFn const isDirectCall = type === this.tokenType.Identifier; //NOTE: fixture.skip('fixtureName'), test.only('testName') etc. const isMemberCall = type === this.tokenType.PropertyAccessExpression && METHODS_SPECIFYING_NAME.indexOf(apiFn) > -1; //NOTE: fixture.before().after()('fixtureName'), test.before()`testName`.after() etc. const isTailCall = type === this.tokenType.CallExpression; return isDirectCall || isMemberCall || isTailCall; } analyzeToken(token) { const tokenType = this.tokenType; const currTokenType = this.getTokenType(token); switch (currTokenType) { case tokenType.ExpressionStatement: case tokenType.TypeAssertionExpression: return this.analyzeToken(token.expression); case tokenType.FunctionDeclaration: case tokenType.FunctionExpression: if (this.isAsyncFn(token)) return null; return this.getFunctionBody(token).map(this.analyzeToken, this); case tokenType.VariableDeclaration: case tokenType.VariableStatement: { const variableValue = this.getRValue(token); // Skip variable declarations like `var foo;` return variableValue ? this.analyzeToken(variableValue) : null; } case tokenType.CallExpression: case tokenType.PropertyAccessExpression: case tokenType.TaggedTemplateExpression: return this.analyzeFnCall(token); case tokenType.ReturnStatement: return token.argument ? this.analyzeToken(token.argument) : null; } return null; } collectTestCafeCalls(astBody) { let calls = []; astBody.forEach(token => { const callExps = this.analyzeToken(token); if (callExps) calls = calls.concat(callExps); }); return calls; } analyze(astBody) { const fixtures = []; const testCafeAPICalls = this.collectTestCafeCalls(astBody); testCafeAPICalls.forEach(call => { if (!call || typeof call.value !== 'string') return; if (call.fnName === 'fixture') { fixtures.push(new Fixture(call.value, call.start, call.end, call.loc, call.meta, call.isSkipped)); return; } if (!fixtures.length) return; // NOTE: If the fixture is skipped, mark all the tests in the fixture skipped, otherwise, use the current test identifier const currentFixture = fixtures[fixtures.length - 1]; const testIsSkipped = currentFixture.isSkipped || call.isSkipped; const test = new Test(call.value, call.start, call.end, call.loc, call.meta, testIsSkipped); currentFixture.tests.push(test); }); return fixtures; } async readFile(filePath) { let fileContent = ''; try { fileContent = await (0, promisified_functions_1.readFile)(filePath, 'utf8'); } catch (err) { throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindSpecifiedTestSource, filePath); } return fileContent; } async getTestList(filePath) { const fileContent = await this.readFile(filePath); return this.parse(fileContent); } getTestListFromCode(code) { return this.parse(code); } } exports.TestFileParserBase = TestFileParserBase; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1maWxlLXBhcnNlci1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBpbGVyL3Rlc3QtZmlsZS90ZXN0LWZpbGUtcGFyc2VyLWJhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkVBQTZEO0FBQzdELCtCQUE4QjtBQUM5QixrREFBb0Q7QUFDcEQsOENBQW9EO0FBRXBELE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDakQsTUFBTSxzQkFBc0IsR0FBSSwyQkFBMkIsQ0FBQztBQUM1RCxNQUFNLGtCQUFrQixHQUFRLE1BQU0sQ0FBQztBQUV2QyxTQUFTLE1BQU0sQ0FBRSxHQUFHO0lBQ2hCLHVEQUF1RDtJQUN2RCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUV2QyxzSEFBc0g7SUFDdEgsOEhBQThIO0lBQzlILG1EQUFtRDtJQUNuRCxPQUFPLE9BQU8sQ0FBQyxRQUFRLENBQUM7SUFDeEIsT0FBTyxPQUFPLENBQUMsY0FBYyxDQUFDO0lBQzlCLE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFDM0IsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztJQUV6QixPQUFPLE9BQU8sQ0FBQztBQUNuQixDQUFDO0FBRUQsTUFBYSxPQUFPO0lBQ2hCLFlBQWEsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFTO1FBQy9DLElBQUksQ0FBQyxJQUFJLEdBQVEsSUFBSSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxHQUFHLEdBQVMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLEdBQU8sS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxHQUFHLEdBQVMsR0FBRyxDQUFDO1FBQ3JCLElB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SyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQyxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sUUFBUSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUSxDQUFFLFFBQVE7UUFDcEIsSUFBSSxXQUFXLEdBQUcsRUFBRSxDQUFDO1FBRXJCLElBQUk7WUFDQSxXQUFXLEdBQUcsTUFBTSxJQUFBLGdDQUFRLEVBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ2xEO1FBRUQsT0FBTyxHQUFHLEVBQUU7WUFDUixNQUFNLElBQUksc0JBQVksQ0FBQyxzQkFBYyxDQUFDLDZCQUE2QixFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQ2xGO1FBRUQsT0FBTyxXQUFXLENBQUM7SUFDdkIsQ0FBQztJQUVELEtBQUssQ0FBQyxXQUFXLENBQUUsUUFBUTtRQUN2QixNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFbEQsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRCxtQkFBbUIsQ0FBRSxJQUFJO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QixDQUFDO0NBQ0o7QUF4UEQsZ0RBd1BDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVhZEZpbGUgfSBmcm9tICcuLi8uLi91dGlscy9wcm9taXNpZmllZC1mdW5jdGlvbnMnO1xuaW1wb3J0IHsgZm9ybWF0IH0gZnJvbSAndXRpbCc7XG5pbXBvcnQgeyBHZW5lcmFsRXJyb3IgfSBmcm9tICcuLi8uLi9lcnJvcnMvcnVudGltZSc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uLy4uL2Vycm9ycy90eXBlcyc7XG5cbmNvbnN0IE1FVEhPRFNfU1BFQ0lGWUlOR19OQU1FID0gWydvbmx5JywgJ3NraXAnXTtcbmNvbnN0IENPTVBVVEVEX05BTUVfVEVYVF9UTVAgID0gJzxjb21wdXRlZCBuYW1lPihsaW5lOiAlcyknO1xuY29uc3QgU0tJUF9QUk9QRVJUWV9OQU1FICAgICAgPSAnc2tpcCc7XG5cbmZ1bmN0aW9uIGdldExvYyAobG9jKSB7XG4gICAgLy8gTk9URTogRG9uJ3QgbW9kaWZ5IHRoZSBCYWJlbCdzIHBhcnNlciBkYXRhIHN0cnVjdHVyZVxuICAgIGNvbnN0IGxvY0NvcHkgPSBPYmplY3QuYXNzaWduKHt9LCBsb2MpO1xuXG4gICAgLy8gTk9URTogJ2ZpbGVOYW1lJyBhbmQgJ2lkZW50aWZpZXJOYW1lJyBmaWVsZHMgd2l0aCAndW5kZWZpbmVkJyB2YWx1ZXMgYWRkZWQgaW4gdGhlIFNvdXJjZUxvY2F0aW9uIGNsYXNzIGNvbnN0cnVjdG9yLlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iYWJlbC9iYWJlbC9ibG9iL2Q1MWFhNmQ3NjE3N2I1NDQ1OTBjZGZlMzg2OGY5ZjRkMzNkODgxM2QvcGFja2FnZXMvYmFiZWwtcGFyc2VyL3NyYy91dGlsL2xvY2F0aW9uLmpzI0wyMlxuICAgIC8vIFNpbmNlIHRoaXMgaXMgdXNlbGVzcyBpbmZvcm1hdGlvbiwgd2UgcmVtb3ZlIGl0LlxuICAgIGRlbGV0ZSBsb2NDb3B5LmZpbGVuYW1lO1xuICAgIGRlbGV0ZSBsb2NDb3B5LmlkZW50aWZpZXJOYW1lO1xuICAgIGRlbGV0ZSBsb2NDb3B5LnN0YXJ0LmluZGV4O1xuICAgIGRlbGV0ZSBsb2NDb3B5LmVuZC5pbmRleDtcblxuICAgIHJldHVybiBsb2NDb3B5O1xufVxuXG5leHBvcnQgY2xhc3MgRml4dHVyZSB7XG4gICAgY29uc3RydWN0b3IgKG5hbWUsIHN0YXJ0LCBlbmQsIGxvYywgbWV0YSwgaXNTa2lwcGVkKSB7XG4gICAgICAgIHRoaXMubmFtZSAgICAgID0gbmFtZTtcbiAgICAgICAgdGhpcy5sb2MgICAgICAgPSBnZXRMb2MobG9jKTtcbiAgICAgICAgdGhpcy5zdGFydCAgICAgPSBzdGFydDtcbiAgICAgICAgdGhpcy5lbmQgICAgICAgPSBlbmQ7XG4gICAgICAgIHRoaXMubWV0YSAgICAgID0gbWV0YTtcbiAgICAgICAgdGhpcy50ZXN0cyAgICAgPSBbXTtcbiAgICAgICAgdGhpcy5pc1NraXBwZWQgPSAhIWlzU2tpcHBlZDtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUZXN0IHtcbiAgICBjb25zdHJ1Y3RvciAobmFtZSwgc3RhcnQsIGVuZCwgbG9jLCBtZXRhLCBpc1NraXBwZWQpIHtcbiAgICAgICAgdGhpcy5uYW1lICAgICAgPSBuYW1lO1xuICAgICAgICB0aGlzLmxvYyAgICAgICA9IGdldExvYyhsb2MpO1xuICAgICAgICB0aGlzLnN0YXJ0ICAgICA9IHN0YXJ0O1xuICAgICAgICB0aGlzLmVuZCAgICAgICA9IGVuZDtcbiAgICAgICAgdGhpcy5tZXRhICAgICAgPSBtZXRhO1xuICAgICAgICB0aGlzLmlzU2tpcHBlZCA9ICEhaXNTa2lwcGVkO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRlc3RGaWxlUGFyc2VyQmFzZSB7XG4gICAgY29uc3RydWN0b3IgKHRva2VuVHlwZSkge1xuICAgICAgICB0aGlzLnRva2VuVHlwZSA9IHRva2VuVHlwZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZm9ybWF0Q29tcHV0ZWROYW1lIChsaW5lKSB7XG4gICAgICAgIHJldHVybiBmb3JtYXQoQ09NUFVURURfTkFNRV9URVhUX1RNUCwgbGluZSk7XG4gICAgfVxuXG4gICAgaXNBc3luY0ZuICgvKiB0b2tlbiAqLykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIH1cblxuICAgIGdldFJWYWx1ZSAoLyogdG9rZW4gKi8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBnZXRGdW5jdGlvbkJvZHkgKC8qIHRva2VuICovKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgZm9ybWF0Rm5EYXRhICgvKiBuYW1lLCB2YWx1ZSwgdG9rZW4gKi8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBhbmFseXplTWVtYmVyRXhwICgvKiB0b2tlbiAqLykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIH1cblxuICAgIGZvcm1hdEZuQXJnICgvKiBhcmcgKi8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBnZXRGbkNhbGwgKC8qIHRva2VuICovKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgZ2V0VGFnZ2VkVGVtcGxhdGVFeHAgKC8qIHRva2VuICovKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgYW5hbHl6ZUZuQ2FsbCAoLyogdG9rZW4gKi8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBwYXJzZSAoLyogZmlsZVBhdGgsIGNvZGUgKi8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBnZXRUb2tlblR5cGUgKC8qIHRva2VuICovKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgZ2V0Q2FsbGVlVG9rZW4gKC8qIHRva2VuICovKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgZ2V0TWVtYmVyRm5OYW1lICgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBnZXRLZXlWYWx1ZSAoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgZ2V0U3RyaW5nVmFsdWUgKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIH1cblxuICAgIGlzQXBpRm4gKGZuKSB7XG4gICAgICAgIHJldHVybiBmbiA9PT0gJ2ZpeHR1cmUnIHx8IGZuID09PSAndGVzdCc7XG4gICAgfVxuXG4gICAgc2VyaWFsaXplT2JqRXhwICh0b2tlbikge1xuICAgICAgICBpZiAodGhpcy5nZXRUb2tlblR5cGUodG9rZW4pICE9PSB0aGlzLnRva2VuVHlwZS5PYmplY3RMaXRlcmFsRXhwcmVzc2lvbilcbiAgICAgICAgICAgIHJldHVybiB7fTtcblxuICAgICAgICByZXR1cm4gdG9rZW4ucHJvcGVydGllcy5yZWR1Y2UoKG9iaiwgcHJvcCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBrZXksIHZhbHVlIH0gPSB0aGlzLmdldEtleVZhbHVlKHByb3ApO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykgcmV0dXJuIHt9O1xuXG4gICAgICAgICAgICBvYmpba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICB9LCB7fSk7XG4gICAgfVxuXG4gICAgcHJvY2Vzc01ldGFBcmdzICh0b2tlbikge1xuICAgICAgICBpZiAodGhpcy5nZXRUb2tlblR5cGUodG9rZW4pICE9PSB0aGlzLnRva2VuVHlwZS5DYWxsRXhwcmVzc2lvbilcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICAgIGNvbnN0IGFyZ3MgPSB0b2tlbi5hcmd1bWVudHM7XG5cbiAgICAgICAgbGV0IG1ldGEgPSB7fTtcblxuICAgICAgICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXRTdHJpbmdWYWx1ZShhcmdzWzFdKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHJldHVybiB7fTtcblxuICAgICAgICAgICAgbWV0YSA9IHsgW3RoaXMuZm9ybWF0Rm5BcmcoYXJnc1swXSldOiB2YWx1ZSB9O1xuICAgICAgICB9XG5cbiAgICAgICAgZWxzZSBpZiAoYXJncy5sZW5ndGggPT09IDEpXG4gICAgICAgICAgICBtZXRhID0gdGhpcy5zZXJpYWxpemVPYmpFeHAoYXJnc1swXSk7XG5cbiAgICAgICAgcmV0dXJuIG1ldGE7XG4gICAgfVxuXG4gICAgZ2V0TWV0YUluZm8gKGNhbGxTdGFjaykge1xuICAgICAgICByZXR1cm4gY2FsbFN0YWNrLnJlZHVjZSgobWV0YUNhbGxzLCBleHApID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldFRva2VuVHlwZShleHApICE9PSB0aGlzLnRva2VuVHlwZS5DYWxsRXhwcmVzc2lvbilcbiAgICAgICAgICAgICAgICByZXR1cm4gbWV0YUNhbGxzO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsZWUgICAgICAgICAgICA9IHRoaXMuZ2V0Q2FsbGVlVG9rZW4oZXhwKTtcbiAgICAgICAgICAgIGNvbnN0IGNhbGxlZVR5cGUgICAgICAgID0gdGhpcy5nZXRUb2tlblR5cGUoY2FsbGVlKTtcbiAgICAgICAgICAgIGNvbnN0IGlzQ2FsbGVlTWVtYmVyRXhwID0gY2FsbGVlVHlwZSA9PT0gdGhpcy50b2tlblR5cGUuUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uO1xuXG4gICAgICAgICAgICBpZiAoaXNDYWxsZWVNZW1iZXJFeHAgJiYgdGhpcy5nZXRNZW1iZXJGbk5hbWUoZXhwKSA9PT0gJ21ldGEnKVxuICAgICAgICAgICAgICAgIHJldHVybiBbdGhpcy5wcm9jZXNzTWV0YUFyZ3MoZXhwKV0uY29uY2F0KG1ldGFDYWxscyk7XG5cbiAgICAgICAgICAgIHJldHVybiBtZXRhQ2FsbHM7XG4gICAgICAgIH0sIFtdKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNTa2lwcGVkIChvcmlnaW5hbFRva2VuLCB0b2tlbiA9IG9yaWdpbmFsVG9rZW4pIHtcbiAgICAgICAgY29uc3QgbmVlZFNraXAgPSB0b2tlbj8ucHJvcGVydHk/Lm5hbWUgPT09IFNLSVBfUFJPUEVSVFlfTkFNRSB8fCB0b2tlbj8ubmFtZT8udGV4dCA9PT0gU0tJUF9QUk9QRVJUWV9OQU1FO1xuXG4gICAgICAgIGlmICghbmVlZFNraXApIHtcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW4uY2FsbGVlIHx8IHRva2VuLnRhZyB8fCB0b2tlbi5vYmplY3QgfHwgdG9rZW4uZXhwcmVzc2lvbjtcblxuICAgICAgICAgICAgcmV0dXJuIHRva2VuID8gVGVzdEZpbGVQYXJzZXJCYXNlLmlzU2tpcHBlZChvcmlnaW5hbFRva2VuLCB0b2tlbikgOiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGNoZWNrRXhwRGVmaW5lVGFyZ2V0TmFtZSAodHlwZSwgYXBpRm4pIHtcbiAgICAgICAgLy9OT1RFOiBmaXh0dXJlKCdmaXh0dXJlTmFtZScpLmNoYWluRm4gb3IgdGVzdCgndGVzdE5hbWUnKS5jaGFpbkZuXG4gICAgICAgIGNvbnN0IGlzRGlyZWN0Q2FsbCA9IHR5cGUgPT09IHRoaXMudG9rZW5UeXBlLklkZW50aWZpZXI7XG5cbiAgICAgICAgLy9OT1RFOiBmaXh0dXJlLnNraXAoJ2ZpeHR1cmVOYW1lJyksIHRlc3Qub25seSgndGVzdE5hbWUnKSBldGMuXG4gICAgICAgIGNvbnN0IGlzTWVtYmVyQ2FsbCA9IHR5cGUgPT09IHRoaXMudG9rZW5UeXBlLlByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbiAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNRVRIT0RTX1NQRUNJRllJTkdfTkFNRS5pbmRleE9mKGFwaUZuKSA+IC0xO1xuXG4gICAgICAgIC8vTk9URTogZml4dHVyZS5iZWZvcmUoKS5hZnRlcigpKCdmaXh0dXJlTmFtZScpLCB0ZXN0LmJlZm9yZSgpYHRlc3ROYW1lYC5hZnRlcigpIGV0Yy5cbiAgICAgICAgY29uc3QgaXNUYWlsQ2FsbCA9IHR5cGUgPT09IHRoaXMudG9rZW5UeXBlLkNhbGxFeHByZXNzaW9uO1xuXG4gICAgICAgIHJldHVybiBpc0RpcmVjdENhbGwgfHwgaXNNZW1iZXJDYWxsIHx8IGlzVGFpbENhbGw7XG4gICAgfVxuXG4gICAgYW5hbHl6ZVRva2VuICh0b2tlbikge1xuICAgICAgICBjb25zdCB0b2tlblR5cGUgICAgID0gdGhpcy50b2tlblR5cGU7XG4gICAgICAgIGNvbnN0IGN1cnJUb2tlblR5cGUgPSB0aGlzLmdldFRva2VuVHlwZSh0b2tlbik7XG5cbiAgICAgICAgc3dpdGNoIChjdXJyVG9rZW5UeXBlKSB7XG4gICAgICAgICAgICBjYXNlIHRva2VuVHlwZS5FeHByZXNzaW9uU3RhdGVtZW50OlxuICAgICAgICAgICAgY2FzZSB0b2tlblR5cGUuVHlwZUFzc2VydGlvbkV4cHJlc3Npb246XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYW5hbHl6ZVRva2VuKHRva2VuLmV4cHJlc3Npb24pO1xuXG4gICAgICAgICAgICBjYXNlIHRva2VuVHlwZS5GdW5jdGlvbkRlY2xhcmF0aW9uOlxuICAgICAgICAgICAgY2FzZSB0b2tlblR5cGUuRnVuY3Rpb25FeHByZXNzaW9uOlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQXN5bmNGbih0b2tlbikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RnVuY3Rpb25Cb2R5KHRva2VuKS5tYXAodGhpcy5hbmFseXplVG9rZW4sIHRoaXMpO1xuXG4gICAgICAgICAgICBjYXNlIHRva2VuVHlwZS5WYXJpYWJsZURlY2xhcmF0aW9uOlxuICAgICAgICAgICAgY2FzZSB0b2tlblR5cGUuVmFyaWFibGVTdGF0ZW1lbnQ6IHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YXJpYWJsZVZhbHVlID0gdGhpcy5nZXRSVmFsdWUodG9rZW4pOyAvLyBTa2lwIHZhcmlhYmxlIGRlY2xhcmF0aW9ucyBsaWtlIGB2YXIgZm9vO2BcblxuICAgICAgICAgICAgICAgIHJldHVybiB2YXJpYWJsZVZhbHVlID8gdGhpcy5hbmFseXplVG9rZW4odmFyaWFibGVWYWx1ZSkgOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSB0b2tlblR5cGUuQ2FsbEV4cHJlc3Npb246XG4gICAgICAgICAgICBjYXNlIHRva2VuVHlwZS5Qcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb246XG4gICAgICAgICAgICBjYXNlIHRva2VuVHlwZS5UYWdnZWRUZW1wbGF0ZUV4cHJlc3Npb246XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYW5hbHl6ZUZuQ2FsbCh0b2tlbik7XG5cbiAgICAgICAgICAgIGNhc2UgdG9rZW5UeXBlLlJldHVyblN0YXRlbWVudDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9rZW4uYXJndW1lbnQgPyB0aGlzLmFuYWx5emVUb2tlbih0b2tlbi5hcmd1bWVudCkgOiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29sbGVjdFRlc3RDYWZlQ2FsbHMgKGFzdEJvZHkpIHtcbiAgICAgICAgbGV0IGNhbGxzID0gW107XG5cbiAgICAgICAgYXN0Qm9keS5mb3JFYWNoKHRva2VuID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNhbGxFeHBzID0gdGhpcy5hbmFseXplVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAoY2FsbEV4cHMpXG4gICAgICAgICAgICAgICAgY2FsbHMgPSBjYWxscy5jb25jYXQoY2FsbEV4cHMpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gY2FsbHM7XG4gICAgfVxuXG4gICAgYW5hbHl6ZSAoYXN0Qm9keSkge1xuICAgICAgICBjb25zdCBmaXh0dXJlcyAgICAgICAgID0gW107XG4gICAgICAgIGNvbnN0IHRlc3RDYWZlQVBJQ2FsbHMgPSB0aGlzLmNvbGxlY3RUZXN0Q2FmZUNhbGxzKGFzdEJvZHkpO1xuXG4gICAgICAgIHRlc3RDYWZlQVBJQ2FsbHMuZm9yRWFjaChjYWxsID0+IHtcbiAgICAgICAgICAgIGlmICghY2FsbCB8fCB0eXBlb2YgY2FsbC52YWx1ZSAhPT0gJ3N0cmluZycpIHJldHVybjtcblxuICAgICAgICAgICAgaWYgKGNhbGwuZm5OYW1lID09PSAnZml4dHVyZScpIHtcbiAgICAgICAgICAgICAgICBmaXh0dXJlcy5wdXNoKG5ldyBGaXh0dXJlKGNhbGwudmFsdWUsIGNhbGwuc3RhcnQsIGNhbGwuZW5kLCBjYWxsLmxvYywgY2FsbC5tZXRhLCBjYWxsLmlzU2tpcHBlZCkpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWZpeHR1cmVzLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgICAgICAgICAvLyBOT1RFOiBJZiB0aGUgZml4dHVyZSBpcyBza2lwcGVkLCBtYXJrIGFsbCB0aGUgdGVzdHMgaW4gdGhlIGZpeHR1cmUgc2tpcHBlZCwgb3RoZXJ3aXNlLCB1c2UgdGhlIGN1cnJlbnQgdGVzdCBpZGVudGlmaWVyXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50Rml4dHVyZSA9IGZpeHR1cmVzW2ZpeHR1cmVzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgY29uc3QgdGVzdElzU2tpcHBlZCAgPSBjdXJyZW50Rml4dHVyZS5pc1NraXBwZWQgfHwgY2FsbC5pc1NraXBwZWQ7XG4gICAgICAgICAgICBjb25zdCB0ZXN0ICAgICAgICAgICA9IG5ldyBUZXN0KGNhbGwudmFsdWUsIGNhbGwuc3RhcnQsIGNhbGwuZW5kLCBjYWxsLmxvYywgY2FsbC5tZXRhLCB0ZXN0SXNTa2lwcGVkKTtcblxuICAgICAgICAgICAgY3VycmVudEZpeHR1cmUudGVzdHMucHVzaCh0ZXN0KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGZpeHR1cmVzO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRGaWxlIChmaWxlUGF0aCkge1xuICAgICAgICBsZXQgZmlsZUNvbnRlbnQgPSAnJztcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZmlsZUNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZShmaWxlUGF0aCwgJ3V0ZjgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuY2Fubm90RmluZFNwZWNpZmllZFRlc3RTb3VyY2UsIGZpbGVQYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmaWxlQ29udGVudDtcbiAgICB9XG5cbiAgICBhc3luYyBnZXRUZXN0TGlzdCAoZmlsZVBhdGgpIHtcbiAgICAgICAgY29uc3QgZmlsZUNvbnRlbnQgPSBhd2FpdCB0aGlzLnJlYWRGaWxlKGZpbGVQYXRoKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShmaWxlQ29udGVudCk7XG4gICAgfVxuXG4gICAgZ2V0VGVzdExpc3RGcm9tQ29kZSAoY29kZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShjb2RlKTtcbiAgICB9XG59XG4iXX0=