testcafe
Version:
Automated browser testing for the modern web development stack.
188 lines • 32.5 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRequestOptions = void 0;
const lodash_1 = require("lodash");
const is_stream_1 = __importDefault(require("is-stream"));
const interfaces_1 = require("./interfaces");
const testcafe_hammerhead_1 = require("testcafe-hammerhead");
const content_types_1 = __importDefault(require("../../assets/content-types"));
const http_headers_1 = __importDefault(require("../../utils/http-headers"));
const types_1 = require("../../errors/types");
const runtime_1 = require("../../errors/runtime");
const actions_1 = require("../commands/actions");
const DEFAULT_ACCEPT = { [http_headers_1.default.accept]: `${content_types_1.default.json}, ${content_types_1.default.textPlain}, ${content_types_1.default.all}` };
const METHODS_WITH_CONTENT_TYPE = ['POST', 'PUT', 'PATCH'];
const DEFAULT_REQUEST_METHOD = 'GET';
const DEFAULT_PROTOCOL = 'http:';
function setContentTypeIfNotExists(headers, value) {
if (!(0, lodash_1.isUndefined)(headers) && (0, lodash_1.isUndefined)(headers[http_headers_1.default.contentType]))
headers[http_headers_1.default.contentType] = value;
}
function typeOf(value) {
if (value === null)
return 'null';
if (value && typeof value === 'object')
return value.constructor.name.toLowerCase();
return typeof value;
}
function transformBody(headers, body) {
if (!body)
return Buffer.from('');
if (typeOf(body) === 'formdata' ||
typeOf(body) === 'file' ||
typeOf(body) === 'blob' ||
(0, lodash_1.isArrayBuffer)(body) ||
(0, lodash_1.isBuffer)(body) ||
(0, is_stream_1.default)(body))
return Buffer.from(body);
else if (ArrayBuffer.isView(body))
return Buffer.from(body.buffer);
else if (body instanceof URLSearchParams) {
setContentTypeIfNotExists(headers, `${content_types_1.default.urlencoded};charset=utf-8`);
return Buffer.from(body.toString());
}
else if ((0, lodash_1.isObject)(body) || headers && headers[http_headers_1.default.contentType] === content_types_1.default.json) {
setContentTypeIfNotExists(headers, content_types_1.default.json);
return Buffer.from(JSON.stringify(body));
}
else if (typeof body === 'string')
setContentTypeIfNotExists(headers, content_types_1.default.textPlain);
return body;
}
function getAuthString(auth) {
return 'Basic ' + Buffer.from(auth.username + ':' + auth.password, 'utf8').toString('base64');
}
function changeHeaderNamesToLowercase(headers) {
const lowerCaseHeaders = {};
Object.keys(headers).forEach(headerName => {
lowerCaseHeaders[headerName.toLowerCase()] = headers[headerName];
});
return lowerCaseHeaders;
}
async function prepareHeaders(options, currentPageUrl, url, body, testRun, withCredentials) {
const { host, origin } = url;
const { method, proxy, auth, headers = {} } = options;
const preparedHeaders = Object.assign({}, DEFAULT_ACCEPT, changeHeaderNamesToLowercase(headers));
preparedHeaders[http_headers_1.default.host] = host;
preparedHeaders[http_headers_1.default.origin] = origin;
preparedHeaders[http_headers_1.default.contentLength] = body.length;
if (method && METHODS_WITH_CONTENT_TYPE.includes(String(method)))
preparedHeaders[http_headers_1.default.contentType] = preparedHeaders[http_headers_1.default.contentType] || content_types_1.default.urlencoded;
if (auth && withCredentials)
preparedHeaders[http_headers_1.default.authorization] = getAuthString(auth);
if (proxy === null || proxy === void 0 ? void 0 : proxy.auth)
preparedHeaders[http_headers_1.default.proxyAuthorization] = getAuthString(proxy.auth);
if (withCredentials) {
const currentPageCookies = await testRun.cookieProvider.getCookieHeader(currentPageUrl.href, currentPageUrl.hostname);
if (currentPageCookies)
preparedHeaders[http_headers_1.default.cookie] = currentPageCookies;
}
//NOTE: Additional header to recognize API requests in the hammerhead
preparedHeaders[http_headers_1.default.isApiRequest] = 'true';
return preparedHeaders;
}
async function prepareUrl(testRun, currentPageUrl, url, callsite) {
let preparedUrl;
try {
preparedUrl = url instanceof URL
? url
: new URL(url, currentPageUrl.hostname ? currentPageUrl.origin : void 0);
}
catch (e) {
throw new runtime_1.APIError(callsite, types_1.RUNTIME_ERRORS.requestUrlInvalidValueError, url);
}
return preparedUrl;
}
function prepareSearchParams(url, params) {
if (!params)
return url;
let searchParams;
if (params instanceof URLSearchParams)
searchParams = params;
else {
searchParams = new URLSearchParams();
for (const key in params) {
if (!params[key])
continue;
(0, lodash_1.castArray)(params[key]).forEach(v => {
searchParams.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));
});
}
}
return `${url}${url.includes('?') ? '&' : '?'}${searchParams.toString()}`;
}
function getProxyUrl(testRun, url, withCredentials) {
return testRun.executeCommand(new actions_1.GetProxyUrlCommand({
url: url,
options: { credentials: withCredentials ? interfaces_1.Credentials.include : interfaces_1.Credentials.omit },
}, testRun, true));
}
async function resolveNativeAutomationUrlParts(url) {
const { href, hostname, port, pathname, search, protocol, } = url;
const partAfterHost = [pathname, search].join('');
return { partAfterHost, href, hostname, port, protocol };
}
async function resolvePoxyUrlParts(testRun, url, withCredentials) {
const href = await getProxyUrl(testRun, url.href, withCredentials);
const urlObj = await (0, testcafe_hammerhead_1.parseProxyUrl)(href);
const { partAfterHost } = urlObj;
const { hostname, port } = urlObj.proxy;
return { partAfterHost, href, hostname, port, protocol: DEFAULT_PROTOCOL };
}
function resolveUrlParts(testRun, url, withCredentials) {
return testRun.isNativeAutomation ? resolveNativeAutomationUrlParts(url) : resolvePoxyUrlParts(testRun, url, withCredentials);
}
async function createRequestOptions(currentPageUrl, testRun, options, callsite) {
var _a;
options.headers = options.headers || {};
options.method = ((_a = options.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || DEFAULT_REQUEST_METHOD;
const url = await prepareUrl(testRun, currentPageUrl, options.url, callsite);
const withCredentials = !currentPageUrl.host || (0, testcafe_hammerhead_1.sameOriginCheck)(currentPageUrl.href, url.href) || options.withCredentials || false;
const body = transformBody(options.headers, options.body);
const headers = await prepareHeaders(options, currentPageUrl, url, body, testRun, withCredentials);
let auth = options.auth;
const { hostname, port, href, partAfterHost, protocol, } = await resolveUrlParts(testRun, url, withCredentials);
if (!auth && url.username && url.password) {
auth = {
username: url.username,
password: url.password,
};
}
const requestParams = {
method: options.method,
url: href,
protocol: protocol,
hostname: hostname,
host: hostname,
port: port,
path: prepareSearchParams(partAfterHost, options.params),
auth: auth && withCredentials ? `${auth.username}:${auth.password}` : void 0,
headers: headers,
credentials: withCredentials ? testRun.session.getAuthCredentials() : void 0,
body: body,
disableHttp2: testRun.session.isHttp2Disabled(),
requestTimeout: {
ajax: options.timeout,
page: options.timeout,
},
};
if (options.proxy) {
requestParams.externalProxySettings = {
host: options.proxy.host,
hostname: options.proxy.host,
port: options.proxy.port.toString(),
proxyAuth: options.proxy.auth ? `${options.proxy.auth.username}:${options.proxy.auth.password}` : void 0,
};
requestParams.protocol = url.protocol;
requestParams.host = url.host;
requestParams.hostname = url.hostname;
requestParams.port = url.port;
requestParams.path = prepareSearchParams(url.pathname + url.search, options.params);
}
return new testcafe_hammerhead_1.RequestOptions(requestParams);
}
exports.createRequestOptions = createRequestOptions;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLXJlcXVlc3Qtb3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0LXJ1bi9yZXF1ZXN0L2NyZWF0ZS1yZXF1ZXN0LW9wdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0EsbUNBTWdCO0FBQ2hCLDBEQUFpQztBQUNqQyw2Q0FLc0I7QUFDdEIsNkRBSzZCO0FBRTdCLCtFQUF1RDtBQUN2RCw0RUFBb0Q7QUFDcEQsOENBQW9EO0FBQ3BELGtEQUFnRDtBQUNoRCxpREFBeUQ7QUFHekQsTUFBTSxjQUFjLEdBQWMsRUFBRSxDQUFDLHNCQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsR0FBRyx1QkFBYSxDQUFDLElBQUksS0FBSyx1QkFBYSxDQUFDLFNBQVMsS0FBSyx1QkFBYSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7QUFDdkksTUFBTSx5QkFBeUIsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDM0QsTUFBTSxzQkFBc0IsR0FBTSxLQUFLLENBQUM7QUFDeEMsTUFBTSxnQkFBZ0IsR0FBWSxPQUFPLENBQUM7QUFFMUMsU0FBUyx5QkFBeUIsQ0FBRSxPQUE0QixFQUFFLEtBQWE7SUFDM0UsSUFBSSxDQUFDLElBQUEsb0JBQVcsRUFBQyxPQUFPLENBQUMsSUFBSSxJQUFBLG9CQUFXLEVBQUMsT0FBTyxDQUFDLHNCQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkUsT0FBTyxDQUFDLHNCQUFZLENBQUMsV0FBVyxDQUFDLEdBQUcsS0FBSyxDQUFDO0FBQ2xELENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBRSxLQUFjO0lBQzNCLElBQUksS0FBSyxLQUFLLElBQUk7UUFDZCxPQUFPLE1BQU0sQ0FBQztJQUVsQixJQUFJLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQ2xDLE9BQU8sS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FB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LElBQUksRUFBRSxPQUFPLENBQUMsT0FBTztTQUN4QjtLQUNKLENBQUM7SUFFRixJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUU7UUFDZixhQUFhLENBQUMscUJBQXFCLEdBQUc7WUFDbEMsSUFBSSxFQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSTtZQUM3QixRQUFRLEVBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJO1lBQzdCLElBQUksRUFBTyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDeEMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1NBQzNHLENBQUM7UUFFRixhQUFhLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFDdEMsYUFBYSxDQUFDLElBQUksR0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ2xDLGFBQWEsQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUN0QyxhQUFhLENBQUMsSUFBSSxHQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDbEMsYUFBYSxDQUFDLElBQUksR0FBTyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzNGO0lBRUQsT0FBTyxJQUFJLG9DQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQTVERCxvREE0REMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPdXRnb2luZ0h0dHBIZWFkZXJzIH0gZnJvbSAnaHR0cCc7XG5pbXBvcnQge1xuICAgIGNhc3RBcnJheSxcbiAgICBpc0FycmF5QnVmZmVyLFxuICAgIGlzQnVmZmVyLFxuICAgIGlzT2JqZWN0LFxuICAgIGlzVW5kZWZpbmVkLFxufSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGlzU3RyZWFtIGZyb20gJ2lzLXN0cmVhbSc7XG5pbXBvcnQge1xuICAgIEF1dGhPcHRpb25zLFxuICAgIENyZWRlbnRpYWxzLFxuICAgIEV4dGVybmFsUmVxdWVzdE9wdGlvbnMsXG4gICAgUGFyYW1zLFxufSBmcm9tICcuL2ludGVyZmFjZXMnO1xuaW1wb3J0IHtcbiAgICBSZXF1ZXN0T3B0aW9ucyxcbiAgICBwYXJzZVByb3h5VXJsLFxuICAgIFJlcXVlc3RPcHRpb25zUGFyYW1zLFxuICAgIHNhbWVPcmlnaW5DaGVjayxcbn0gZnJvbSAndGVzdGNhZmUtaGFtbWVyaGVhZCc7XG5pbXBvcnQgVGVzdFJ1biBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgQ09OVEVOVF9UWVBFUyBmcm9tICcuLi8uLi9hc3NldHMvY29udGVudC10eXBlcyc7XG5pbXBvcnQgSFRUUF9IRUFERVJTIGZyb20gJy4uLy4uL3V0aWxzL2h0dHAtaGVhZGVycyc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uLy4uL2Vycm9ycy90eXBlcyc7XG5pbXBvcnQgeyBBUElFcnJvciB9IGZyb20gJy4uLy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCB7IEdldFByb3h5VXJsQ29tbWFuZCB9IGZyb20gJy4uL2NvbW1hbmRzL2FjdGlvbnMnO1xuaW1wb3J0IHsgQ2FsbHNpdGVSZWNvcmQgfSBmcm9tICdAZGV2ZXhwcmVzcy9jYWxsc2l0ZS1yZWNvcmQnO1xuXG5jb25zdCBERUZBVUxUX0FDQ0VQVCAgICAgICAgICAgID0geyBbSFRUUF9IRUFERVJTLmFjY2VwdF06IGAke0NPTlRFTlRfVFlQRVMuanNvbn0sICR7Q09OVEVOVF9UWVBFUy50ZXh0UGxhaW59LCAke0NPTlRFTlRfVFlQRVMuYWxsfWAgfTtcbmNvbnN0IE1FVEhPRFNfV0lUSF9DT05URU5UX1RZUEUgPSBbJ1BPU1QnLCAnUFVUJywgJ1BBVENIJ107XG5jb25zdCBERUZBVUxUX1JFUVVFU1RfTUVUSE9EICAgID0gJ0dFVCc7XG5jb25zdCBERUZBVUxUX1BST1RPQ09MICAgICAgICAgID0gJ2h0dHA6JztcblxuZnVuY3Rpb24gc2V0Q29udGVudFR5cGVJZk5vdEV4aXN0cyAoaGVhZGVyczogT3V0Z29pbmdIdHRwSGVhZGVycywgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghaXNVbmRlZmluZWQoaGVhZGVycykgJiYgaXNVbmRlZmluZWQoaGVhZGVyc1tIVFRQX0hFQURFUlMuY29udGVudFR5cGVdKSlcbiAgICAgICAgaGVhZGVyc1tIVFRQX0hFQURFUlMuY29udGVudFR5cGVdID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHR5cGVPZiAodmFsdWU6IHVua25vd24pOiBzdHJpbmcge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbClcbiAgICAgICAgcmV0dXJuICdudWxsJztcblxuICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKVxuICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IubmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gdHJhbnNmb3JtQm9keSAoaGVhZGVyczogT3V0Z29pbmdIdHRwSGVhZGVycywgYm9keT86IGFueSk6IEJ1ZmZlciB7XG4gICAgaWYgKCFib2R5KVxuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oJycpO1xuXG4gICAgaWYgKHR5cGVPZihib2R5KSA9PT0gJ2Zvcm1kYXRhJyB8fFxuICAgICAgICB0eXBlT2YoYm9keSkgPT09ICdmaWxlJyB8fFxuICAgICAgICB0eXBlT2YoYm9keSkgPT09ICdibG9iJyB8fFxuICAgICAgICBpc0FycmF5QnVmZmVyKGJvZHkpIHx8XG4gICAgICAgIGlzQnVmZmVyKGJvZHkpIHx8XG4gICAgICAgIGlzU3RyZWFtKGJvZHkpXG4gICAgKVxuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oYm9keSk7XG4gICAgZWxzZSBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KGJvZHkpKVxuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oYm9keS5idWZmZXIpO1xuXG4gICAgZWxzZSBpZiAoYm9keSBpbnN0YW5jZW9mIFVSTFNlYXJjaFBhcmFtcykge1xuICAgICAgICBzZXRDb250ZW50VHlwZUlmTm90RXhpc3RzKGhlYWRlcnMsIGAke0NPTlRFTlRfVFlQRVMudXJsZW5jb2RlZH07Y2hhcnNldD11dGYtOGApO1xuXG4gICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShib2R5LnRvU3RyaW5nKCkpO1xuICAgIH1cbiAgICBlbHNlIGlmIChpc09iamVjdChib2R5KSB8fCBoZWFkZXJzICYmIGhlYWRlcnNbSFRUUF9IRUFERVJTLmNvbnRlbnRUeXBlXSA9PT0gQ09OVEVOVF9UWVBFUy5qc29uKSB7XG4gICAgICAgIHNldENvbnRlbnRUeXBlSWZOb3RFeGlzdHMoaGVhZGVycywgQ09OVEVOVF9UWVBFUy5qc29uKTtcblxuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoYm9keSkpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycpXG4gICAgICAgIHNldENvbnRlbnRUeXBlSWZOb3RFeGlzdHMoaGVhZGVycywgQ09OVEVOVF9UWVBFUy50ZXh0UGxhaW4pO1xuXG4gICAgcmV0dXJuIGJvZHk7XG59XG5cbmZ1bmN0aW9uIGdldEF1dGhTdHJpbmcgKGF1dGg6IEF1dGhPcHRpb25zKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ0Jhc2ljICcgKyBCdWZmZXIuZnJvbShhdXRoLnVzZXJuYW1lICsgJzonICsgYXV0aC5wYXNzd29yZCwgJ3V0ZjgnKS50b1N0cmluZygnYmFzZTY0Jyk7XG59XG5cbmZ1bmN0aW9uIGNoYW5nZUhlYWRlck5hbWVzVG9Mb3dlcmNhc2UgKGhlYWRlcnM6IE91dGdvaW5nSHR0cEhlYWRlcnMpOiBPdXRnb2luZ0h0dHBIZWFkZXJzIHtcbiAgICBjb25zdCBsb3dlckNhc2VIZWFkZXJzOiBPdXRnb2luZ0h0dHBIZWFkZXJzID0ge307XG5cbiAgICBPYmplY3Qua2V5cyhoZWFkZXJzKS5mb3JFYWNoKGhlYWRlck5hbWUgPT4ge1xuICAgICAgICBsb3dlckNhc2VIZWFkZXJzW2hlYWRlck5hbWUudG9Mb3dlckNhc2UoKV0gPSBoZWFkZXJzW2hlYWRlck5hbWVdO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGxvd2VyQ2FzZUhlYWRlcnM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHByZXBhcmVIZWFkZXJzIChvcHRpb25zOiBFeHRlcm5hbFJlcXVlc3RPcHRpb25zLCBjdXJyZW50UGFnZVVybDogVVJMLCB1cmw6IFVSTCwgYm9keTogQnVmZmVyLCB0ZXN0UnVuOiBUZXN0UnVuLCB3aXRoQ3JlZGVudGlhbHM6IGJvb2xlYW4pOiBQcm9taXNlPE91dGdvaW5nSHR0cEhlYWRlcnM+IHtcbiAgICBjb25zdCB7IGhvc3QsIG9yaWdpbiB9ICAgICAgICAgICAgICAgICAgICAgID0gdXJsO1xuICAgIGNvbnN0IHsgbWV0aG9kLCBwcm94eSwgYXV0aCwgaGVhZGVycyA9IHt9IH0gPSBvcHRpb25zO1xuICAgIGNvbnN0IHByZXBhcmVkSGVhZGVyczogT3V0Z29pbmdIdHRwSGVhZGVycyAgPSBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX0FDQ0VQVCwgY2hhbmdlSGVhZGVyTmFtZXNUb0xvd2VyY2FzZShoZWFkZXJzKSk7XG5cbiAgICBwcmVwYXJlZEhlYWRlcnNbSFRUUF9IRUFERVJTLmhvc3RdICAgICAgICAgID0gaG9zdDtcbiAgICBwcmVwYXJlZEhlYWRlcnNbSFRUUF9IRUFERVJTLm9yaWdpbl0gICAgICAgID0gb3JpZ2luO1xuICAgIHByZXBhcmVkSGVhZGVyc1tIVFRQX0hFQURFUlMuY29udGVudExlbmd0aF0gPSBib2R5Lmxlbmd0aDtcblxuICAgIGlmIChtZXRob2QgJiYgTUVUSE9EU19XSVRIX0NPTlRFTlRfVFlQRS5pbmNsdWRlcyhTdHJpbmcobWV0aG9kKSkpXG4gICAgICAgIHByZXBhcmVkSGVhZGVyc1tIVFRQX0hFQURFUlMuY29udGVudFR5cGVdID0gcHJlcGFyZWRIZWFkZXJzW0hUVFBfSEVBREVSUy5jb250ZW50VHlwZV0gfHwgQ09OVEVOVF9UWVBFUy51cmxlbmNvZGVkO1xuXG4gICAgaWYgKGF1dGggJiYgd2l0aENyZWRlbnRpYWxzKVxuICAgICAgICBwcmVwYXJlZEhlYWRlcnNbSFRUUF9IRUFERVJTLmF1dGhvcml6YXRpb25dID0gZ2V0QXV0aFN0cmluZyhhdXRoKTtcblxuICAgIGlmIChwcm94eT8uYXV0aClcbiAgICAgICAgcHJlcGFyZWRIZWFkZXJzW0hUVFBfSEVBREVSUy5wcm94eUF1dGhvcml6YXRpb25dID0gZ2V0QXV0aFN0cmluZyhwcm94eS5hdXRoKTtcblxuICAgIGlmICh3aXRoQ3JlZGVudGlhbHMpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFBhZ2VDb29raWVzID0gYXdhaXQgdGVzdFJ1bi5jb29raWVQcm92aWRlci5nZXRDb29raWVIZWFkZXIoY3VycmVudFBhZ2VVcmwuaHJlZiwgY3VycmVudFBhZ2VVcmwuaG9zdG5hbWUpO1xuXG4gICAgICAgIGlmIChjdXJyZW50UGFnZUNvb2tpZXMpXG4gICAgICAgICAgICBwcmVwYXJlZEhlYWRlcnNbSFRUUF9IRUFERVJTLmNvb2tpZV0gPSBjdXJyZW50UGFnZUNvb2tpZXM7XG4gICAgfVxuXG4gICAgLy9OT1RFOiBBZGRpdGlvbmFsIGhlYWRlciB0byByZWNvZ25pemUgQVBJIHJlcXVlc3RzIGluIHRoZSBoYW1tZXJoZWFkXG4gICAgcHJlcGFyZWRIZWFkZXJzW0hUVFBfSEVBREVSUy5pc0FwaVJlcXVlc3RdID0gJ3RydWUnO1xuXG4gICAgcmV0dXJuIHByZXBhcmVkSGVhZGVycztcbn1cblxuYXN5bmMgZnVuY3Rpb24gcHJlcGFyZVVybCAodGVzdFJ1bjogVGVzdFJ1biwgY3VycmVudFBhZ2VVcmw6IFVSTCwgdXJsOiBzdHJpbmcgfCBVUkwsIGNhbGxzaXRlOiBDYWxsc2l0ZVJlY29yZCB8IG51bGwpOiBQcm9taXNlPFVSTD4ge1xuICAgIGxldCBwcmVwYXJlZFVybDogVVJMO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgcHJlcGFyZWRVcmwgPSB1cmwgaW5zdGFuY2VvZiBVUkxcbiAgICAgICAgICAgID8gdXJsXG4gICAgICAgICAgICA6IG5ldyBVUkwodXJsLCBjdXJyZW50UGFnZVVybC5ob3N0bmFtZSA/IGN1cnJlbnRQYWdlVXJsLm9yaWdpbiA6IHZvaWQgMCk7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBBUElFcnJvcihjYWxsc2l0ZSwgUlVOVElNRV9FUlJPUlMucmVxdWVzdFVybEludmFsaWRWYWx1ZUVycm9yLCB1cmwpO1xuICAgIH1cblxuICAgIHJldHVybiBwcmVwYXJlZFVybDtcbn1cblxuZnVuY3Rpb24gcHJlcGFyZVNlYXJjaFBhcmFtcyAodXJsOiBzdHJpbmcsIHBhcmFtcz86IFBhcmFtcyk6IHN0cmluZyB7XG4gICAgaWYgKCFwYXJhbXMpXG4gICAgICAgIHJldHVybiB1cmw7XG5cbiAgICBsZXQgc2VhcmNoUGFyYW1zOiBVUkxTZWFyY2hQYXJhbXM7XG5cbiAgICBpZiAocGFyYW1zIGluc3RhbmNlb2YgVVJMU2VhcmNoUGFyYW1zKVxuICAgICAgICBzZWFyY2hQYXJhbXMgPSBwYXJhbXM7XG4gICAgZWxzZSB7XG4gICAgICAgIHNlYXJjaFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcblxuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBwYXJhbXMpIHtcbiAgICAgICAgICAgIGlmICghcGFyYW1zW2tleV0pXG4gICAgICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgICAgIGNhc3RBcnJheShwYXJhbXNba2V5XSkuZm9yRWFjaCh2ID0+IHtcbiAgICAgICAgICAgICAgICBzZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgdHlwZW9mIHYgPT09ICdvYmplY3QnID8gSlNPTi5zdHJpbmdpZnkodikgOiBTdHJpbmcodikpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYCR7dXJsfSR7dXJsLmluY2x1ZGVzKCc/JykgPyAnJicgOiAnPyd9JHtzZWFyY2hQYXJhbXMudG9TdHJpbmcoKX1gO1xufVxuXG5mdW5jdGlvbiBnZXRQcm94eVVybCAodGVzdFJ1bjogVGVzdFJ1biwgdXJsOiBzdHJpbmcsIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4pOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiB0ZXN0UnVuLmV4ZWN1dGVDb21tYW5kKG5ldyBHZXRQcm94eVVybENvbW1hbmQoe1xuICAgICAgICB1cmw6ICAgICB1cmwsXG4gICAgICAgIG9wdGlvbnM6IHsgY3JlZGVudGlhbHM6IHdpdGhDcmVkZW50aWFscyA/IENyZWRlbnRpYWxzLmluY2x1ZGUgOiBDcmVkZW50aWFscy5vbWl0IH0sXG4gICAgfSwgdGVzdFJ1biwgdHJ1ZSkpIGFzIFByb21pc2U8c3RyaW5nPjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZU5hdGl2ZUF1dG9tYXRpb25VcmxQYXJ0cyAodXJsOiBVUkwpOiBQcm9taXNlPHsgaG9zdG5hbWU6IHN0cmluZzsgcHJvdG9jb2w6IHN0cmluZzsgcG9ydDogc3RyaW5nOyBocmVmOiBzdHJpbmc7IHBhcnRBZnRlckhvc3Q6IHN0cmluZyB9PiB7XG4gICAgY29uc3Qge1xuICAgICAgICBocmVmLFxuICAgICAgICBob3N0bmFtZSxcbiAgICAgICAgcG9ydCxcbiAgICAgICAgcGF0aG5hbWUsXG4gICAgICAgIHNlYXJjaCxcbiAgICAgICAgcHJvdG9jb2wsXG4gICAgfSA9IHVybDtcblxuICAgIGNvbnN0IHBhcnRBZnRlckhvc3QgPSBbcGF0aG5hbWUsIHNlYXJjaF0uam9pbignJyk7XG5cbiAgICByZXR1cm4geyBwYXJ0QWZ0ZXJIb3N0LCBocmVmLCBob3N0bmFtZSwgcG9ydCwgcHJvdG9jb2wgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZVBveHlVcmxQYXJ0cyAodGVzdFJ1bjogVGVzdFJ1biwgdXJsOiBVUkwsIHdpdGhDcmVkZW50aWFsczogYm9vbGVhbik6IFByb21pc2U8eyBob3N0bmFtZTogc3RyaW5nOyBwcm90b2NvbDogc3RyaW5nOyBwb3J0OiBzdHJpbmc7IGhyZWY6IHN0cmluZzsgcGFydEFmdGVySG9zdDogc3RyaW5nIH0+IHtcbiAgICBjb25zdCBocmVmICAgICAgICAgICAgICAgPSBhd2FpdCBnZXRQcm94eVVybCh0ZXN0UnVuLCB1cmwuaHJlZiwgd2l0aENyZWRlbnRpYWxzKTtcbiAgICBjb25zdCB1cmxPYmogICAgICAgICAgICAgPSBhd2FpdCBwYXJzZVByb3h5VXJsKGhyZWYpO1xuICAgIGNvbnN0IHsgcGFydEFmdGVySG9zdCB9ICA9IHVybE9iajtcbiAgICBjb25zdCB7IGhvc3RuYW1lLCBwb3J0IH0gPSB1cmxPYmoucHJveHk7XG5cbiAgICByZXR1cm4geyBwYXJ0QWZ0ZXJIb3N0LCBocmVmLCBob3N0bmFtZSwgcG9ydCwgcHJvdG9jb2w6IERFRkFVTFRfUFJPVE9DT0wgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVVybFBhcnRzICh0ZXN0UnVuOiBUZXN0UnVuLCB1cmw6IFVSTCwgd2l0aENyZWRlbnRpYWxzOiBib29sZWFuKTogUHJvbWlzZTx7IGhvc3RuYW1lOiBzdHJpbmc7IHByb3RvY29sOiBzdHJpbmc7IHBvcnQ6IHN0cmluZzsgaHJlZjogc3RyaW5nOyBwYXJ0QWZ0ZXJIb3N0OiBzdHJpbmcgfT4ge1xuICAgIHJldHVybiB0ZXN0UnVuLmlzTmF0aXZlQXV0b21hdGlvbiA/IHJlc29sdmVOYXRpdmVBdXRvbWF0aW9uVXJsUGFydHModXJsKSA6IHJlc29sdmVQb3h5VXJsUGFydHModGVzdFJ1biwgdXJsLCB3aXRoQ3JlZGVudGlhbHMpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlUmVxdWVzdE9wdGlvbnMgKGN1cnJlbnRQYWdlVXJsOiBVUkwsIHRlc3RSdW46IFRlc3RSdW4sIG9wdGlvbnM6IEV4dGVybmFsUmVxdWVzdE9wdGlvbnMsIGNhbGxzaXRlOiBDYWxsc2l0ZVJlY29yZCB8IG51bGwpOiBQcm9taXNlPFJlcXVlc3RPcHRpb25zPiB7XG4gICAgb3B0aW9ucy5oZWFkZXJzID0gb3B0aW9ucy5oZWFkZXJzIHx8IHt9O1xuICAgIG9wdGlvbnMubWV0aG9kICA9IG9wdGlvbnMubWV0aG9kPy50b1VwcGVyQ2FzZSgpIHx8IERFRkFVTFRfUkVRVUVTVF9NRVRIT0Q7XG5cbiAgICBjb25zdCB1cmwgICAgICAgICAgICAgPSBhd2FpdCBwcmVwYXJlVXJsKHRlc3RSdW4sIGN1cnJlbnRQYWdlVXJsLCBvcHRpb25zLnVybCwgY2FsbHNpdGUpO1xuICAgIGNvbnN0IHdpdGhDcmVkZW50aWFscyA9ICFjdXJyZW50UGFnZVVybC5ob3N0IHx8IHNhbWVPcmlnaW5DaGVjayhjdXJyZW50UGFnZVVybC5ocmVmLCB1cmwuaHJlZikgfHwgb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMgfHwgZmFsc2U7XG4gICAgY29uc3QgYm9keSAgICAgICAgICAgID0gdHJhbnNmb3JtQm9keShvcHRpb25zLmhlYWRlcnMsIG9wdGlvbnMuYm9keSk7XG4gICAgY29uc3QgaGVhZGVycyAgICAgICAgID0gYXdhaXQgcHJlcGFyZUhlYWRlcnMob3B0aW9ucywgY3VycmVudFBhZ2VVcmwsIHVybCwgYm9keSwgdGVzdFJ1biwgd2l0aENyZWRlbnRpYWxzKTtcbiAgICBsZXQgYXV0aCAgICAgICAgICAgICAgPSBvcHRpb25zLmF1dGg7XG5cbiAgICBjb25zdCB7XG4gICAgICAgIGhvc3RuYW1lLFxuICAgICAgICBwb3J0LFxuICAgICAgICBocmVmLFxuICAgICAgICBwYXJ0QWZ0ZXJIb3N0LFxuICAgICAgICBwcm90b2NvbCxcbiAgICB9ID0gYXdhaXQgcmVzb2x2ZVVybFBhcnRzKHRlc3RSdW4sIHVybCwgd2l0aENyZWRlbnRpYWxzKTtcblxuICAgIGlmICghYXV0aCAmJiB1cmwudXNlcm5hbWUgJiYgdXJsLnBhc3N3b3JkKSB7XG4gICAgICAgIGF1dGggPSB7XG4gICAgICAgICAgICB1c2VybmFtZTogdXJsLnVzZXJuYW1lLFxuICAgICAgICAgICAgcGFzc3dvcmQ6IHVybC5wYXNzd29yZCxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0UGFyYW1zOiBSZXF1ZXN0T3B0aW9uc1BhcmFtcyA9IHtcbiAgICAgICAgbWV0aG9kOiAgICAgICAgIG9wdGlvbnMubWV0aG9kLFxuICAgICAgICB1cmw6ICAgICAgICAgICAgaHJlZixcbiAgICAgICAgcHJvdG9jb2w6ICAgICAgIHByb3RvY29sLFxuICAgICAgICBob3N0bmFtZTogICAgICAgaG9zdG5hbWUsXG4gICAgICAgIGhvc3Q6ICAgICAgICAgICBob3N0bmFtZSxcbiAgICAgICAgcG9ydDogICAgICAgICAgIHBvcnQsXG4gICAgICAgIHBhdGg6ICAgICAgICAgICBwcmVwYXJlU2VhcmNoUGFyYW1zKHBhcnRBZnRlckhvc3QsIG9wdGlvbnMucGFyYW1zKSxcbiAgICAgICAgYXV0aDogICAgICAgICAgIGF1dGggJiYgd2l0aENyZWRlbnRpYWxzID8gYCR7YXV0aC51c2VybmFtZX06JHthdXRoLnBhc3N3b3JkfWAgOiB2b2lkIDAsXG4gICAgICAgIGhlYWRlcnM6ICAgICAgICBoZWFkZXJzLFxuICAgICAgICBjcmVkZW50aWFsczogICAgd2l0aENyZWRlbnRpYWxzID8gdGVzdFJ1bi5zZXNzaW9uLmdldEF1dGhDcmVkZW50aWFscygpIDogdm9pZCAwLFxuICAgICAgICBib2R5OiAgICAgICAgICAgYm9keSxcbiAgICAgICAgZGlzYWJsZUh0dHAyOiAgIHRlc3RSdW4uc2Vzc2lvbi5pc0h0dHAyRGlzYWJsZWQoKSxcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQ6IHtcbiAgICAgICAgICAgIGFqYXg6IG9wdGlvbnMudGltZW91dCxcbiAgICAgICAgICAgIHBhZ2U6IG9wdGlvbnMudGltZW91dCxcbiAgICAgICAgfSxcbiAgICB9O1xuXG4gICAgaWYgKG9wdGlvbnMucHJveHkpIHtcbiAgICAgICAgcmVxdWVzdFBhcmFtcy5leHRlcm5hbFByb3h5U2V0dGluZ3MgPSB7XG4gICAgICAgICAgICBob3N0OiAgICAgIG9wdGlvbnMucHJveHkuaG9zdCxcbiAgICAgICAgICAgIGhvc3RuYW1lOiAgb3B0aW9ucy5wcm94eS5ob3N0LFxuICAgICAgICAgICAgcG9ydDogICAgICBvcHRpb25zLnByb3h5LnBvcnQudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIHByb3h5QXV0aDogb3B0aW9ucy5wcm94eS5hdXRoID8gYCR7b3B0aW9ucy5wcm94eS5hdXRoLnVzZXJuYW1lfToke29wdGlvbnMucHJveHkuYXV0aC5wYXNzd29yZH1gIDogdm9pZCAwLFxuICAgICAgICB9O1xuXG4gICAgICAgIHJlcXVlc3RQYXJhbXMucHJvdG9jb2wgPSB1cmwucHJvdG9jb2w7XG4gICAgICAgIHJlcXVlc3RQYXJhbXMuaG9zdCAgICAgPSB1cmwuaG9zdDtcbiAgICAgICAgcmVxdWVzdFBhcmFtcy5ob3N0bmFtZSA9IHVybC5ob3N0bmFtZTtcbiAgICAgICAgcmVxdWVzdFBhcmFtcy5wb3J0ICAgICA9IHVybC5wb3J0O1xuICAgICAgICByZXF1ZXN0UGFyYW1zLnBhdGggICAgID0gcHJlcGFyZVNlYXJjaFBhcmFtcyh1cmwucGF0aG5hbWUgKyB1cmwuc2VhcmNoLCBvcHRpb25zLnBhcmFtcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBSZXF1ZXN0T3B0aW9ucyhyZXF1ZXN0UGFyYW1zKTtcbn1cbiJdfQ==