testcafe-browser-provider-browserstack
Version:
Browserstack TestCafe browser provider plugin.
201 lines • 27.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("util");
const base_1 = __importDefault(require("./base"));
const request_api_1 = __importDefault(require("../utils/request-api"));
const create_browserstack_status_1 = __importDefault(require("../utils/create-browserstack-status"));
const get_api_polling_interval_1 = __importDefault(require("../utils/get-api-polling-interval"));
const ERROR_MESSAGES = __importStar(require("../templates/error-messages"));
const sharp_1 = __importDefault(require("sharp"));
const API_POLLING_INTERVAL = (0, get_api_polling_interval_1.default)();
const BROWSERSTACK_API_PATHS = {
browserList: {
url: 'https://api.browserstack.com/automate/browsers.json'
},
newSession: {
url: 'https://hub-cloud.browserstack.com/wd/hub/session',
method: 'POST'
},
openUrl: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}/url`,
method: 'POST'
}),
getWindowSize: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}/window/current/size`
}),
setWindowSize: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}/window/current/size`,
method: 'POST'
}),
maximizeWindow: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}/window/current/maximize`,
method: 'POST'
}),
getUrl: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}/url`
}),
deleteSession: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}`,
method: 'DELETE'
}),
screenshot: id => ({
url: `https://hub-cloud.browserstack.com/wd/hub/session/${id}/screenshot`
}),
getStatus: id => ({
url: `https://api.browserstack.com/automate/sessions/${id}.json`
}),
setStatus: id => ({
url: `https://api.browserstack.com/automate/sessions/${id}.json`,
method: 'PUT'
})
};
function requestApi(path, params) {
return (0, request_api_1.default)(path, params)
.then(response => {
if (response.status) {
throw new Error(ERROR_MESSAGES.REMOTE_API_REQUEST_FAILED({
status: response.status,
apiResponse: response.value && response.value.message || (0, util_1.inspect)(response)
}));
}
return response;
});
}
function getCorrectedSize(currentClientAreaSize, currentWindowSize, requestedSize) {
var horizontalChrome = currentWindowSize.width - currentClientAreaSize.width;
var verticalChrome = currentWindowSize.height - currentClientAreaSize.height;
return {
width: requestedSize.width + horizontalChrome,
height: requestedSize.height + verticalChrome
};
}
class AutomateBackend extends base_1.default {
constructor(...args) {
super(...args);
this.sessions = {};
}
static _ensureSessionId(sessionInfo) {
const sessionData = sessionInfo.value || {};
const sessionCapabilities = sessionData.capabilities || {};
sessionInfo.sessionId = sessionInfo.sessionId ||
sessionData.sessionId ||
sessionData['webdriver.remote.sessionid'] ||
sessionCapabilities['webdriver.remote.sessionid'];
if (!sessionInfo.sessionId) {
throw new Error(ERROR_MESSAGES.SESSION_ID_NOT_FOUND({
sessionInfoDump: (0, util_1.inspect)(sessionInfo)
}));
}
}
async _requestSessionInfo(id) {
var sessionInfo = await (0, request_api_1.default)(BROWSERSTACK_API_PATHS.getStatus(this.sessions[id].sessionId));
return sessionInfo['automation_session'];
}
async _requestCurrentWindowSize(id) {
var currentWindowSizeData = await requestApi(BROWSERSTACK_API_PATHS.getWindowSize(this.sessions[id].sessionId));
return {
width: currentWindowSizeData.value.width,
height: currentWindowSizeData.value.height
};
}
async getBrowsersList() {
var platformsInfo = await (0, request_api_1.default)(BROWSERSTACK_API_PATHS.browserList);
return platformsInfo.reverse();
}
getSessionUrl(id) {
return this.sessions[id] ? this.sessions[id].sessionUrl : '';
}
async getOSInfo(id) {
if (this.sessions[id])
return this.sessions[id].osInfo;
return null;
}
async openBrowser(id, pageUrl, capabilities) {
var { localIdentifier, local } = capabilities, restCapabilities = __rest(capabilities, ["localIdentifier", "local"]);
capabilities = Object.assign({ 'browserstack.localIdentifier': localIdentifier, 'browserstack.local': local }, restCapabilities);
this.sessions[id] = await requestApi(BROWSERSTACK_API_PATHS.newSession, {
body: { desiredCapabilities: capabilities },
});
AutomateBackend._ensureSessionId(this.sessions[id]);
const sessionInfo = await this._requestSessionInfo(id);
const osInfo = {
name: sessionInfo['os'] || '',
version: sessionInfo['os_version'] || ''
};
this.sessions[id].sessionUrl = sessionInfo['browser_url'];
this.sessions[id].osInfo = osInfo;
var sessionId = this.sessions[id].sessionId;
this.sessions[id].interval = setInterval(() => requestApi(BROWSERSTACK_API_PATHS.getUrl(sessionId)), API_POLLING_INTERVAL);
await requestApi(BROWSERSTACK_API_PATHS.openUrl(sessionId), { body: { url: pageUrl } });
}
async closeBrowser(id) {
const session = this.sessions[id];
if (!session)
return;
clearInterval(session.interval);
delete this.sessions[id];
// Delete session whose sessionId is created
if (session.sessionId && session.sessionId !== '')
await requestApi(BROWSERSTACK_API_PATHS.deleteSession(session.sessionId));
}
async takeScreenshot(id, screenshotPath) {
var base64Data = await requestApi(BROWSERSTACK_API_PATHS.screenshot(this.sessions[id].sessionId));
var buffer = Buffer.from(base64Data.value, 'base64');
await (0, sharp_1.default)(buffer).toFile(screenshotPath);
}
async resizeWindow(id, width, height, currentWidth, currentHeight) {
var sessionId = this.sessions[id].sessionId;
var currentWindowSize = await this._requestCurrentWindowSize(id);
var currentClientAreaSize = { width: currentWidth, height: currentHeight };
var requestedSize = { width, height };
var correctedSize = getCorrectedSize(currentClientAreaSize, currentWindowSize, requestedSize);
await requestApi(BROWSERSTACK_API_PATHS.setWindowSize(sessionId), { body: correctedSize });
}
async maximizeWindow(id) {
await requestApi(BROWSERSTACK_API_PATHS.maximizeWindow(this.sessions[id].sessionId));
}
async reportJobResult(id, jobResult, jobData, possibleResults) {
var sessionId = this.sessions[id].sessionId;
var jobStatus = (0, create_browserstack_status_1.default)(jobResult, jobData, possibleResults);
await (0, request_api_1.default)(BROWSERSTACK_API_PATHS.setStatus(sessionId), { body: jobStatus });
}
}
exports.default = AutomateBackend;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b21hdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmFja2VuZHMvYXV0b21hdGUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0JBQStCO0FBQy9CLGtEQUFpQztBQUNqQyx1RUFBa0Q7QUFDbEQscUdBQTJFO0FBQzNFLGlHQUFzRTtBQUN0RSw0RUFBOEQ7QUFDOUQsa0RBQTBCO0FBRTFCLE1BQU0sb0JBQW9CLEdBQUcsSUFBQSxrQ0FBcUIsR0FBRSxDQUFDO0FBRXJELE1BQU0sc0JBQXNCLEdBQUc7SUFDM0IsV0FBVyxFQUFFO1FBQ1QsR0FBRyxFQUFFLHFEQUFxRDtLQUM3RDtJQUVELFVBQVUsRUFBRTtRQUNSLEdBQUcsRUFBSyxtREFBbUQ7UUFDM0QsTUFBTSxFQUFFLE1BQU07S0FDakI7SUFFRCxPQUFPLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ1osR0FBRyxFQUFLLHFEQUFxRCxFQUFFLE1BQU07UUFDckUsTUFBTSxFQUFFLE1BQU07S0FDakIsQ0FBQztJQUVGLGFBQWEsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbEIsR0FBRyxFQUFFLHFEQUFxRCxFQUFFLHNCQUFzQjtLQUNyRixDQUFDO0lBRUYsYUFBYSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNsQixHQUFHLEVBQUsscURBQXFELEVBQUUsc0JBQXNCO1FBQ3JGLE1BQU0sRUFBRSxNQUFNO0tBQ2pCLENBQUM7SUFFRixjQUFjLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ25CLEdBQUcsRUFBSyxxREFBcUQsRUFBRSwwQkFBMEI7UUFDekYsTUFBTSxFQUFFLE1BQU07S0FDakIsQ0FBQztJQUVGLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDWCxHQUFHLEVBQUUscURBQXFELEVBQUUsTUFBTTtL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LHFCQUFxQixHQUFHLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLENBQUM7UUFDM0UsSUFBSSxhQUFhLEdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDOUMsSUFBSSxhQUFhLEdBQVcsZ0JBQWdCLENBQUMscUJBQXFCLEVBQUUsaUJBQWlCLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFFdEcsTUFBTSxVQUFVLENBQUMsc0JBQXNCLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUM7SUFDL0YsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjLENBQUUsRUFBRTtRQUNwQixNQUFNLFVBQVUsQ0FBQyxzQkFBc0IsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLGVBQWU7UUFDMUQsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDNUMsSUFBSSxTQUFTLEdBQUcsSUFBQSxvQ0FBd0IsRUFBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBRTlFLE1BQU0sSUFBQSxxQkFBYyxFQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQzNGLENBQUM7Q0FDSjtBQWhJRCxrQ0FnSUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSAndXRpbCc7XG5pbXBvcnQgQmFzZUJhY2tlbmQgZnJvbSAnLi9iYXNlJztcbmltcG9ydCByZXF1ZXN0QXBpQmFzZSBmcm9tICcuLi91dGlscy9yZXF1ZXN0LWFwaSc7XG5pbXBvcnQgY3JlYXRlQnJvd3NlcnN0YWNrU3RhdHVzIGZyb20gJy4uL3V0aWxzL2NyZWF0ZS1icm93c2Vyc3RhY2stc3RhdHVzJztcbmltcG9ydCBnZXRBUElQb2xsaW5nSW50ZXJ2YWwgZnJvbSAnLi4vdXRpbHMvZ2V0LWFwaS1wb2xsaW5nLWludGVydmFsJztcbmltcG9ydCAqIGFzIEVSUk9SX01FU1NBR0VTIGZyb20gJy4uL3RlbXBsYXRlcy9lcnJvci1tZXNzYWdlcyc7XG5pbXBvcnQgc2hhcnAgZnJvbSAnc2hhcnAnO1xuXG5jb25zdCBBUElfUE9MTElOR19JTlRFUlZBTCA9IGdldEFQSVBvbGxpbmdJbnRlcnZhbCgpO1xuXG5jb25zdCBCUk9XU0VSU1RBQ0tfQVBJX1BBVEhTID0ge1xuICAgIGJyb3dzZXJMaXN0OiB7XG4gICAgICAgIHVybDogJ2h0dHBzOi8vYXBpLmJyb3dzZXJzdGFjay5jb20vYXV0b21hdGUvYnJvd3NlcnMuanNvbidcbiAgICB9LFxuXG4gICAgbmV3U2Vzc2lvbjoge1xuICAgICAgICB1cmw6ICAgICdodHRwczovL2h1Yi1jbG91ZC5icm93c2Vyc3RhY2suY29tL3dkL2h1Yi9zZXNzaW9uJyxcbiAgICAgICAgbWV0aG9kOiAnUE9TVCdcbiAgICB9LFxuXG4gICAgb3BlblVybDogaWQgPT4gKHtcbiAgICAgICAgdXJsOiAgICBgaHR0cHM6Ly9odWItY2xvdWQuYnJvd3NlcnN0YWNrLmNvbS93ZC9odWIvc2Vzc2lvbi8ke2lkfS91cmxgLFxuICAgICAgICBtZXRob2Q6ICdQT1NUJ1xuICAgIH0pLFxuXG4gICAgZ2V0V2luZG93U2l6ZTogaWQgPT4gKHtcbiAgICAgICAgdXJsOiBgaHR0cHM6Ly9odWItY2xvdWQuYnJvd3NlcnN0YWNrLmNvbS93ZC9odWIvc2Vzc2lvbi8ke2lkfS93aW5kb3cvY3VycmVudC9zaXplYFxuICAgIH0pLFxuXG4gICAgc2V0V2luZG93U2l6ZTogaWQgPT4gKHtcbiAgICAgICAgdXJsOiAgICBgaHR0cHM6Ly9odWItY2xvdWQuYnJvd3NlcnN0YWNrLmNvbS93ZC9odWIvc2Vzc2lvbi8ke2lkfS93aW5kb3cvY3VycmVudC9zaXplYCxcbiAgICAgICAgbWV0aG9kOiAnUE9TVCdcbiAgICB9KSxcblxuICAgIG1heGltaXplV2luZG93OiBpZCA9PiAoe1xuICAgICAgICB1cmw6ICAgIGBodHRwczovL2h1Yi1jbG91ZC5icm93c2Vyc3RhY2suY29tL3dkL2h1Yi9zZXNzaW9uLyR7aWR9L3dpbmRvdy9jdXJyZW50L21heGltaXplYCxcbiAgICAgICAgbWV0aG9kOiAnUE9TVCdcbiAgICB9KSxcblxuICAgIGdldFVybDogaWQgPT4gKHtcbiAgICAgICAgdXJsOiBgaHR0cHM6Ly9odWItY2xvdWQuYnJvd3NlcnN0YWNrLmNvbS93ZC9odWIvc2Vzc2lvbi8ke2lkfS91cmxgXG4gICAgfSksXG5cbiAgICBkZWxldGVTZXNzaW9uOiBpZCA9PiAoe1xuICAgICAgICB1cmw6ICAgIGBodHRwczovL2h1Yi1jbG91ZC5icm93c2Vyc3RhY2suY29tL3dkL2h1Yi9zZXNzaW9uLyR7aWR9YCxcbiAgICAgICAgbWV0aG9kOiAnREVMRVRFJ1xuICAgIH0pLFxuXG4gICAgc2NyZWVuc2hvdDogaWQgPT4gKHtcbiAgICAgICAgdXJsOiBgaHR0cHM6Ly9odWItY2xvdWQuYnJvd3NlcnN0YWNrLmNvbS93ZC9odWIvc2Vzc2lvbi8ke2lkfS9zY3JlZW5zaG90YFxuICAgIH0pLFxuXG4gICAgZ2V0U3RhdHVzOiBpZCA9PiAoe1xuICAgICAgICB1cmw6IGBodHRwczovL2FwaS5icm93c2Vyc3RhY2suY29tL2F1dG9tYXRlL3Nlc3Npb25zLyR7aWR9Lmpzb25gXG4gICAgfSksXG5cbiAgICBzZXRTdGF0dXM6IGlkID0+ICh7XG4gICAgICAgIHVybDogICAgYGh0dHBzOi8vYXBpLmJyb3dzZXJzdGFjay5jb20vYXV0b21hdGUvc2Vzc2lvbnMvJHtpZH0uanNvbmAsXG4gICAgICAgIG1ldGhvZDogJ1BVVCdcbiAgICB9KVxufTtcblxuXG5mdW5jdGlvbiByZXF1ZXN0QXBpIChwYXRoLCBwYXJhbXMpIHtcbiAgICByZXR1cm4gcmVxdWVzdEFwaUJhc2UocGF0aCwgcGFyYW1zKVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKEVSUk9SX01FU1NBR0VTLlJFTU9URV9BUElfUkVRVUVTVF9GQUlMRUQoe1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXM6ICAgICAgcmVzcG9uc2Uuc3RhdHVzLFxuICAgICAgICAgICAgICAgICAgICBhcGlSZXNwb25zZTogcmVzcG9uc2UudmFsdWUgJiYgcmVzcG9uc2UudmFsdWUubWVzc2FnZSB8fCBpbnNwZWN0KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0Q29ycmVjdGVkU2l6ZSAoY3VycmVudENsaWVudEFyZWFTaXplLCBjdXJyZW50V2luZG93U2l6ZSwgcmVxdWVzdGVkU2l6ZSkge1xuICAgIHZhciBob3Jpem9udGFsQ2hyb21lID0gY3VycmVudFdpbmRvd1NpemUud2lkdGggLSBjdXJyZW50Q2xpZW50QXJlYVNpemUud2lkdGg7XG4gICAgdmFyIHZlcnRpY2FsQ2hyb21lICAgPSBjdXJyZW50V2luZG93U2l6ZS5oZWlnaHQgLSBjdXJyZW50Q2xpZW50QXJlYVNpemUuaGVpZ2h0O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGg6ICByZXF1ZXN0ZWRTaXplLndpZHRoICsgaG9yaXpvbnRhbENocm9tZSxcbiAgICAgICAgaGVpZ2h0OiByZXF1ZXN0ZWRTaXplLmhlaWdodCArIHZlcnRpY2FsQ2hyb21lXG4gICAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQXV0b21hdGVCYWNrZW5kIGV4dGVuZHMgQmFzZUJhY2tlbmQge1xuICAgIGNvbnN0cnVjdG9yICguLi5hcmdzKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3MpO1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbnMgPSB7fTtcbiAgICB9XG5cbiAgICBzdGF0aWMgX2Vuc3VyZVNlc3Npb25JZCAoc2Vzc2lvbkluZm8pIHtcbiAgICAgICAgY29uc3Qgc2Vzc2lvbkRhdGEgICAgICAgICA9IHNlc3Npb25JbmZvLnZhbHVlIHx8IHt9O1xuICAgICAgICBjb25zdCBzZXNzaW9uQ2FwYWJpbGl0aWVzID0gc2Vzc2lvbkRhdGEuY2FwYWJpbGl0aWVzIHx8IHt9O1xuXG4gICAgICAgIHNlc3Npb25JbmZvLnNlc3Npb25JZCA9IHNlc3Npb25JbmZvLnNlc3Npb25JZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uRGF0YS5zZXNzaW9uSWQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbkRhdGFbJ3dlYmRyaXZlci5yZW1vdGUuc2Vzc2lvbmlkJ10gfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbkNhcGFiaWxpdGllc1snd2ViZHJpdmVyLnJlbW90ZS5zZXNzaW9uaWQnXTtcblxuICAgICAgICBpZiAoIXNlc3Npb25JbmZvLnNlc3Npb25JZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKEVSUk9SX01FU1NBR0VTLlNFU1NJT05fSURfTk9UX0ZPVU5EKHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uSW5mb0R1bXA6IGluc3BlY3Qoc2Vzc2lvbkluZm8pXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBfcmVxdWVzdFNlc3Npb25JbmZvIChpZCkge1xuICAgICAgICB2YXIgc2Vzc2lvbkluZm8gPSBhd2FpdCByZXF1ZXN0QXBpQmFzZShCUk9XU0VSU1RBQ0tfQVBJX1BBVEhTLmdldFN0YXR1cyh0aGlzLnNlc3Npb25zW2lkXS5zZXNzaW9uSWQpKTtcblxuICAgICAgICByZXR1cm4gc2Vzc2lvbkluZm9bJ2F1dG9tYXRpb25fc2Vzc2lvbiddO1xuICAgIH1cblxuICAgIGFzeW5jIF9yZXF1ZXN0Q3VycmVudFdpbmRvd1NpemUgKGlkKSB7XG4gICAgICAgIHZhciBjdXJyZW50V2luZG93U2l6ZURhdGEgPSBhd2FpdCByZXF1ZXN0QXBpKEJST1dTRVJTVEFDS19BUElfUEFUSFMuZ2V0V2luZG93U2l6ZSh0aGlzLnNlc3Npb25zW2lkXS5zZXNzaW9uSWQpKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgd2lkdGg6ICBjdXJyZW50V2luZG93U2l6ZURhdGEudmFsdWUud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IGN1cnJlbnRXaW5kb3dTaXplRGF0YS52YWx1ZS5oZWlnaHRcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBhc3luYyBnZXRCcm93c2Vyc0xpc3QgKCkge1xuICAgICAgICB2YXIgcGxhdGZvcm1zSW5mbyA9IGF3YWl0IHJlcXVlc3RBcGlCYXNlKEJST1dTRVJTVEFDS19BUElfUEFUSFMuYnJvd3Nlckxpc3QpO1xuXG4gICAgICAgIHJldHVybiBwbGF0Zm9ybXNJbmZvLnJldmVyc2UoKTtcbiAgICB9XG5cbiAgICBnZXRTZXNzaW9uVXJsIChpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uc1tpZF0gPyB0aGlzLnNlc3Npb25zW2lkXS5zZXNzaW9uVXJsIDogJyc7XG4gICAgfVxuXG4gICAgYXN5bmMgZ2V0T1NJbmZvIChpZCkge1xuICAgICAgICBpZiAodGhpcy5zZXNzaW9uc1tpZF0pXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uc1tpZF0ub3NJbmZvO1xuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGFzeW5jIG9wZW5Ccm93c2VyIChpZCwgcGFnZVVybCwgY2FwYWJpbGl0aWVzKSB7XG4gICAgICAgIHZhciB7IGxvY2FsSWRlbnRpZmllciwgbG9jYWwsIC4uLnJlc3RDYXBhYmlsaXRpZXMgfSA9IGNhcGFiaWxpdGllcztcblxuICAgICAgICBjYXBhYmlsaXRpZXMgPSB7XG4gICAgICAgICAgICAnYnJvd3NlcnN0YWNrLmxvY2FsSWRlbnRpZmllcic6IGxvY2FsSWRlbnRpZmllcixcbiAgICAgICAgICAgICdicm93c2Vyc3RhY2subG9jYWwnOiAgICAgICAgICAgbG9jYWwsXG4gICAgICAgICAgICAuLi5yZXN0Q2FwYWJpbGl0aWVzXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uc1tpZF0gPSBhd2FpdCByZXF1ZXN0QXBpKEJST1dTRVJTVEFDS19BUElfUEFUSFMubmV3U2Vzc2lvbiwge1xuICAgICAgICAgICAgYm9keTogeyBkZXNpcmVkQ2FwYWJpbGl0aWVzOiBjYXBhYmlsaXRpZXMgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgQXV0b21hdGVCYWNrZW5kLl9lbnN1cmVTZXNzaW9uSWQodGhpcy5zZXNzaW9uc1tpZF0pO1xuXG4gICAgICAgIGNvbnN0IHNlc3Npb25JbmZvID0gYXdhaXQgdGhpcy5fcmVxdWVzdFNlc3Npb25JbmZvKGlkKTtcbiAgICAgICAgY29uc3Qgb3NJbmZvICAgICAgPSB7XG4gICAgICAgICAgICBuYW1lOiAgICBzZXNzaW9uSW5mb1snb3MnXSB8fCAnJyxcbiAgICAgICAgICAgIHZlcnNpb246IHNlc3Npb25JbmZvWydvc192ZXJzaW9uJ10gfHwgJydcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnNlc3Npb25zW2lkXS5zZXNzaW9uVXJsID0gc2Vzc2lvbkluZm9bJ2Jyb3dzZXJfdXJsJ107XG4gICAgICAgIHRoaXMuc2Vzc2lvbnNbaWRdLm9zSW5mbyAgICAgPSBvc0luZm87XG5cbiAgICAgICAgdmFyIHNlc3Npb25JZCA9IHRoaXMuc2Vzc2lvbnNbaWRdLnNlc3Npb25JZDtcblxuICAgICAgICB0aGlzLnNlc3Npb25zW2lkXS5pbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHJlcXVlc3RBcGkoQlJPV1NFUlNUQUNLX0FQSV9QQVRIUy5nZXRVcmwoc2Vzc2lvbklkKSksIEFQSV9QT0xMSU5HX0lOVEVSVkFMKTtcblxuICAgICAgICBhd2FpdCByZXF1ZXN0QXBpKEJST1dTRVJTVEFDS19BUElfUEFUSFMub3BlblVybChzZXNzaW9uSWQpLCB7IGJvZHk6IHsgdXJsOiBwYWdlVXJsIH0gfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgY2xvc2VCcm93c2VyIChpZCkge1xuICAgICAgICBjb25zdCBzZXNzaW9uID0gdGhpcy5zZXNzaW9uc1tpZF07XG5cbiAgICAgICAgaWYgKCFzZXNzaW9uKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNsZWFySW50ZXJ2YWwoc2Vzc2lvbi5pbnRlcnZhbCk7XG5cbiAgICAgICAgZGVsZXRlIHRoaXMuc2Vzc2lvbnNbaWRdO1xuXG4gICAgICAgIC8vIERlbGV0ZSBzZXNzaW9uIHdob3NlIHNlc3Npb25JZCBpcyBjcmVhdGVkXG4gICAgICAgIGlmIChzZXNzaW9uLnNlc3Npb25JZCAmJiBzZXNzaW9uLnNlc3Npb25JZCAhPT0gJycpXG4gICAgICAgICAgICBhd2FpdCByZXF1ZXN0QXBpKEJST1dTRVJTVEFDS19BUElfUEFUSFMuZGVsZXRlU2Vzc2lvbihzZXNzaW9uLnNlc3Npb25JZCkpO1xuICAgIH1cblxuICAgIGFzeW5jIHRha2VTY3JlZW5zaG90IChpZCwgc2NyZWVuc2hvdFBhdGgpIHtcbiAgICAgICAgdmFyIGJhc2U2NERhdGEgID0gYXdhaXQgcmVxdWVzdEFwaShCUk9XU0VSU1RBQ0tfQVBJX1BBVEhTLnNjcmVlbnNob3QodGhpcy5zZXNzaW9uc1tpZF0uc2Vzc2lvbklkKSk7XG4gICAgICAgIHZhciBidWZmZXIgICAgICA9IEJ1ZmZlci5mcm9tKGJhc2U2NERhdGEudmFsdWUsICdiYXNlNjQnKTtcblxuICAgICAgICBhd2FpdCBzaGFycChidWZmZXIpLnRvRmlsZShzY3JlZW5zaG90UGF0aCk7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVzaXplV2luZG93IChpZCwgd2lkdGgsIGhlaWdodCwgY3VycmVudFdpZHRoLCBjdXJyZW50SGVpZ2h0KSB7XG4gICAgICAgIHZhciBzZXNzaW9uSWQgICAgICAgICAgICAgPSB0aGlzLnNlc3Npb25zW2lkXS5zZXNzaW9uSWQ7XG4gICAgICAgIHZhciBjdXJyZW50V2luZG93U2l6ZSAgICAgPSBhd2FpdCB0aGlzLl9yZXF1ZXN0Q3VycmVudFdpbmRvd1NpemUoaWQpO1xuICAgICAgICB2YXIgY3VycmVudENsaWVudEFyZWFTaXplID0geyB3aWR0aDogY3VycmVudFdpZHRoLCBoZWlnaHQ6IGN1cnJlbnRIZWlnaHQgfTtcbiAgICAgICAgdmFyIHJlcXVlc3RlZFNpemUgICAgICAgICA9IHsgd2lkdGgsIGhlaWdodCB9O1xuICAgICAgICB2YXIgY29ycmVjdGVkU2l6ZSAgICAgICAgID0gZ2V0Q29ycmVjdGVkU2l6ZShjdXJyZW50Q2xpZW50QXJlYVNpemUsIGN1cnJlbnRXaW5kb3dTaXplLCByZXF1ZXN0ZWRTaXplKTtcblxuICAgICAgICBhd2FpdCByZXF1ZXN0QXBpKEJST1dTRVJTVEFDS19BUElfUEFUSFMuc2V0V2luZG93U2l6ZShzZXNzaW9uSWQpLCB7IGJvZHk6IGNvcnJlY3RlZFNpemUgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgbWF4aW1pemVXaW5kb3cgKGlkKSB7XG4gICAgICAgIGF3YWl0IHJlcXVlc3RBcGkoQlJPV1NFUlNUQUNLX0FQSV9QQVRIUy5tYXhpbWl6ZVdpbmRvdyh0aGlzLnNlc3Npb25zW2lkXS5zZXNzaW9uSWQpKTtcbiAgICB9XG5cbiAgICBhc3luYyByZXBvcnRKb2JSZXN1bHQgKGlkLCBqb2JSZXN1bHQsIGpvYkRhdGEsIHBvc3NpYmxlUmVzdWx0cykge1xuICAgICAgICB2YXIgc2Vzc2lvbklkID0gdGhpcy5zZXNzaW9uc1tpZF0uc2Vzc2lvbklkO1xuICAgICAgICB2YXIgam9iU3RhdHVzID0gY3JlYXRlQnJvd3NlcnN0YWNrU3RhdHVzKGpvYlJlc3VsdCwgam9iRGF0YSwgcG9zc2libGVSZXN1bHRzKTtcblxuICAgICAgICBhd2FpdCByZXF1ZXN0QXBpQmFzZShCUk9XU0VSU1RBQ0tfQVBJX1BBVEhTLnNldFN0YXR1cyhzZXNzaW9uSWQpLCB7IGJvZHk6IGpvYlN0YXR1cyB9KTtcbiAgICB9XG59XG4iXX0=