UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

98 lines 16.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Quarantine = exports.getQuarantineOptions = exports.validateQuarantineOptions = void 0; const quarantine_option_names_1 = __importDefault(require("../../configuration/quarantine-option-names")); const types_1 = require("../../errors/types"); const runtime_1 = require("../../errors/runtime"); const boolean_or_object_option_1 = require("./boolean-or-object-option"); const DEFAULT_ATTEMPT_LIMIT = 5; const DEFAULT_THRESHOLD = 3; const MIN_ATTEMPT_LIMIT = 2; const MIN_SUCCESS_THRESHOLD = 1; function _isQuarantineOption(option) { return Object.values(quarantine_option_names_1.default).includes(option); } function validateQuarantineOptions(options) { for (const key in options) { if (!_isQuarantineOption(key)) throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidQuarantineOption, key); } const attemptLimit = typeof options.attemptLimit === 'number' ? options.attemptLimit : DEFAULT_ATTEMPT_LIMIT; const successThreshold = typeof options.successThreshold === 'number' ? options.successThreshold : DEFAULT_THRESHOLD; if (attemptLimit < MIN_ATTEMPT_LIMIT) throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidAttemptLimitValue, quarantine_option_names_1.default.attemptLimit, MIN_ATTEMPT_LIMIT); if (successThreshold < MIN_SUCCESS_THRESHOLD) throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidSuccessThresholdValue, quarantine_option_names_1.default.successThreshold, MIN_SUCCESS_THRESHOLD); if (successThreshold >= attemptLimit) throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidQuarantineParametersRatio, attemptLimit, successThreshold); } exports.validateQuarantineOptions = validateQuarantineOptions; async function getQuarantineOptions(optionName, options) { const onOptionParsed = async (key, value) => { if (!key || !value) throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.optionValueIsNotValidKeyValue, optionName); return Number(value); }; return await (0, boolean_or_object_option_1.getBooleanOrObjectOption)(optionName, options, { onOptionParsed, skipOptionValueTypeConversion: true, }, validateQuarantineOptions); } exports.getQuarantineOptions = getQuarantineOptions; class Quarantine { constructor() { this.attempts = []; this.attemptLimit = DEFAULT_ATTEMPT_LIMIT; this.successThreshold = DEFAULT_THRESHOLD; this.failureThreshold = DEFAULT_THRESHOLD; } getFailedAttempts() { return this.attempts.filter(({ errors }) => !!errors.length); } getPassedAttempts() { return this.attempts.filter(({ errors }) => errors.length === 0); } setCustomParameters(attemptLimit, successThreshold) { const needToUpdateTestRunThreshold = typeof attemptLimit === 'number'; const needToUpdatePassedQuarantineThreshold = typeof successThreshold === 'number'; const needToRecalculateFailedThreshold = needToUpdateTestRunThreshold || needToUpdatePassedQuarantineThreshold; if (needToUpdateTestRunThreshold) this.attemptLimit = attemptLimit; if (needToUpdatePassedQuarantineThreshold) this.successThreshold = successThreshold; if (needToRecalculateFailedThreshold) this._setFailedThreshold(); } getNextAttemptNumber() { return this.attempts.length + 1; } isThresholdReached(extraErrors) { const { passedTimes, failedTimes } = this._getAttemptsResult(extraErrors); const successThresholdReached = passedTimes >= this.successThreshold; const failureThresholdReached = failedTimes >= this.failureThreshold; return successThresholdReached || failureThresholdReached; } isFirstAttemptSuccessful(extraErrors) { const { failedTimes, passedTimes } = this._getAttemptsResult(extraErrors); return failedTimes === 0 && passedTimes > 0; } _getAttemptsResult(extraErrors) { let failedTimes = this.getFailedAttempts().length; let passedTimes = this.getPassedAttempts().length; if (extraErrors) { if (extraErrors.length) failedTimes += extraErrors.length; else passedTimes += 1; } return { failedTimes, passedTimes }; } _setFailedThreshold() { this.failureThreshold = this.attemptLimit - this.successThreshold + 1; } } exports.Quarantine = Quarantine; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVhcmFudGluZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9nZXQtb3B0aW9ucy9xdWFyYW50aW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDBHQUFrRjtBQUNsRiw4Q0FBb0Q7QUFDcEQsa0RBQW9EO0FBR3BELHlFQUFzRTtBQUV0RSxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQztBQUNoQyxNQUFNLGlCQUFpQixHQUFPLENBQUMsQ0FBQztBQUNoQyxNQUFNLGlCQUFpQixHQUFPLENBQUMsQ0FBQztBQUNoQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQztBQUVoQyxTQUFTLG1CQUFtQixDQUFFLE1BQWM7SUFDeEMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLGlDQUF1QixDQUFDLENBQUMsUUFBUSxDQUFDLE1BQWlDLENBQUMsQ0FBQztBQUM5RixDQUFDO0FBRUQsU0FBZ0IseUJBQXlCLENBQUUsT0FBb0M7SUFDM0UsS0FBSyxNQUFNLEdBQUcsSUFBSSxPQUFPLEVBQUU7UUFDdkIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQztZQUN6QixNQUFNLElBQUksc0JBQVksQ0FBQyxzQkFBYyxDQUFDLHVCQUF1QixFQUFFLEdBQUcsQ0FBQyxDQUFDO0tBQzNFO0lBRUQsTUFBTSxZQUFZLEdBQU8sT0FBTyxPQUFPLENBQUMsWUFBWSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMscUJBQXFCLENBQUM7SUFDakgsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLE9BQU8sQ0FBQyxnQkFBZ0IsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUM7SUFFckgsSUFBSSxZQUFZLEdBQUcsaUJBQWlCO1FBQ2hDLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsd0JB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QkFBdUIsQ0FBQztJQUM5RCxDQUFDO0lBRU0sd0JBQXdCLENBQUUsV0FBNkM7UUFDMUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFMUUsT0FBTyxXQUFXLEtBQUssQ0FBQyxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVPLGtCQUFrQixDQUFFLFdBQThDO1FBQ3RFLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNsRCxJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxNQUFNLENBQUM7UUFFbEQsSUFBSSxXQUFXLEVBQUU7WUFDYixJQUFJLFdBQVcsQ0FBQyxNQUFNO2dCQUNsQixXQUFXLElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQzs7Z0JBRWxDLFdBQVcsSUFBSSxDQUFDLENBQUM7U0FDeEI7UUFFRCxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFTyxtQkFBbUI7UUFDdkIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQztJQUMxRSxDQUFDO0NBQ0o7QUFuRUQsZ0NBbUVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFFVQVJBTlRJTkVfT1BUSU9OX05BTUVTIGZyb20gJy4uLy4uL2NvbmZpZ3VyYXRpb24vcXVhcmFudGluZS1vcHRpb24tbmFtZXMnO1xuaW1wb3J0IHsgUlVOVElNRV9FUlJPUlMgfSBmcm9tICcuLi8uLi9lcnJvcnMvdHlwZXMnO1xuaW1wb3J0IHsgR2VuZXJhbEVycm9yIH0gZnJvbSAnLi4vLi4vZXJyb3JzL3J1bnRpbWUnO1xuaW1wb3J0IHsgRGljdGlvbmFyeSB9IGZyb20gJy4uLy4uL2NvbmZpZ3VyYXRpb24vaW50ZXJmYWNlcyc7XG5pbXBvcnQgVGVzdFJ1bkVycm9yRm9ybWF0dGFibGVBZGFwdGVyIGZyb20gJy4uLy4uL2Vycm9ycy90ZXN0LXJ1bi9mb3JtYXR0YWJsZS1hZGFwdGVyJztcbmltcG9ydCB7IGdldEJvb2xlYW5Pck9iamVjdE9wdGlvbiB9IGZyb20gJy4vYm9vbGVhbi1vci1vYmplY3Qtb3B0aW9uJztcblxuY29uc3QgREVGQVVMVF9BVFRFTVBUX0xJTUlUID0gNTtcbmNvbnN0IERFRkFVTFRfVEhSRVNIT0xEICAgICA9IDM7XG5jb25zdCBNSU5fQVRURU1QVF9MSU1JVCAgICAgPSAyO1xuY29uc3QgTUlOX1NVQ0NFU1NfVEhSRVNIT0xEID0gMTtcblxuZnVuY3Rpb24gX2lzUXVhcmFudGluZU9wdGlvbiAob3B0aW9uOiBzdHJpbmcpOiBvcHRpb24gaXMgUVVBUkFOVElORV9PUFRJT05fTkFNRVMge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKFFVQVJBTlRJTkVfT1BUSU9OX05BTUVTKS5pbmNsdWRlcyhvcHRpb24gYXMgUVVBUkFOVElORV9PUFRJT05fTkFNRVMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVRdWFyYW50aW5lT3B0aW9ucyAob3B0aW9uczogRGljdGlvbmFyeTxzdHJpbmcgfCBudW1iZXI+KTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gb3B0aW9ucykge1xuICAgICAgICBpZiAoIV9pc1F1YXJhbnRpbmVPcHRpb24oa2V5KSlcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuaW52YWxpZFF1YXJhbnRpbmVPcHRpb24sIGtleSk7XG4gICAgfVxuXG4gICAgY29uc3QgYXR0ZW1wdExpbWl0ICAgICA9IHR5cGVvZiBvcHRpb25zLmF0dGVtcHRMaW1pdCA9PT0gJ251bWJlcicgPyBvcHRpb25zLmF0dGVtcHRMaW1pdCA6IERFRkFVTFRfQVRURU1QVF9MSU1JVDtcbiAgICBjb25zdCBzdWNjZXNzVGhyZXNob2xkID0gdHlwZW9mIG9wdGlvbnMuc3VjY2Vzc1RocmVzaG9sZCA9PT0gJ251bWJlcicgPyBvcHRpb25zLnN1Y2Nlc3NUaHJlc2hvbGQgOiBERUZBVUxUX1RIUkVTSE9MRDtcblxuICAgIGlmIChhdHRlbXB0TGltaXQgPCBNSU5fQVRURU1QVF9MSU1JVClcbiAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5pbnZhbGlkQXR0ZW1wdExpbWl0VmFsdWUsIFFVQVJBTlRJTkVfT1BUSU9OX05BTUVTLmF0dGVtcHRMaW1pdCwgTUlOX0FUVEVNUFRfTElNSVQpO1xuXG4gICAgaWYgKHN1Y2Nlc3NUaHJlc2hvbGQgPCBNSU5fU1VDQ0VTU19USFJFU0hPTEQpXG4gICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuaW52YWxpZFN1Y2Nlc3NUaHJlc2hvbGRWYWx1ZSwgUVVBUkFOVElORV9PUFRJT05fTkFNRVMuc3VjY2Vzc1RocmVzaG9sZCwgTUlOX1NVQ0NFU1NfVEhSRVNIT0xEKTtcblxuICAgIGlmIChzdWNjZXNzVGhyZXNob2xkID49IGF0dGVtcHRMaW1pdClcbiAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5pbnZhbGlkUXVhcmFudGluZVBhcmFtZXRlcnNSYXRpbywgYXR0ZW1wdExpbWl0LCBzdWNjZXNzVGhyZXNob2xkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFF1YXJhbnRpbmVPcHRpb25zIChvcHRpb25OYW1lOiBzdHJpbmcsIG9wdGlvbnM6IHN0cmluZyB8IGJvb2xlYW4gfCBEaWN0aW9uYXJ5PHN0cmluZyB8IG51bWJlcj4pOiBQcm9taXNlPERpY3Rpb25hcnk8bnVtYmVyPiB8IGJvb2xlYW4+IHtcbiAgICBjb25zdCBvbk9wdGlvblBhcnNlZCA9IGFzeW5jIChrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gICAgICAgIGlmICgha2V5IHx8ICF2YWx1ZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMub3B0aW9uVmFsdWVJc05vdFZhbGlkS2V5VmFsdWUsIG9wdGlvbk5hbWUpO1xuXG4gICAgICAgIHJldHVybiBOdW1iZXIodmFsdWUpO1xuICAgIH07XG5cbiAgICByZXR1cm4gYXdhaXQgZ2V0Qm9vbGVhbk9yT2JqZWN0T3B0aW9uPG51bWJlcj4ob3B0aW9uTmFtZSwgb3B0aW9ucywge1xuICAgICAgICBvbk9wdGlvblBhcnNlZCxcbiAgICAgICAgc2tpcE9wdGlvblZhbHVlVHlwZUNvbnZlcnNpb246IHRydWUsXG4gICAgfSwgdmFsaWRhdGVRdWFyYW50aW5lT3B0aW9ucyk7XG59XG5cblxuaW50ZXJmYWNlIEF0dGVtcHRSZXN1bHQge1xuICAgIGZhaWxlZFRpbWVzOiBudW1iZXI7XG4gICAgcGFzc2VkVGltZXM6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFF1YXJhbnRpbmVBdHRlbXB0IHtcbiAgICB0ZXN0UnVuSWQ6IHN0cmluZztcbiAgICBlcnJvcnM6IFRlc3RSdW5FcnJvckZvcm1hdHRhYmxlQWRhcHRlcltdO1xufVxuXG5leHBvcnQgY2xhc3MgUXVhcmFudGluZSB7XG4gICAgcHVibGljIGF0dGVtcHRzOiBRdWFyYW50aW5lQXR0ZW1wdFtdO1xuICAgIHB1YmxpYyBhdHRlbXB0TGltaXQ6IG51bWJlcjtcbiAgICBwdWJsaWMgc3VjY2Vzc1RocmVzaG9sZDogbnVtYmVyO1xuICAgIHB1YmxpYyBmYWlsdXJlVGhyZXNob2xkOiBudW1iZXI7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IgKCkge1xuICAgICAgICB0aGlzLmF0dGVtcHRzICAgICAgICAgPSBbXTtcbiAgICAgICAgdGhpcy5hdHRlbXB0TGltaXQgICAgID0gREVGQVVMVF9BVFRFTVBUX0xJTUlUO1xuICAgICAgICB0aGlzLnN1Y2Nlc3NUaHJlc2hvbGQgPSBERUZBVUxUX1RIUkVTSE9MRDtcbiAgICAgICAgdGhpcy5mYWlsdXJlVGhyZXNob2xkID0gREVGQVVMVF9USFJFU0hPTEQ7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEZhaWxlZEF0dGVtcHRzICgpOiBRdWFyYW50aW5lQXR0ZW1wdFtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXR0ZW1wdHMuZmlsdGVyKCh7IGVycm9ycyB9KSA9PiAhIWVycm9ycy5sZW5ndGgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRQYXNzZWRBdHRlbXB0cyAoKTogUXVhcmFudGluZUF0dGVtcHRbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLmF0dGVtcHRzLmZpbHRlcigoeyBlcnJvcnMgfSkgPT4gZXJyb3JzLmxlbmd0aCA9PT0gMCk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldEN1c3RvbVBhcmFtZXRlcnMgKGF0dGVtcHRMaW1pdDogbnVtYmVyIHwgdW5kZWZpbmVkLCBzdWNjZXNzVGhyZXNob2xkOiBudW1iZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbmVlZFRvVXBkYXRlVGVzdFJ1blRocmVzaG9sZCAgICAgICAgICA9IHR5cGVvZiBhdHRlbXB0TGltaXQgPT09ICdudW1iZXInO1xuICAgICAgICBjb25zdCBuZWVkVG9VcGRhdGVQYXNzZWRRdWFyYW50aW5lVGhyZXNob2xkID0gdHlwZW9mIHN1Y2Nlc3NUaHJlc2hvbGQgPT09ICdudW1iZXInO1xuICAgICAgICBjb25zdCBuZWVkVG9SZWNhbGN1bGF0ZUZhaWxlZFRocmVzaG9sZCAgICAgID0gbmVlZFRvVXBkYXRlVGVzdFJ1blRocmVzaG9sZCB8fCBuZWVkVG9VcGRhdGVQYXNzZWRRdWFyYW50aW5lVGhyZXNob2xkO1xuXG4gICAgICAgIGlmIChuZWVkVG9VcGRhdGVUZXN0UnVuVGhyZXNob2xkKSB0aGlzLmF0dGVtcHRMaW1pdCA9IGF0dGVtcHRMaW1pdCBhcyBudW1iZXI7XG4gICAgICAgIGlmIChuZWVkVG9VcGRhdGVQYXNzZWRRdWFyYW50aW5lVGhyZXNob2xkKSB0aGlzLnN1Y2Nlc3NUaHJlc2hvbGQgPSBzdWNjZXNzVGhyZXNob2xkIGFzIG51bWJlcjtcbiAgICAgICAgaWYgKG5lZWRUb1JlY2FsY3VsYXRlRmFpbGVkVGhyZXNob2xkKSB0aGlzLl9zZXRGYWlsZWRUaHJlc2hvbGQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0TmV4dEF0dGVtcHROdW1iZXIgKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmF0dGVtcHRzLmxlbmd0aCArIDE7XG4gICAgfVxuXG4gICAgcHVibGljIGlzVGhyZXNob2xkUmVhY2hlZCAoZXh0cmFFcnJvcnM/OiBUZXN0UnVuRXJyb3JGb3JtYXR0YWJsZUFkYXB0ZXJbXSk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB7IHBhc3NlZFRpbWVzLCBmYWlsZWRUaW1lcyB9ID0gdGhpcy5fZ2V0QXR0ZW1wdHNSZXN1bHQoZXh0cmFFcnJvcnMpO1xuXG4gICAgICAgIGNvbnN0IHN1Y2Nlc3NUaHJlc2hvbGRSZWFjaGVkID0gcGFzc2VkVGltZXMgPj0gdGhpcy5zdWNjZXNzVGhyZXNob2xkO1xuICAgICAgICBjb25zdCBmYWlsdXJlVGhyZXNob2xkUmVhY2hlZCA9IGZhaWxlZFRpbWVzID49IHRoaXMuZmFpbHVyZVRocmVzaG9sZDtcblxuICAgICAgICByZXR1cm4gc3VjY2Vzc1RocmVzaG9sZFJlYWNoZWQgfHwgZmFpbHVyZVRocmVzaG9sZFJlYWNoZWQ7XG4gICAgfVxuXG4gICAgcHVibGljIGlzRmlyc3RBdHRlbXB0U3VjY2Vzc2Z1bCAoZXh0cmFFcnJvcnM6IFRlc3RSdW5FcnJvckZvcm1hdHRhYmxlQWRhcHRlcltdKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IHsgZmFpbGVkVGltZXMsIHBhc3NlZFRpbWVzIH0gPSB0aGlzLl9nZXRBdHRlbXB0c1Jlc3VsdChleHRyYUVycm9ycyk7XG5cbiAgICAgICAgcmV0dXJuIGZhaWxlZFRpbWVzID09PSAwICYmIHBhc3NlZFRpbWVzID4gMDtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRBdHRlbXB0c1Jlc3VsdCAoZXh0cmFFcnJvcnM/OiBUZXN0UnVuRXJyb3JGb3JtYXR0YWJsZUFkYXB0ZXJbXSk6IEF0dGVtcHRSZXN1bHQge1xuICAgICAgICBsZXQgZmFpbGVkVGltZXMgPSB0aGlzLmdldEZhaWxlZEF0dGVtcHRzKCkubGVuZ3RoO1xuICAgICAgICBsZXQgcGFzc2VkVGltZXMgPSB0aGlzLmdldFBhc3NlZEF0dGVtcHRzKCkubGVuZ3RoO1xuXG4gICAgICAgIGlmIChleHRyYUVycm9ycykge1xuICAgICAgICAgICAgaWYgKGV4dHJhRXJyb3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmYWlsZWRUaW1lcyArPSBleHRyYUVycm9ycy5sZW5ndGg7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcGFzc2VkVGltZXMgKz0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGZhaWxlZFRpbWVzLCBwYXNzZWRUaW1lcyB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgX3NldEZhaWxlZFRocmVzaG9sZCAoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZmFpbHVyZVRocmVzaG9sZCA9IHRoaXMuYXR0ZW1wdExpbWl0IC0gdGhpcy5zdWNjZXNzVGhyZXNob2xkICsgMTtcbiAgICB9XG59XG4iXX0=