UNPKG

@browserstack/testcafe

Version:

Automated browser testing for the modern web development stack.

142 lines 21 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 testcafe_browser_tools_1 = require("testcafe-browser-tools"); const crop_1 = require("./crop"); const async_queue_1 = require("../utils/async-queue"); const warning_message_1 = __importDefault(require("../notifications/warning-message")); const escape_user_agent_1 = __importDefault(require("../utils/escape-user-agent")); const correct_file_path_1 = __importDefault(require("../utils/correct-file-path")); const promisified_functions_1 = require("../utils/promisified-functions"); class Capturer { constructor(baseScreenshotsPath, testEntry, connection, pathPattern, fullPage, warningLog) { this.enabled = !!baseScreenshotsPath; this.baseScreenshotsPath = baseScreenshotsPath; this.testEntry = testEntry; this.provider = connection.provider; this.browserId = connection.id; this.warningLog = warningLog; this.pathPattern = pathPattern; this.fullPage = fullPage; } static _getDimensionWithoutScrollbar(fullDimension, documentDimension, bodyDimension) { if (bodyDimension > fullDimension) return documentDimension; if (documentDimension > fullDimension) return bodyDimension; return Math.max(documentDimension, bodyDimension); } static _getCropDimensions(cropDimensions, pageDimensions) { if (!cropDimensions || !pageDimensions) return null; const { dpr } = pageDimensions; const { top, left, bottom, right } = cropDimensions; return { top: Math.round(top * dpr), left: Math.round(left * dpr), bottom: Math.round(bottom * dpr), right: Math.round(right * dpr) }; } static _getClientAreaDimensions(pageDimensions) { if (!pageDimensions) return null; const { innerWidth, documentWidth, bodyWidth, innerHeight, documentHeight, bodyHeight, dpr } = pageDimensions; return { width: Math.floor(Capturer._getDimensionWithoutScrollbar(innerWidth, documentWidth, bodyWidth) * dpr), height: Math.floor(Capturer._getDimensionWithoutScrollbar(innerHeight, documentHeight, bodyHeight) * dpr) }; } static async _isScreenshotCaptured(screenshotPath) { try { const stats = await promisified_functions_1.stat(screenshotPath); return stats.isFile(); } catch (e) { return false; } } _joinWithBaseScreenshotPath(path) { return path_1.join(this.baseScreenshotsPath, path); } _incrementFileIndexes(forError) { if (forError) this.pathPattern.data.errorFileIndex++; else this.pathPattern.data.fileIndex++; } _getCustomScreenshotPath(customPath) { const correctedCustomPath = correct_file_path_1.default(customPath); return this._joinWithBaseScreenshotPath(correctedCustomPath); } _getScreenshotPath(forError) { const path = this.pathPattern.getPath(forError); this._incrementFileIndexes(forError); return this._joinWithBaseScreenshotPath(path); } _getThumbnailPath(screenshotPath) { const imageName = path_1.basename(screenshotPath); const imageDir = path_1.dirname(screenshotPath); return path_1.join(imageDir, 'thumbnails', imageName); } async _takeScreenshot({ filePath, pageWidth, pageHeight, fullPage = this.fullPage }) { await this.provider.takeScreenshot(this.browserId, filePath, pageWidth, pageHeight, fullPage); } async _capture(forError, { pageDimensions, cropDimensions, markSeed, customPath, fullPage } = {}) { if (!this.enabled) return null; const screenshotPath = customPath ? this._getCustomScreenshotPath(customPath) : this._getScreenshotPath(forError); const thumbnailPath = this._getThumbnailPath(screenshotPath); if (async_queue_1.isInQueue(screenshotPath)) this.warningLog.addWarning(warning_message_1.default.screenshotRewritingError, screenshotPath); await async_queue_1.addToQueue(screenshotPath, async () => { const clientAreaDimensions = Capturer._getClientAreaDimensions(pageDimensions); const { width: pageWidth, height: pageHeight } = clientAreaDimensions || {}; const takeScreenshotOptions = { filePath: screenshotPath, pageWidth, pageHeight, fullPage }; await this._takeScreenshot(takeScreenshotOptions); if (!await Capturer._isScreenshotCaptured(screenshotPath)) return; const image = await promisified_functions_1.readPngFile(screenshotPath); const croppedImage = await crop_1.cropScreenshot(image, { markSeed, clientAreaDimensions, path: screenshotPath, cropDimensions: Capturer._getCropDimensions(cropDimensions, pageDimensions) }); if (croppedImage) await promisified_functions_1.writePng(screenshotPath, croppedImage); await testcafe_browser_tools_1.generateThumbnail(screenshotPath, thumbnailPath); }); const testRunId = this.testEntry.testRuns[this.browserId].id; const userAgent = escape_user_agent_1.default(this.pathPattern.data.parsedUserAgent.prettyUserAgent); const quarantineAttempt = this.pathPattern.data.quarantineAttempt; const takenOnFail = forError; const screenshot = { testRunId, screenshotPath, thumbnailPath, userAgent, quarantineAttempt, takenOnFail }; this.testEntry.screenshots.push(screenshot); return screenshotPath; } async captureAction(options) { return await this._capture(false, options); } async captureError(options) { return await this._capture(true, options); } } exports.default = Capturer; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwdHVyZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyZWVuc2hvdHMvY2FwdHVyZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSwrQkFBMkQ7QUFDM0QsbUVBQTJEO0FBQzNELGlDQUF3QztBQUN4QyxzREFBNkQ7QUFDN0QsdUZBQStEO0FBQy9ELG1GQUF5RDtBQUN6RCxtRkFBeUQ7QUFDekQsMEVBQTZFO0FBRzdFLE1BQXFCLFFBQVE7SUFDekIsWUFBYSxtQkFBbUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsVUFBVTtRQUN0RixJQUFJLENBQUMsT0FBTyxHQUFlLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztRQUNqRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsbUJBQW1CLENBQUM7UUFDL0MsSUFBSSxDQUFDLFNBQVMsR0FBYSxTQUFTLENBQUM7UUFDckMsSUFBSSxDQUFDLFFBQVEsR0FBYyxVQUFVLENBQUMsUUFBUSxDQUFDO1FBQy9DLElBQUksQ0FBQyxTQUFTLEdBQWEsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUN6QyxJQUFJLENBQUMsVUFBVSxHQUFZLFVBQVUsQ0FBQztRQUN0QyxJQUFJLENBQUMsV0FBVyxHQUFXLFdBQVcsQ0FBQztRQUN2QyxJQUFJLENBQUMsUUFBUSxHQUFjLFFBQVEsQ0FBQztJQUN4QyxDQUFDO0lBRUQsTUFBTSxDQUFDLDZCQUE2QixDQUFFLGFBQWEsRUFBRSxpQkFBaUIsRUFBRSxhQUFhO1FBQ2pGLElBQUksYUFBYSxHQUFHLGFBQWE7WUFDN0IsT0FBTyxpQkFBaUIsQ0FBQztRQUU3QixJQUFJLGlCQUFpQixHQUFHLGFBQWE7WUFDakMsT0FBTyxhQUFhLENBQUM7UUFFekIsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLGlCQUFpQixFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRCxNQUFNLENBQUMsa0JBQWtCLENBQUUsY0FB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LENBQUM7UUFFNUMsT0FBTyxjQUFjLENBQUM7SUFDMUIsQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENBQUUsT0FBTztRQUN4QixPQUFPLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELEtBQUssQ0FBQyxZQUFZLENBQUUsT0FBTztRQUN2QixPQUFPLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDOUMsQ0FBQztDQUNKO0FBcktELDJCQXFLQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpvaW4gYXMgam9pblBhdGgsIGRpcm5hbWUsIGJhc2VuYW1lIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBnZW5lcmF0ZVRodW1ibmFpbCB9IGZyb20gJ3Rlc3RjYWZlLWJyb3dzZXItdG9vbHMnO1xuaW1wb3J0IHsgY3JvcFNjcmVlbnNob3QgfSBmcm9tICcuL2Nyb3AnO1xuaW1wb3J0IHsgaXNJblF1ZXVlLCBhZGRUb1F1ZXVlIH0gZnJvbSAnLi4vdXRpbHMvYXN5bmMtcXVldWUnO1xuaW1wb3J0IFdBUk5JTkdfTUVTU0FHRSBmcm9tICcuLi9ub3RpZmljYXRpb25zL3dhcm5pbmctbWVzc2FnZSc7XG5pbXBvcnQgZXNjYXBlVXNlckFnZW50IGZyb20gJy4uL3V0aWxzL2VzY2FwZS11c2VyLWFnZW50JztcbmltcG9ydCBjb3JyZWN0RmlsZVBhdGggZnJvbSAnLi4vdXRpbHMvY29ycmVjdC1maWxlLXBhdGgnO1xuaW1wb3J0IHsgcmVhZFBuZ0ZpbGUsIHN0YXQsIHdyaXRlUG5nIH0gZnJvbSAnLi4vdXRpbHMvcHJvbWlzaWZpZWQtZnVuY3Rpb25zJztcblxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDYXB0dXJlciB7XG4gICAgY29uc3RydWN0b3IgKGJhc2VTY3JlZW5zaG90c1BhdGgsIHRlc3RFbnRyeSwgY29ubmVjdGlvbiwgcGF0aFBhdHRlcm4sIGZ1bGxQYWdlLCB3YXJuaW5nTG9nKSB7XG4gICAgICAgIHRoaXMuZW5hYmxlZCAgICAgICAgICAgICA9ICEhYmFzZVNjcmVlbnNob3RzUGF0aDtcbiAgICAgICAgdGhpcy5iYXNlU2NyZWVuc2hvdHNQYXRoID0gYmFzZVNjcmVlbnNob3RzUGF0aDtcbiAgICAgICAgdGhpcy50ZXN0RW50cnkgICAgICAgICAgID0gdGVzdEVudHJ5O1xuICAgICAgICB0aGlzLnByb3ZpZGVyICAgICAgICAgICAgPSBjb25uZWN0aW9uLnByb3ZpZGVyO1xuICAgICAgICB0aGlzLmJyb3dzZXJJZCAgICAgICAgICAgPSBjb25uZWN0aW9uLmlkO1xuICAgICAgICB0aGlzLndhcm5pbmdMb2cgICAgICAgICAgPSB3YXJuaW5nTG9nO1xuICAgICAgICB0aGlzLnBhdGhQYXR0ZXJuICAgICAgICAgPSBwYXRoUGF0dGVybjtcbiAgICAgICAgdGhpcy5mdWxsUGFnZSAgICAgICAgICAgID0gZnVsbFBhZ2U7XG4gICAgfVxuXG4gICAgc3RhdGljIF9nZXREaW1lbnNpb25XaXRob3V0U2Nyb2xsYmFyIChmdWxsRGltZW5zaW9uLCBkb2N1bWVudERpbWVuc2lvbiwgYm9keURpbWVuc2lvbikge1xuICAgICAgICBpZiAoYm9keURpbWVuc2lvbiA+IGZ1bGxEaW1lbnNpb24pXG4gICAgICAgICAgICByZXR1cm4gZG9jdW1lbnREaW1lbnNpb247XG5cbiAgICAgICAgaWYgKGRvY3VtZW50RGltZW5zaW9uID4gZnVsbERpbWVuc2lvbilcbiAgICAgICAgICAgIHJldHVybiBib2R5RGltZW5zaW9uO1xuXG4gICAgICAgIHJldHVybiBNYXRoLm1heChkb2N1bWVudERpbWVuc2lvbiwgYm9keURpbWVuc2lvbik7XG4gICAgfVxuXG4gICAgc3RhdGljIF9nZXRDcm9wRGltZW5zaW9ucyAoY3JvcERpbWVuc2lvbnMsIHBhZ2VEaW1lbnNpb25zKSB7XG4gICAgICAgIGlmICghY3JvcERpbWVuc2lvbnMgfHwgIXBhZ2VEaW1lbnNpb25zKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgY29uc3QgeyBkcHIgfSAgICAgICAgICAgICAgICAgICAgICA9IHBhZ2VEaW1lbnNpb25zO1xuICAgICAgICBjb25zdCB7IHRvcCwgbGVmdCwgYm90dG9tLCByaWdodCB9ID0gY3JvcERpbWVuc2lvbnM7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRvcDogICAgTWF0aC5yb3VuZCh0b3AgKiBkcHIpLFxuICAgICAgICAgICAgbGVmdDogICBNYXRoLnJvdW5kKGxlZnQgKiBkcHIpLFxuICAgICAgICAgICAgYm90dG9tOiBNYXRoLnJvdW5kKGJvdHRvbSAqIGRwciksXG4gICAgICAgICAgICByaWdodDogIE1hdGgucm91bmQocmlnaHQgKiBkcHIpXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3RhdGljIF9nZXRDbGllbnRBcmVhRGltZW5zaW9ucyAocGFnZURpbWVuc2lvbnMpIHtcbiAgICAgICAgaWYgKCFwYWdlRGltZW5zaW9ucylcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICAgIGNvbnN0IHsgaW5uZXJXaWR0aCwgZG9jdW1lbnRXaWR0aCwgYm9keVdpZHRoLCBpbm5lckhlaWdodCwgZG9jdW1lbnRIZWlnaHQsIGJvZHlIZWlnaHQsIGRwciB9ID0gcGFnZURpbWVuc2lvbnM7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdpZHRoOiAgTWF0aC5mbG9vcihDYXB0dXJlci5fZ2V0RGltZW5zaW9uV2l0aG91dFNjcm9sbGJhcihpbm5lcldpZHRoLCBkb2N1bWVudFdpZHRoLCBib2R5V2lkdGgpICogZHByKSxcbiAgICAgICAgICAgIGhlaWdodDogTWF0aC5mbG9vcihDYXB0dXJlci5fZ2V0RGltZW5zaW9uV2l0aG91dFNjcm9sbGJhcihpbm5lckhlaWdodCwgZG9jdW1lbnRIZWlnaHQsIGJvZHlIZWlnaHQpICogZHByKVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBfaXNTY3JlZW5zaG90Q2FwdHVyZWQgKHNjcmVlbnNob3RQYXRoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IHN0YXQoc2NyZWVuc2hvdFBhdGgpO1xuXG4gICAgICAgICAgICByZXR1cm4gc3RhdHMuaXNGaWxlKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9qb2luV2l0aEJhc2VTY3JlZW5zaG90UGF0aCAocGF0aCkge1xuICAgICAgICByZXR1cm4gam9pblBhdGgodGhpcy5iYXNlU2NyZWVuc2hvdHNQYXRoLCBwYXRoKTtcbiAgICB9XG5cbiAgICBfaW5jcmVtZW50RmlsZUluZGV4ZXMgKGZvckVycm9yKSB7XG4gICAgICAgIGlmIChmb3JFcnJvcilcbiAgICAgICAgICAgIHRoaXMucGF0aFBhdHRlcm4uZGF0YS5lcnJvckZpbGVJbmRleCsrO1xuXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMucGF0aFBhdHRlcm4uZGF0YS5maWxlSW5kZXgrKztcbiAgICB9XG5cbiAgICBfZ2V0Q3VzdG9tU2NyZWVuc2hvdFBhdGggKGN1c3RvbVBhdGgpIHtcbiAgICAgICAgY29uc3QgY29ycmVjdGVkQ3VzdG9tUGF0aCA9IGNvcnJlY3RGaWxlUGF0aChjdXN0b21QYXRoKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fam9pbldpdGhCYXNlU2NyZWVuc2hvdFBhdGgoY29ycmVjdGVkQ3VzdG9tUGF0aCk7XG4gICAgfVxuXG4gICAgX2dldFNjcmVlbnNob3RQYXRoIChmb3JFcnJvcikge1xuICAgICAgICBjb25zdCBwYXRoID0gdGhpcy5wYXRoUGF0dGVybi5nZXRQYXRoKGZvckVycm9yKTtcblxuICAgICAgICB0aGlzLl9pbmNyZW1lbnRGaWxlSW5kZXhlcyhmb3JFcnJvcik7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2pvaW5XaXRoQmFzZVNjcmVlbnNob3RQYXRoKHBhdGgpO1xuICAgIH1cblxuICAgIF9nZXRUaHVtYm5haWxQYXRoIChzY3JlZW5zaG90UGF0aCkge1xuICAgICAgICBjb25zdCBpbWFnZU5hbWUgPSBiYXNlbmFtZShzY3JlZW5zaG90UGF0aCk7XG4gICAgICAgIGNvbnN0IGltYWdlRGlyICA9IGRpcm5hbWUoc2NyZWVuc2hvdFBhdGgpO1xuXG4gICAgICAgIHJldHVybiBqb2luUGF0aChpbWFnZURpciwgJ3RodW1ibmFpbHMnLCBpbWFnZU5hbWUpO1xuICAgIH1cblxuICAgIGFzeW5jIF90YWtlU2NyZWVuc2hvdCAoeyBmaWxlUGF0aCwgcGFnZVdpZHRoLCBwYWdlSGVpZ2h0LCBmdWxsUGFnZSA9IHRoaXMuZnVsbFBhZ2UgfSkge1xuICAgICAgICBhd2FpdCB0aGlzLnByb3ZpZGVyLnRha2VTY3JlZW5zaG90KHRoaXMuYnJvd3NlcklkLCBmaWxlUGF0aCwgcGFnZVdpZHRoLCBwYWdlSGVpZ2h0LCBmdWxsUGFnZSk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2NhcHR1cmUgKGZvckVycm9yLCB7IHBhZ2VEaW1lbnNpb25zLCBjcm9wRGltZW5zaW9ucywgbWFya1NlZWQsIGN1c3RvbVBhdGgsIGZ1bGxQYWdlIH0gPSB7fSkge1xuICAgICAgICBpZiAoIXRoaXMuZW5hYmxlZClcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgICAgIGNvbnN0IHNjcmVlbnNob3RQYXRoID0gY3VzdG9tUGF0aCA/IHRoaXMuX2dldEN1c3RvbVNjcmVlbnNob3RQYXRoKGN1c3RvbVBhdGgpIDogdGhpcy5fZ2V0U2NyZWVuc2hvdFBhdGgoZm9yRXJyb3IpO1xuICAgICAgICBjb25zdCB0aHVtYm5haWxQYXRoICA9IHRoaXMuX2dldFRodW1ibmFpbFBhdGgoc2NyZWVuc2hvdFBhdGgpO1xuXG4gICAgICAgIGlmIChpc0luUXVldWUoc2NyZWVuc2hvdFBhdGgpKVxuICAgICAgICAgICAgdGhpcy53YXJuaW5nTG9nLmFkZFdhcm5pbmcoV0FSTklOR19NRVNTQUdFLnNjcmVlbnNob3RSZXdyaXRpbmdFcnJvciwgc2NyZWVuc2hvdFBhdGgpO1xuXG4gICAgICAgIGF3YWl0IGFkZFRvUXVldWUoc2NyZWVuc2hvdFBhdGgsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudEFyZWFEaW1lbnNpb25zID0gQ2FwdHVyZXIuX2dldENsaWVudEFyZWFEaW1lbnNpb25zKHBhZ2VEaW1lbnNpb25zKTtcblxuICAgICAgICAgICAgY29uc3QgeyB3aWR0aDogcGFnZVdpZHRoLCBoZWlnaHQ6IHBhZ2VIZWlnaHQgfSA9IGNsaWVudEFyZWFEaW1lbnNpb25zIHx8IHt9O1xuXG4gICAgICAgICAgICBjb25zdCB0YWtlU2NyZWVuc2hvdE9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgZmlsZVBhdGg6IHNjcmVlbnNob3RQYXRoLFxuICAgICAgICAgICAgICAgIHBhZ2VXaWR0aCxcbiAgICAgICAgICAgICAgICBwYWdlSGVpZ2h0LFxuICAgICAgICAgICAgICAgIGZ1bGxQYWdlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl90YWtlU2NyZWVuc2hvdCh0YWtlU2NyZWVuc2hvdE9wdGlvbnMpO1xuXG4gICAgICAgICAgICBpZiAoIWF3YWl0IENhcHR1cmVyLl9pc1NjcmVlbnNob3RDYXB0dXJlZChzY3JlZW5zaG90UGF0aCkpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IGF3YWl0IHJlYWRQbmdGaWxlKHNjcmVlbnNob3RQYXRoKTtcblxuICAgICAgICAgICAgY29uc3QgY3JvcHBlZEltYWdlID0gYXdhaXQgY3JvcFNjcmVlbnNob3QoaW1hZ2UsIHtcbiAgICAgICAgICAgICAgICBtYXJrU2VlZCxcbiAgICAgICAgICAgICAgICBjbGllbnRBcmVhRGltZW5zaW9ucyxcbiAgICAgICAgICAgICAgICBwYXRoOiAgICAgICAgICAgc2NyZWVuc2hvdFBhdGgsXG4gICAgICAgICAgICAgICAgY3JvcERpbWVuc2lvbnM6IENhcHR1cmVyLl9nZXRDcm9wRGltZW5zaW9ucyhjcm9wRGltZW5zaW9ucywgcGFnZURpbWVuc2lvbnMpXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKGNyb3BwZWRJbWFnZSlcbiAgICAgICAgICAgICAgICBhd2FpdCB3cml0ZVBuZyhzY3JlZW5zaG90UGF0aCwgY3JvcHBlZEltYWdlKTtcblxuICAgICAgICAgICAgYXdhaXQgZ2VuZXJhdGVUaHVtYm5haWwoc2NyZWVuc2hvdFBhdGgsIHRodW1ibmFpbFBhdGgpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0ZXN0UnVuSWQgICAgICAgICA9IHRoaXMudGVzdEVudHJ5LnRlc3RSdW5zW3RoaXMuYnJvd3NlcklkXS5pZDtcbiAgICAgICAgY29uc3QgdXNlckFnZW50ICAgICAgICAgPSBlc2NhcGVVc2VyQWdlbnQodGhpcy5wYXRoUGF0dGVybi5kYXRhLnBhcnNlZFVzZXJBZ2VudC5wcmV0dHlVc2VyQWdlbnQpO1xuICAgICAgICBjb25zdCBxdWFyYW50aW5lQXR0ZW1wdCA9IHRoaXMucGF0aFBhdHRlcm4uZGF0YS5xdWFyYW50aW5lQXR0ZW1wdDtcbiAgICAgICAgY29uc3QgdGFrZW5PbkZhaWwgICAgICAgPSBmb3JFcnJvcjtcblxuICAgICAgICBjb25zdCBzY3JlZW5zaG90ID0ge1xuICAgICAgICAgICAgdGVzdFJ1bklkLFxuICAgICAgICAgICAgc2NyZWVuc2hvdFBhdGgsXG4gICAgICAgICAgICB0aHVtYm5haWxQYXRoLFxuICAgICAgICAgICAgdXNlckFnZW50LFxuICAgICAgICAgICAgcXVhcmFudGluZUF0dGVtcHQsXG4gICAgICAgICAgICB0YWtlbk9uRmFpbFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMudGVzdEVudHJ5LnNjcmVlbnNob3RzLnB1c2goc2NyZWVuc2hvdCk7XG5cbiAgICAgICAgcmV0dXJuIHNjcmVlbnNob3RQYXRoO1xuICAgIH1cblxuICAgIGFzeW5jIGNhcHR1cmVBY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2NhcHR1cmUoZmFsc2UsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGFzeW5jIGNhcHR1cmVFcnJvciAob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fY2FwdHVyZSh0cnVlLCBvcHRpb25zKTtcbiAgICB9XG59XG5cbiJdfQ==