Skip to content

Instantly share code, notes, and snippets.

@vladfrangu
Created October 5, 2023 12:42
Show Gist options
  • Save vladfrangu/43d58632db350e3a2522eb91e8c25ed0 to your computer and use it in GitHub Desktop.
Save vladfrangu/43d58632db350e3a2522eb91e8c25ed0 to your computer and use it in GitHub Desktop.
Vitest issues
// /@vite/env
const context = (() => {
if (typeof globalThis !== 'undefined') {
return globalThis;
}
else if (typeof self !== 'undefined') {
return self;
}
else if (typeof window !== 'undefined') {
return window;
}
else {
return Function('return this')();
}
})();
// assign defines
const defines = {};
Object.keys(defines).forEach((key) => {
const segments = key.split('.');
let target = context;
for (let i = 0; i < segments.length; i++) {
const segment = segments[i];
if (i === segments.length - 1) {
target[segment] = defines[key];
}
else {
target = target[segment] || (target[segment] = {});
}
}
});
//# sourceMappingSource=vite-node
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQ0EsTUFBTSxPQUFPLEdBQUcsQ0FBQyxNQUFNO0FBQ3ZCLElBQUksSUFBSSxPQUFPLFVBQVUsS0FBSyxXQUFXLEVBQUU7QUFDM0MsUUFBUSxPQUFPLFVBQVUsQ0FBQztBQUMxQixLQUFLO0FBQ0wsU0FBUyxJQUFJLE9BQU8sSUFBSSxLQUFLLFdBQVcsRUFBRTtBQUMxQyxRQUFRLE9BQU8sSUFBSSxDQUFDO0FBQ3BCLEtBQUs7QUFDTCxTQUFTLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVyxFQUFFO0FBQzVDLFFBQVEsT0FBTyxNQUFNLENBQUM7QUFDdEIsS0FBSztBQUNMLFNBQVM7QUFDVCxRQUFRLE9BQU8sUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7QUFDekMsS0FBSztBQUNMLENBQUMsR0FBRyxDQUFDO0FBQ0w7QUFDQSxNQUFNLE9BQU8sR0FBRztBQUNoQixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsS0FBSztBQUN0QyxJQUFJLE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDcEMsSUFBSSxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUM7QUFDekIsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM5QyxRQUFRLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNwQyxRQUFRLElBQUksQ0FBQyxLQUFLLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0FBQ3ZDLFlBQVksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMzQyxTQUFTO0FBQ1QsYUFBYTtBQUNiLFlBQVksTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7QUFDL0QsU0FBUztBQUNULEtBQUs7QUFDTCxDQUFDLENBQUMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiZW52LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xuY29uc3QgY29udGV4dCA9ICgoKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gZ2xvYmFsVGhpcztcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiBzZWxmO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gd2luZG93O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG4gICAgfVxufSkoKTtcbi8vIGFzc2lnbiBkZWZpbmVzXG5jb25zdCBkZWZpbmVzID0gX19ERUZJTkVTX187XG5PYmplY3Qua2V5cyhkZWZpbmVzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBjb25zdCBzZWdtZW50cyA9IGtleS5zcGxpdCgnLicpO1xuICAgIGxldCB0YXJnZXQgPSBjb250ZXh0O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3Qgc2VnbWVudCA9IHNlZ21lbnRzW2ldO1xuICAgICAgICBpZiAoaSA9PT0gc2VnbWVudHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgdGFyZ2V0W3NlZ21lbnRdID0gZGVmaW5lc1trZXldO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGFyZ2V0ID0gdGFyZ2V0W3NlZ21lbnRdIHx8ICh0YXJnZXRbc2VnbWVudF0gPSB7fSk7XG4gICAgICAgIH1cbiAgICB9XG59KTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWVudi5qcy5tYXAiXSwiZmlsZSI6Ii9Adml0ZS9lbnYifQ==
// /Users/vlad/Development/Apify/crawlee/test/browser-pool/browser-plugins/plugins.test.ts
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var import_http = __toESM(require("http"));
var import_util = require("util");
var import_browser_pool = require("@crawlee/browser-pool");
var import_playwright = __toESM(require("playwright"));
var import_puppeteer = __toESM(require("puppeteer"));
var import_helper = require("test/shared/_helper");
var import_create_proxy_server = require("./create-proxy-server");
jest.setTimeout(12e4);
let port;
let server;
let serverAddress = "http://localhost:";
beforeAll(async () => {
[server, port] = await (0, import_helper.runExampleComServer)();
serverAddress += port;
});
afterAll(() => {
server.close();
});
const runPluginTest = (Plugin, Controller, library) => {
let plugin = new Plugin(library);
describe(`${plugin.constructor.name} - ${"name" in library ? library.name() : ""} general`, () => {
let browser;
beforeEach(() => {
plugin = new Plugin(library);
});
afterEach(async () => {
await browser?.close();
});
test("should launch browser", async () => {
browser = await plugin.launch();
expect(typeof browser.newPage).toBe("function");
expect(typeof browser.close).toBe("function");
});
test("should create launch context", () => {
const id = "abc";
const launchOptions = { foo: "bar" };
const proxyUrl = "http://proxy.com/";
const context = plugin.createLaunchContext({
id,
// @ts-expect-error Testing options
launchOptions
});
expect(context).toBeInstanceOf(import_browser_pool.LaunchContext);
context.proxyUrl = proxyUrl;
context.extend({
one: 1
});
const desiredObject = {
id,
launchOptions,
browserPlugin: plugin,
_proxyUrl: proxyUrl.slice(0, -1),
one: 1,
useIncognitoPages: false
};
expect(context.id).toEqual(desiredObject.id);
expect(context.launchOptions).toEqual(desiredObject.launchOptions);
expect(context.browserPlugin).toEqual(desiredObject.browserPlugin);
expect(context["_proxyUrl"]).toEqual(desiredObject._proxyUrl);
expect(context.one).toEqual(desiredObject.one);
expect(context.useIncognitoPages).toEqual(desiredObject.useIncognitoPages);
});
test("should get default launchContext values from plugin options", async () => {
const proxyUrl = "http://apify1234@10.10.10.0:8080/";
plugin = new Plugin(library, {
proxyUrl,
userDataDir: "test",
useIncognitoPages: true
});
const context = plugin.createLaunchContext();
expect(context.proxyUrl).toEqual(proxyUrl.slice(0, -1));
expect(context.useIncognitoPages).toBeTruthy();
expect(context.userDataDir).toEqual("test");
});
test("should create browser controller", () => {
const browserController = plugin.createController();
expect(browserController).toBeInstanceOf(Controller);
});
test("should work with cookies", async () => {
const browserController = plugin.createController();
const context = plugin.createLaunchContext();
browser = await plugin.launch(context);
browserController.assignBrowser(browser, context);
browserController.activate();
const page = await browserController.newPage();
await browserController.setCookies(page, [{ name: "TEST", value: "TESTER-COOKIE", url: serverAddress }]);
await page.goto(serverAddress, { waitUntil: "domcontentloaded" });
const cookies = await browserController.getCookies(page);
expect(cookies[0].name).toBe("TEST");
expect(cookies[0].value).toBe("TESTER-COOKIE");
});
test("newPage options cannot be used with persistent context", async () => {
const browserController = plugin.createController();
const context = plugin.createLaunchContext({
useIncognitoPages: false
});
browser = await plugin.launch(context);
browserController.assignBrowser(browser, context);
browserController.activate();
try {
const page = await browserController.newPage({});
await page.close();
expect(false).toBe(true);
} catch (error) {
expect(error.message).toBe("A new page can be created with provided context only when using incognito pages or experimental containers.");
}
});
});
};
describe("Plugins", () => {
let target;
let unprotectedProxy;
let protectedProxy;
beforeAll(async () => {
target = import_http.default.createServer((request, response) => {
response.end(request.socket.remoteAddress);
});
await (0, import_util.promisify)(target.listen.bind(target))(0, "127.0.0.1");
unprotectedProxy = (0, import_create_proxy_server.createProxyServer)("127.0.0.2", "", "");
await unprotectedProxy.listen();
protectedProxy = (0, import_create_proxy_server.createProxyServer)("127.0.0.3", "foo", "bar");
await protectedProxy.listen();
});
afterAll(async () => {
await (0, import_util.promisify)(target.close.bind(target))();
await unprotectedProxy.close(false);
await protectedProxy.close(false);
});
describe("Puppeteer specifics", () => {
let browser;
afterEach(async () => {
await browser.close();
});
test("should work with non authenticated proxyUrl", async () => {
const proxyUrl = `http://127.0.0.2:${unprotectedProxy.port}`;
const plugin = new import_browser_pool.PuppeteerPlugin(import_puppeteer.default);
const context = plugin.createLaunchContext({
proxyUrl,
launchOptions: {
args: [
// Exclude loopback interface from proxy bypass list,
// so the request to localhost goes through proxy.
// This way there's no need for a 3rd party server.
"--proxy-bypass-list=<-loopback>"
]
}
});
browser = await plugin.launch(context);
const page = await browser.newPage();
const response = await page.goto(`http://127.0.0.1:${target.address().port}`);
const text = await response.text();
expect(text).toBe("127.0.0.2");
await page.close();
});
test("should work with authenticated proxyUrl", async () => {
const proxyUrl = `http://foo:bar@127.0.0.3:${protectedProxy.port}`;
const plugin = new import_browser_pool.PuppeteerPlugin(import_puppeteer.default);
const context = plugin.createLaunchContext({
proxyUrl,
launchOptions: {
args: [
// Exclude loopback interface from proxy bypass list,
// so the request to localhost goes through proxy.
// This way there's no need for a 3rd party server.
"--proxy-bypass-list=<-loopback>"
]
}
});
browser = await plugin.launch(context);
const page = await browser.newPage();
const response = await page.goto(`http://127.0.0.1:${target.address().port}`);
const text = await response.text();
expect(text).toBe("127.0.0.3");
await page.close();
await browser.close();
});
test("should use persistent context by default", async () => {
const plugin = new import_browser_pool.PuppeteerPlugin(import_puppeteer.default);
const browserController = plugin.createController();
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
browserController.assignBrowser(browser, launchContext);
browserController.activate();
const page = await browserController.newPage();
const browserContext = page.browserContext();
expect(browserContext.isIncognito()).toBeFalsy();
});
test("should use incognito pages by option", async () => {
const plugin = new import_browser_pool.PuppeteerPlugin(import_puppeteer.default);
const browserController = plugin.createController();
const launchContext = plugin.createLaunchContext({ useIncognitoPages: true });
browser = await plugin.launch(launchContext);
browserController.assignBrowser(browser, launchContext);
browserController.activate();
const page = await browserController.newPage();
const browserContext = page.browserContext();
expect(browserContext.isIncognito()).toBeTruthy();
});
test("should pass launch options to browser", async () => {
const plugin = new import_browser_pool.PuppeteerPlugin(import_puppeteer.default);
const userAgent = "HelloWorld";
const launchOptions = {
args: [
`--user-agent=${userAgent}`
]
};
const launchContext = plugin.createLaunchContext({ launchOptions });
browser = await plugin.launch(launchContext);
expect(await browser.userAgent()).toBe(userAgent);
});
test("proxyUsername and proxyPassword as newPage options", async () => {
const plugin = new import_browser_pool.PuppeteerPlugin(import_puppeteer.default);
const browserController = new import_browser_pool.PuppeteerController(plugin);
const launchContext = plugin.createLaunchContext({
useIncognitoPages: true
});
browser = await plugin.launch(launchContext);
browserController.assignBrowser(browser, launchContext);
browserController.activate();
const page = await browserController.newPage({
proxyServer: `http://127.0.0.3:${protectedProxy.port}`,
proxyUsername: "foo",
proxyPassword: "bar",
proxyBypassList: ["<-loopback>"]
});
const response = await page.goto(`http://127.0.0.1:${target.address().port}`);
const text = await response.text();
expect(text).toBe(process.platform === "win32" ? "127.0.0.1" : "127.0.0.3");
await page.close();
});
});
runPluginTest(import_browser_pool.PuppeteerPlugin, import_browser_pool.PuppeteerController, import_puppeteer.default);
describe("Playwright specifics", () => {
let browser;
afterEach(async () => {
await browser.close();
});
describe.each(["chromium", "firefox", "webkit"])("with %s", (browserName) => {
test("should work with non authenticated proxyUrl", async () => {
const proxyUrl = `http://127.0.0.2:${unprotectedProxy.port}`;
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchOptions = browserName === "chromium" ? {
args: [
// Exclude loopback interface from proxy bypass list,
// so the request to localhost goes through proxy.
// This way there's no need for a 3rd party server.
"--proxy-bypass-list=<-loopback>"
]
} : void 0;
const context = plugin.createLaunchContext({
proxyUrl,
launchOptions
});
browser = await plugin.launch(context);
expect(context.launchOptions.proxy.server).toEqual(proxyUrl);
const page = await browser.newPage();
const response = await page.goto(`http://127.0.0.1:${target.address().port}`);
const text = await response.text();
expect(text).toBe("127.0.0.2");
await page.close();
});
test("should work with authenticated proxyUrl", async () => {
const proxyUrl = `http://foo:bar@127.0.0.3:${protectedProxy.port}`;
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchOptions = browserName === "chromium" ? {
args: [
// Exclude loopback interface from proxy bypass list,
// so the request to localhost goes through proxy.
// This way there's no need for a 3rd party server.
"--proxy-bypass-list=<-loopback>"
]
} : void 0;
const context = plugin.createLaunchContext({
proxyUrl,
launchOptions
});
browser = await plugin.launch(context);
const page = await browser.newPage();
const response = await page.goto(`http://127.0.0.1:${target.address().port}`);
const text = await response.text();
expect(text).toBe("127.0.0.3");
await page.close();
});
test("proxy as newPage option", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default.chromium);
const browserController = new import_browser_pool.PlaywrightController(plugin);
const launchContext = plugin.createLaunchContext({
useIncognitoPages: true
});
browser = await plugin.launch(launchContext);
browserController.assignBrowser(browser, launchContext);
browserController.activate();
const page = await browserController.newPage({
proxy: {
server: `http://127.0.0.3:${protectedProxy.port}`,
username: "foo",
password: "bar",
bypass: "<-loopback>"
}
});
const response = await page.goto(`http://127.0.0.1:${target.address().port}`);
const text = await response.text();
expect(text).toBe("127.0.0.3");
await page.close();
});
test("should use incognito context by option", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const browserController = plugin.createController();
const launchContext = plugin.createLaunchContext({ useIncognitoPages: true });
browser = await plugin.launch(launchContext);
browserController.assignBrowser(browser, launchContext);
browserController.activate();
const page = await browserController.newPage();
const browserContext = page.context();
await browserController.newPage();
expect(browserContext.pages()).toHaveLength(1);
});
test("should use persistent context by default", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const browserController = plugin.createController();
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
browserController.assignBrowser(browser, launchContext);
browserController.activate();
const page = await browserController.newPage();
const context = page.context();
await browserController.newPage();
expect(context.pages()).toHaveLength(3);
});
test("should pass launch options to browser", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
let ran = false;
const launchOptions = {
logger: {
isEnabled: () => {
ran = true;
return false;
},
log: () => {
}
}
};
const launchContext = plugin.createLaunchContext({ launchOptions });
browser = await plugin.launch(launchContext);
expect(ran).toBe(true);
});
describe("PlaywrightBrowser", () => {
test("should create new page", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
const page = await browser.newPage();
expect(typeof page.close).toBe("function");
expect(typeof page.evaluate).toBe("function");
});
test("should emit disconnected event on close", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
let called = false;
browser.on("disconnected", () => {
called = true;
});
await browser.close();
expect(called).toBe(true);
});
test("should be used only with incognito pages context", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext({ useIncognitoPages: false });
browser = await plugin.launch(launchContext);
expect(browser).toBeInstanceOf(import_browser_pool.PlaywrightBrowser);
await browser.close();
const launchContext2 = plugin.createLaunchContext({ useIncognitoPages: true });
browser = await plugin.launch(launchContext2);
expect(browser).not.toBeInstanceOf(import_browser_pool.PlaywrightBrowser);
});
test("should return correct version", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext({ useIncognitoPages: false });
browser = await plugin.launch(launchContext);
const version1 = browser.version();
await browser.close();
const launchContext2 = plugin.createLaunchContext({ useIncognitoPages: true });
browser = await plugin.launch(launchContext2);
expect(version1).toEqual(browser.version());
});
test("should return all contexts", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
const contexts = browser.contexts();
expect(contexts).toHaveLength(1);
expect(contexts[0]).toEqual(browser._browserContext);
});
test("should return correct connected status", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
expect(browser.isConnected()).toBe(true);
await browser.close();
expect(browser.isConnected()).toBe(false);
});
test("should throw on newContext call", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const launchContext = plugin.createLaunchContext();
browser = await plugin.launch(launchContext);
await expect(browser.newContext()).rejects.toThrow("Function `newContext()` is not available in incognito mode");
});
test("should have same public interface as playwright browserType", async () => {
const plugin = new import_browser_pool.PlaywrightPlugin(import_playwright.default[browserName]);
const originalFunctionNames = ["close", "contexts", "isConnected", "newContext", "newPage", "version"];
const launchContext = plugin.createLaunchContext({ useIncognitoPages: true });
browser = await plugin.launch(launchContext);
for (const originalFunctionName of originalFunctionNames) {
expect(typeof browser[originalFunctionName]).toBe("function");
}
expect.hasAssertions();
});
});
});
});
runPluginTest(import_browser_pool.PlaywrightPlugin, import_browser_pool.PlaywrightController, import_playwright.default.chromium);
runPluginTest(import_browser_pool.PlaywrightPlugin, import_browser_pool.PlaywrightController, import_playwright.default.firefox);
runPluginTest(import_browser_pool.PlaywrightPlugin, import_browser_pool.PlaywrightController, import_playwright.default.webkit);
});
//# sourceMappingSource=vite-node
//# sourceMappingURL=data:application/json;charset=utf-8;base64,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O0FBQUEsTUFDTCxDQUFDO0FBQUEsSUFDTCxDQUFDO0FBQUEsRUFDTCxDQUFDO0FBRUQsZ0JBQWMsc0NBQWtCLDBDQUFzQixrQkFBQUEsUUFBVyxRQUFRO0FBQ3pFLGdCQUFjLHNDQUFrQiwwQ0FBc0Isa0JBQUFBLFFBQVcsT0FBTztBQUN4RSxnQkFBYyxzQ0FBa0IsMENBQXNCLGtCQUFBQSxRQUFXLE1BQU07QUFDM0UsQ0FBQyIsIm5hbWVzIjpbImh0dHAiLCJwdXBwZXRlZXIiLCJwbGF5d3JpZ2h0Il0sInNvdXJjZXMiOlsicGx1Z2lucy50ZXN0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU2VydmVyIH0gZnJvbSAnaHR0cCc7XG5pbXBvcnQgaHR0cCBmcm9tICdodHRwJztcbmltcG9ydCB0eXBlIHsgQWRkcmVzc0luZm8gfSBmcm9tICduZXQnO1xuaW1wb3J0IHsgcHJvbWlzaWZ5IH0gZnJvbSAndXRpbCc7XG5cbmltcG9ydCB7IFB1cHBldGVlclBsdWdpbiwgUGxheXdyaWdodFBsdWdpbiwgUHVwcGV0ZWVyQ29udHJvbGxlciwgUGxheXdyaWdodENvbnRyb2xsZXIsIFBsYXl3cmlnaHRCcm93c2VyLCBMYXVuY2hDb250ZXh0IH0gZnJvbSAnQGNyYXdsZWUvYnJvd3Nlci1wb29sJztcbmltcG9ydCB0eXBlIHsgVW53cmFwUHJvbWlzZSwgQ29tbW9uTGlicmFyeSB9IGZyb20gJ0BjcmF3bGVlL2Jyb3dzZXItcG9vbCc7XG5pbXBvcnQgcGxheXdyaWdodCBmcm9tICdwbGF5d3JpZ2h0JztcbmltcG9ydCB0eXBlIHsgU2VydmVyIGFzIFByb3h5Q2hhaW5TZXJ2ZXIgfSBmcm9tICdwcm94eS1jaGFpbic7XG5pbXBvcnQgdHlwZSB7IEJyb3dzZXIgfSBmcm9tICdwdXBwZXRlZXInO1xuaW1wb3J0IHB1cHBldGVlciBmcm9tICdwdXBwZXRlZXInO1xuaW1wb3J0IHsgcnVuRXhhbXBsZUNvbVNlcnZlciB9IGZyb20gJ3Rlc3Qvc2hhcmVkL19oZWxwZXInO1xuXG5pbXBvcnQgeyBjcmVhdGVQcm94eVNlcnZlciB9IGZyb20gJy4vY3JlYXRlLXByb3h5LXNlcnZlcic7XG5cbmplc3Quc2V0VGltZW91dCgxMjAwMDApO1xuXG5sZXQgcG9ydDogbnVtYmVyO1xubGV0IHNlcnZlcjogU2VydmVyO1xubGV0IHNlcnZlckFkZHJlc3MgPSAnaHR0cDovL2xvY2FsaG9zdDonO1xuXG5iZWZvcmVBbGwoYXN5bmMgKCkgPT4ge1xuICAgIFtzZXJ2ZXIsIHBvcnRdID0gYXdhaXQgcnVuRXhhbXBsZUNvbVNlcnZlcigpO1xuICAgIHNlcnZlckFkZHJlc3MgKz0gcG9ydDtcbn0pO1xuXG5hZnRlckFsbCgoKSA9PiB7XG4gICAgc2VydmVyLmNsb3NlKCk7XG59KTtcblxuY29uc3QgcnVuUGx1Z2luVGVzdCA9IDxcbiAgICBQIGV4dGVuZHMgdHlwZW9mIFBsYXl3cmlnaHRQbHVnaW4gfCB0eXBlb2YgUHVwcGV0ZWVyUGx1Z2luLFxuICAgIEMgZXh0ZW5kcyB0eXBlb2YgUHVwcGV0ZWVyQ29udHJvbGxlciB8IHR5cGVvZiBQbGF5d3JpZ2h0Q29udHJvbGxlcixcbiAgICBMIGV4dGVuZHMgQ29tbW9uTGlicmFyeSxcbj4oUGx1Z2luOiBQLCBDb250cm9sbGVyOiBDLCBsaWJyYXJ5OiBMKSA9PiB7XG4gICAgbGV0IHBsdWdpbiA9IG5ldyBQbHVnaW4obGlicmFyeSBhcyBuZXZlcik7XG5cbiAgICBkZXNjcmliZShgJHtwbHVnaW4uY29uc3RydWN0b3IubmFtZX0gLSAkeyduYW1lJyBpbiBsaWJyYXJ5ID8gbGlicmFyeS5uYW1lISgpIDogJyd9IGdlbmVyYWxgLCAoKSA9PiB7XG4gICAgICAgIGxldCBicm93c2VyOiBwbGF5d3JpZ2h0LkJyb3dzZXIgfCBVbndyYXBQcm9taXNlPFJldHVyblR5cGU8dHlwZW9mIHB1cHBldGVlclsnbGF1bmNoJ10+PiB8IHVuZGVmaW5lZDtcblxuICAgICAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgICAgICAgIHBsdWdpbiA9IG5ldyBQbHVnaW4obGlicmFyeSBhcyBuZXZlcik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyPy5jbG9zZSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0KCdzaG91bGQgbGF1bmNoIGJyb3dzZXInLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaCgpO1xuICAgICAgICAgICAgZXhwZWN0KHR5cGVvZiBicm93c2VyLm5ld1BhZ2UpLnRvQmUoJ2Z1bmN0aW9uJyk7XG4gICAgICAgICAgICBleHBlY3QodHlwZW9mIGJyb3dzZXIuY2xvc2UpLnRvQmUoJ2Z1bmN0aW9uJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCBjcmVhdGUgbGF1bmNoIGNvbnRleHQnLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpZCA9ICdhYmMnO1xuICAgICAgICAgICAgY29uc3QgbGF1bmNoT3B0aW9ucyA9IHsgZm9vOiAnYmFyJyB9O1xuICAgICAgICAgICAgY29uc3QgcHJveHlVcmwgPSAnaHR0cDovL3Byb3h5LmNvbS8nO1xuICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHtcbiAgICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRlc3Rpbmcgb3B0aW9uc1xuICAgICAgICAgICAgICAgIGxhdW5jaE9wdGlvbnMsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZXhwZWN0KGNvbnRleHQpLnRvQmVJbnN0YW5jZU9mKExhdW5jaENvbnRleHQpO1xuXG4gICAgICAgICAgICBjb250ZXh0LnByb3h5VXJsID0gcHJveHlVcmw7XG4gICAgICAgICAgICBjb250ZXh0LmV4dGVuZCh7XG4gICAgICAgICAgICAgICAgb25lOiAxLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGRlc2lyZWRPYmplY3QgPSB7XG4gICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgbGF1bmNoT3B0aW9ucyxcbiAgICAgICAgICAgICAgICBicm93c2VyUGx1Z2luOiBwbHVnaW4sXG4gICAgICAgICAgICAgICAgX3Byb3h5VXJsOiBwcm94eVVybC5zbGljZSgwLCAtMSksXG4gICAgICAgICAgICAgICAgb25lOiAxLFxuICAgICAgICAgICAgICAgIHVzZUluY29nbml0b1BhZ2VzOiBmYWxzZSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8vIGV4cGVjdChjb250ZXh0KS50b01hdGNoT2JqZWN0KGRlc2lyZWRPYmplY3QpXG4gICAgICAgICAgICAvLyBTd2l0Y2ggdG8gdGhpcyBhZnRlciB0aGUgaXNzdWUgd2l0aCBgVHlwZUVycm9yOiBwcm9wLnN0YXJ0c1dpdGggaXMgbm90IGEgZnVuY3Rpb25gIGlzIHNvbHZlZC5cblxuICAgICAgICAgICAgZXhwZWN0KGNvbnRleHQuaWQpLnRvRXF1YWwoZGVzaXJlZE9iamVjdC5pZCk7XG4gICAgICAgICAgICBleHBlY3QoY29udGV4dC5sYXVuY2hPcHRpb25zKS50b0VxdWFsKGRlc2lyZWRPYmplY3QubGF1bmNoT3B0aW9ucyk7XG4gICAgICAgICAgICBleHBlY3QoY29udGV4dC5icm93c2VyUGx1Z2luKS50b0VxdWFsKGRlc2lyZWRPYmplY3QuYnJvd3NlclBsdWdpbik7XG4gICAgICAgICAgICBleHBlY3QoY29udGV4dFsnX3Byb3h5VXJsJ10pLnRvRXF1YWwoZGVzaXJlZE9iamVjdC5fcHJveHlVcmwpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG4gICAgICAgICAgICBleHBlY3QoY29udGV4dC5vbmUpLnRvRXF1YWwoZGVzaXJlZE9iamVjdC5vbmUpO1xuICAgICAgICAgICAgZXhwZWN0KGNvbnRleHQudXNlSW5jb2duaXRvUGFnZXMpLnRvRXF1YWwoZGVzaXJlZE9iamVjdC51c2VJbmNvZ25pdG9QYWdlcyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCBnZXQgZGVmYXVsdCBsYXVuY2hDb250ZXh0IHZhbHVlcyBmcm9tIHBsdWdpbiBvcHRpb25zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcHJveHlVcmwgPSAnaHR0cDovL2FwaWZ5MTIzNEAxMC4xMC4xMC4wOjgwODAvJztcblxuICAgICAgICAgICAgcGx1Z2luID0gbmV3IFBsdWdpbihsaWJyYXJ5IGFzIG5ldmVyLCB7XG4gICAgICAgICAgICAgICAgcHJveHlVcmwsXG4gICAgICAgICAgICAgICAgdXNlckRhdGFEaXI6ICd0ZXN0JyxcbiAgICAgICAgICAgICAgICB1c2VJbmNvZ25pdG9QYWdlczogdHJ1ZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoKTtcblxuICAgICAgICAgICAgZXhwZWN0KGNvbnRleHQucHJveHlVcmwpLnRvRXF1YWwocHJveHlVcmwuc2xpY2UoMCwgLTEpKTtcbiAgICAgICAgICAgIGV4cGVjdChjb250ZXh0LnVzZUluY29nbml0b1BhZ2VzKS50b0JlVHJ1dGh5KCk7XG4gICAgICAgICAgICBleHBlY3QoY29udGV4dC51c2VyRGF0YURpcikudG9FcXVhbCgndGVzdCcpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0KCdzaG91bGQgY3JlYXRlIGJyb3dzZXIgY29udHJvbGxlcicsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250cm9sbGVyID0gcGx1Z2luLmNyZWF0ZUNvbnRyb2xsZXIoKTtcbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyQ29udHJvbGxlcikudG9CZUluc3RhbmNlT2YoQ29udHJvbGxlcik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCB3b3JrIHdpdGggY29va2llcycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250cm9sbGVyID0gcGx1Z2luLmNyZWF0ZUNvbnRyb2xsZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBwbHVnaW4uY3JlYXRlTGF1bmNoQ29udGV4dCgpO1xuXG4gICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChjb250ZXh0IGFzIG5ldmVyKTtcblxuICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIuYXNzaWduQnJvd3Nlcihicm93c2VyIGFzIG5ldmVyLCBjb250ZXh0IGFzIG5ldmVyKTtcbiAgICAgICAgICAgIGJyb3dzZXJDb250cm9sbGVyLmFjdGl2YXRlKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyQ29udHJvbGxlci5uZXdQYWdlKCk7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyQ29udHJvbGxlci5zZXRDb29raWVzKHBhZ2UgYXMgbmV2ZXIsIFt7IG5hbWU6ICdURVNUJywgdmFsdWU6ICdURVNURVItQ09PS0lFJywgdXJsOiBzZXJ2ZXJBZGRyZXNzIH1dKTtcbiAgICAgICAgICAgIGF3YWl0IHBhZ2UuZ290byhzZXJ2ZXJBZGRyZXNzLCB7IHdhaXRVbnRpbDogJ2RvbWNvbnRlbnRsb2FkZWQnIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBjb29raWVzID0gYXdhaXQgYnJvd3NlckNvbnRyb2xsZXIuZ2V0Q29va2llcyhwYWdlIGFzIG5ldmVyKTtcbiAgICAgICAgICAgIGV4cGVjdChjb29raWVzWzBdLm5hbWUpLnRvQmUoJ1RFU1QnKTtcbiAgICAgICAgICAgIGV4cGVjdChjb29raWVzWzBdLnZhbHVlKS50b0JlKCdURVNURVItQ09PS0lFJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ25ld1BhZ2Ugb3B0aW9ucyBjYW5ub3QgYmUgdXNlZCB3aXRoIHBlcnNpc3RlbnQgY29udGV4dCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250cm9sbGVyID0gcGx1Z2luLmNyZWF0ZUNvbnRyb2xsZXIoKTtcblxuICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHtcbiAgICAgICAgICAgICAgICB1c2VJbmNvZ25pdG9QYWdlczogZmFsc2UsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgYnJvd3NlciA9IGF3YWl0IHBsdWdpbi5sYXVuY2goY29udGV4dCBhcyBuZXZlcik7XG4gICAgICAgICAgICBicm93c2VyQ29udHJvbGxlci5hc3NpZ25Ccm93c2VyKGJyb3dzZXIgYXMgbmV2ZXIsIGNvbnRleHQgYXMgbmV2ZXIpO1xuICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIuYWN0aXZhdGUoKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlckNvbnRyb2xsZXIubmV3UGFnZSh7fSk7XG4gICAgICAgICAgICAgICAgYXdhaXQgcGFnZS5jbG9zZSgpO1xuXG4gICAgICAgICAgICAgICAgZXhwZWN0KGZhbHNlKS50b0JlKHRydWUpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgICAgICAgICAgIGV4cGVjdChlcnJvci5tZXNzYWdlKS50b0JlKCdBIG5ldyBwYWdlIGNhbiBiZSBjcmVhdGVkIHdpdGggcHJvdmlkZWQgY29udGV4dCBvbmx5IHdoZW4gdXNpbmcgaW5jb2duaXRvIHBhZ2VzIG9yIGV4cGVyaW1lbnRhbCBjb250YWluZXJzLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbmRlc2NyaWJlKCdQbHVnaW5zJywgKCkgPT4ge1xuICAgIGxldCB0YXJnZXQ6IGh0dHAuU2VydmVyO1xuICAgIGxldCB1bnByb3RlY3RlZFByb3h5OiBQcm94eUNoYWluU2VydmVyO1xuICAgIGxldCBwcm90ZWN0ZWRQcm94eTogUHJveHlDaGFpblNlcnZlcjtcblxuICAgIGJlZm9yZUFsbChhc3luYyAoKSA9PiB7XG4gICAgICAgIHRhcmdldCA9IGh0dHAuY3JlYXRlU2VydmVyKChyZXF1ZXN0LCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgcmVzcG9uc2UuZW5kKHJlcXVlc3Quc29ja2V0LnJlbW90ZUFkZHJlc3MpO1xuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgcHJvbWlzaWZ5KHRhcmdldC5saXN0ZW4uYmluZCh0YXJnZXQpIGFzIGFueSkoMCwgJzEyNy4wLjAuMScpO1xuXG4gICAgICAgIHVucHJvdGVjdGVkUHJveHkgPSBjcmVhdGVQcm94eVNlcnZlcignMTI3LjAuMC4yJywgJycsICcnKTtcbiAgICAgICAgYXdhaXQgdW5wcm90ZWN0ZWRQcm94eS5saXN0ZW4oKTtcblxuICAgICAgICBwcm90ZWN0ZWRQcm94eSA9IGNyZWF0ZVByb3h5U2VydmVyKCcxMjcuMC4wLjMnLCAnZm9vJywgJ2JhcicpO1xuICAgICAgICBhd2FpdCBwcm90ZWN0ZWRQcm94eS5saXN0ZW4oKTtcbiAgICB9KTtcblxuICAgIGFmdGVyQWxsKGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgcHJvbWlzaWZ5KHRhcmdldC5jbG9zZS5iaW5kKHRhcmdldCkpKCk7XG5cbiAgICAgICAgYXdhaXQgdW5wcm90ZWN0ZWRQcm94eS5jbG9zZShmYWxzZSk7XG4gICAgICAgIGF3YWl0IHByb3RlY3RlZFByb3h5LmNsb3NlKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdQdXBwZXRlZXIgc3BlY2lmaWNzJywgKCkgPT4ge1xuICAgICAgICBsZXQgYnJvd3NlcjogQnJvd3NlcjtcblxuICAgICAgICBhZnRlckVhY2goYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYnJvd3Nlci5jbG9zZSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0KCdzaG91bGQgd29yayB3aXRoIG5vbiBhdXRoZW50aWNhdGVkIHByb3h5VXJsJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcHJveHlVcmwgPSBgaHR0cDovLzEyNy4wLjAuMjoke3VucHJvdGVjdGVkUHJveHkucG9ydH1gO1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gbmV3IFB1cHBldGVlclBsdWdpbihwdXBwZXRlZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoe1xuICAgICAgICAgICAgICAgIHByb3h5VXJsLFxuICAgICAgICAgICAgICAgIGxhdW5jaE9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjbHVkZSBsb29wYmFjayBpbnRlcmZhY2UgZnJvbSBwcm94eSBieXBhc3MgbGlzdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIHRoZSByZXF1ZXN0IHRvIGxvY2FsaG9zdCBnb2VzIHRocm91Z2ggcHJveHkuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdheSB0aGVyZSdzIG5vIG5lZWQgZm9yIGEgM3JkIHBhcnR5IHNlcnZlci5cbiAgICAgICAgICAgICAgICAgICAgICAgICctLXByb3h5LWJ5cGFzcy1saXN0PTwtbG9vcGJhY2s+JyxcbiAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGNvbnRleHQpO1xuXG4gICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3Nlci5uZXdQYWdlKCk7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBhZ2UuZ290byhgaHR0cDovLzEyNy4wLjAuMTokeyh0YXJnZXQuYWRkcmVzcygpIGFzIEFkZHJlc3NJbmZvKS5wb3J0fWApO1xuXG4gICAgICAgICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuXG4gICAgICAgICAgICBleHBlY3QodGV4dCkudG9CZSgnMTI3LjAuMC4yJyk7XG5cbiAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGVzdCgnc2hvdWxkIHdvcmsgd2l0aCBhdXRoZW50aWNhdGVkIHByb3h5VXJsJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcHJveHlVcmwgPSBgaHR0cDovL2ZvbzpiYXJAMTI3LjAuMC4zOiR7cHJvdGVjdGVkUHJveHkucG9ydH1gO1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gbmV3IFB1cHBldGVlclBsdWdpbihwdXBwZXRlZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoe1xuICAgICAgICAgICAgICAgIHByb3h5VXJsLFxuICAgICAgICAgICAgICAgIGxhdW5jaE9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjbHVkZSBsb29wYmFjayBpbnRlcmZhY2UgZnJvbSBwcm94eSBieXBhc3MgbGlzdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIHRoZSByZXF1ZXN0IHRvIGxvY2FsaG9zdCBnb2VzIHRocm91Z2ggcHJveHkuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdheSB0aGVyZSdzIG5vIG5lZWQgZm9yIGEgM3JkIHBhcnR5IHNlcnZlci5cbiAgICAgICAgICAgICAgICAgICAgICAgICctLXByb3h5LWJ5cGFzcy1saXN0PTwtbG9vcGJhY2s+JyxcbiAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGNvbnRleHQpO1xuXG4gICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3Nlci5uZXdQYWdlKCk7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBhZ2UuZ290byhgaHR0cDovLzEyNy4wLjAuMTokeyh0YXJnZXQuYWRkcmVzcygpIGFzIEFkZHJlc3NJbmZvKS5wb3J0fWApO1xuXG4gICAgICAgICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuXG4gICAgICAgICAgICBleHBlY3QodGV4dCkudG9CZSgnMTI3LjAuMC4zJyk7XG5cbiAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcblxuICAgICAgICAgICAgYXdhaXQgYnJvd3Nlci5jbG9zZSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0KCdzaG91bGQgdXNlIHBlcnNpc3RlbnQgY29udGV4dCBieSBkZWZhdWx0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gbmV3IFB1cHBldGVlclBsdWdpbihwdXBwZXRlZXIpO1xuICAgICAgICAgICAgY29uc3QgYnJvd3NlckNvbnRyb2xsZXIgPSBwbHVnaW4uY3JlYXRlQ29udHJvbGxlcigpO1xuXG4gICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoKTtcblxuICAgICAgICAgICAgYnJvd3NlciA9IGF3YWl0IHBsdWdpbi5sYXVuY2gobGF1bmNoQ29udGV4dCk7XG4gICAgICAgICAgICBicm93c2VyQ29udHJvbGxlci5hc3NpZ25Ccm93c2VyKGJyb3dzZXIsIGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIuYWN0aXZhdGUoKTtcblxuICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJDb250cm9sbGVyLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250ZXh0ID0gcGFnZS5icm93c2VyQ29udGV4dCgpO1xuXG4gICAgICAgICAgICBleHBlY3QoYnJvd3NlckNvbnRleHQuaXNJbmNvZ25pdG8oKSkudG9CZUZhbHN5KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCB1c2UgaW5jb2duaXRvIHBhZ2VzIGJ5IG9wdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQdXBwZXRlZXJQbHVnaW4ocHVwcGV0ZWVyKTtcbiAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250cm9sbGVyID0gcGx1Z2luLmNyZWF0ZUNvbnRyb2xsZXIoKTtcblxuICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHsgdXNlSW5jb2duaXRvUGFnZXM6IHRydWUgfSk7XG5cbiAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIuYXNzaWduQnJvd3Nlcihicm93c2VyLCBsYXVuY2hDb250ZXh0KTtcbiAgICAgICAgICAgIGJyb3dzZXJDb250cm9sbGVyLmFjdGl2YXRlKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyQ29udHJvbGxlci5uZXdQYWdlKCk7XG4gICAgICAgICAgICBjb25zdCBicm93c2VyQ29udGV4dCA9IHBhZ2UuYnJvd3NlckNvbnRleHQoKTtcblxuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJDb250ZXh0LmlzSW5jb2duaXRvKCkpLnRvQmVUcnV0aHkoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGVzdCgnc2hvdWxkIHBhc3MgbGF1bmNoIG9wdGlvbnMgdG8gYnJvd3NlcicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQdXBwZXRlZXJQbHVnaW4ocHVwcGV0ZWVyKTtcblxuICAgICAgICAgICAgY29uc3QgdXNlckFnZW50ID0gJ0hlbGxvV29ybGQnO1xuXG4gICAgICAgICAgICBjb25zdCBsYXVuY2hPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgICAgICAgICAgYC0tdXNlci1hZ2VudD0ke3VzZXJBZ2VudH1gLFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoeyBsYXVuY2hPcHRpb25zIH0pO1xuICAgICAgICAgICAgYnJvd3NlciA9IGF3YWl0IHBsdWdpbi5sYXVuY2gobGF1bmNoQ29udGV4dCk7XG5cbiAgICAgICAgICAgIGV4cGVjdChhd2FpdCBicm93c2VyLnVzZXJBZ2VudCgpKS50b0JlKHVzZXJBZ2VudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Byb3h5VXNlcm5hbWUgYW5kIHByb3h5UGFzc3dvcmQgYXMgbmV3UGFnZSBvcHRpb25zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gbmV3IFB1cHBldGVlclBsdWdpbihwdXBwZXRlZXIpO1xuICAgICAgICAgICAgY29uc3QgYnJvd3NlckNvbnRyb2xsZXIgPSBuZXcgUHVwcGV0ZWVyQ29udHJvbGxlcihwbHVnaW4pO1xuXG4gICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoe1xuICAgICAgICAgICAgICAgIHVzZUluY29nbml0b1BhZ2VzOiB0cnVlLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIuYXNzaWduQnJvd3Nlcihicm93c2VyLCBsYXVuY2hDb250ZXh0KTtcbiAgICAgICAgICAgIGJyb3dzZXJDb250cm9sbGVyLmFjdGl2YXRlKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyQ29udHJvbGxlci5uZXdQYWdlKHtcbiAgICAgICAgICAgICAgICBwcm94eVNlcnZlcjogYGh0dHA6Ly8xMjcuMC4wLjM6JHtwcm90ZWN0ZWRQcm94eS5wb3J0fWAsXG4gICAgICAgICAgICAgICAgcHJveHlVc2VybmFtZTogJ2ZvbycsXG4gICAgICAgICAgICAgICAgcHJveHlQYXNzd29yZDogJ2JhcicsXG4gICAgICAgICAgICAgICAgcHJveHlCeXBhc3NMaXN0OiBbJzwtbG9vcGJhY2s+J10sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBwYWdlLmdvdG8oYGh0dHA6Ly8xMjcuMC4wLjE6JHsodGFyZ2V0LmFkZHJlc3MoKSBhcyBBZGRyZXNzSW5mbykucG9ydH1gKTtcbiAgICAgICAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXNwb25zZSEudGV4dCgpO1xuXG4gICAgICAgICAgICAvLyBGQUlMSU5HLiBJdCBzaG91bGQgZ2l2ZSAxMjcuMC4wLjMgZm9yIGFsbCBwbGF0Zm9ybXMuXG4gICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3B1cHBldGVlci9wdXBwZXRlZXIvaXNzdWVzLzc2OThcbiAgICAgICAgICAgIGV4cGVjdCh0ZXh0KS50b0JlKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicgPyAnMTI3LjAuMC4xJyA6ICcxMjcuMC4wLjMnKTtcblxuICAgICAgICAgICAgYXdhaXQgcGFnZS5jbG9zZSgpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJ1blBsdWdpblRlc3QoUHVwcGV0ZWVyUGx1Z2luLCBQdXBwZXRlZXJDb250cm9sbGVyLCBwdXBwZXRlZXIpO1xuXG4gICAgZGVzY3JpYmUoJ1BsYXl3cmlnaHQgc3BlY2lmaWNzJywgKCkgPT4ge1xuICAgICAgICBsZXQgYnJvd3NlcjogcGxheXdyaWdodC5Ccm93c2VyO1xuXG4gICAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyLmNsb3NlKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlc2NyaWJlLmVhY2goWydjaHJvbWl1bScsICdmaXJlZm94JywgJ3dlYmtpdCddIGFzIGNvbnN0KSgnd2l0aCAlcycsIChicm93c2VyTmFtZSkgPT4ge1xuICAgICAgICAgICAgdGVzdCgnc2hvdWxkIHdvcmsgd2l0aCBub24gYXV0aGVudGljYXRlZCBwcm94eVVybCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwcm94eVVybCA9IGBodHRwOi8vMTI3LjAuMC4yOiR7dW5wcm90ZWN0ZWRQcm94eS5wb3J0fWA7XG4gICAgICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gbmV3IFBsYXl3cmlnaHRQbHVnaW4ocGxheXdyaWdodFticm93c2VyTmFtZV0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoT3B0aW9ucyA9IGJyb3dzZXJOYW1lID09PSAnY2hyb21pdW0nID8ge1xuICAgICAgICAgICAgICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNsdWRlIGxvb3BiYWNrIGludGVyZmFjZSBmcm9tIHByb3h5IGJ5cGFzcyBsaXN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gdGhlIHJlcXVlc3QgdG8gbG9jYWxob3N0IGdvZXMgdGhyb3VnaCBwcm94eS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgd2F5IHRoZXJlJ3Mgbm8gbmVlZCBmb3IgYSAzcmQgcGFydHkgc2VydmVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgJy0tcHJveHktYnlwYXNzLWxpc3Q9PC1sb29wYmFjaz4nLFxuICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIH0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoe1xuICAgICAgICAgICAgICAgICAgICBwcm94eVVybCxcbiAgICAgICAgICAgICAgICAgICAgbGF1bmNoT3B0aW9ucyxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGNvbnRleHQpO1xuICAgICAgICAgICAgICAgIGV4cGVjdChjb250ZXh0LmxhdW5jaE9wdGlvbnMhLnByb3h5IS5zZXJ2ZXIpLnRvRXF1YWwocHJveHlVcmwpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXIubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcGFnZS5nb3RvKGBodHRwOi8vMTI3LjAuMC4xOiR7KHRhcmdldC5hZGRyZXNzKCkgYXMgQWRkcmVzc0luZm8pLnBvcnR9YCk7XG4gICAgICAgICAgICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlc3BvbnNlIS50ZXh0KCk7XG5cbiAgICAgICAgICAgICAgICBleHBlY3QodGV4dCkudG9CZSgnMTI3LjAuMC4yJyk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBwYWdlLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGVzdCgnc2hvdWxkIHdvcmsgd2l0aCBhdXRoZW50aWNhdGVkIHByb3h5VXJsJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHByb3h5VXJsID0gYGh0dHA6Ly9mb286YmFyQDEyNy4wLjAuMzoke3Byb3RlY3RlZFByb3h5LnBvcnR9YDtcbiAgICAgICAgICAgICAgICBjb25zdCBwbHVnaW4gPSBuZXcgUGxheXdyaWdodFBsdWdpbihwbGF5d3JpZ2h0W2Jyb3dzZXJOYW1lXSk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBsYXVuY2hPcHRpb25zID0gYnJvd3Nlck5hbWUgPT09ICdjaHJvbWl1bScgPyB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2x1ZGUgbG9vcGJhY2sgaW50ZXJmYWNlIGZyb20gcHJveHkgYnlwYXNzIGxpc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzbyB0aGUgcmVxdWVzdCB0byBsb2NhbGhvc3QgZ29lcyB0aHJvdWdoIHByb3h5LlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyB3YXkgdGhlcmUncyBubyBuZWVkIGZvciBhIDNyZCBwYXJ0eSBzZXJ2ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICAnLS1wcm94eS1ieXBhc3MtbGlzdD08LWxvb3BiYWNrPicsXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBwbHVnaW4uY3JlYXRlTGF1bmNoQ29udGV4dCh7XG4gICAgICAgICAgICAgICAgICAgIHByb3h5VXJsLFxuICAgICAgICAgICAgICAgICAgICBsYXVuY2hPcHRpb25zLFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgYnJvd3NlciA9IGF3YWl0IHBsdWdpbi5sYXVuY2goY29udGV4dCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3Nlci5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBwYWdlLmdvdG8oYGh0dHA6Ly8xMjcuMC4wLjE6JHsodGFyZ2V0LmFkZHJlc3MoKSBhcyBBZGRyZXNzSW5mbykucG9ydH1gKTtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UhLnRleHQoKTtcblxuICAgICAgICAgICAgICAgIGV4cGVjdCh0ZXh0KS50b0JlKCcxMjcuMC4wLjMnKTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0ZXN0KCdwcm94eSBhcyBuZXdQYWdlIG9wdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwbHVnaW4gPSBuZXcgUGxheXdyaWdodFBsdWdpbihwbGF5d3JpZ2h0LmNocm9taXVtKTtcbiAgICAgICAgICAgICAgICBjb25zdCBicm93c2VyQ29udHJvbGxlciA9IG5ldyBQbGF5d3JpZ2h0Q29udHJvbGxlcihwbHVnaW4pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgdXNlSW5jb2duaXRvUGFnZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChsYXVuY2hDb250ZXh0KTtcbiAgICAgICAgICAgICAgICBicm93c2VyQ29udHJvbGxlci5hc3NpZ25Ccm93c2VyKGJyb3dzZXIsIGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgICAgIGJyb3dzZXJDb250cm9sbGVyLmFjdGl2YXRlKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlckNvbnRyb2xsZXIubmV3UGFnZSh7XG4gICAgICAgICAgICAgICAgICAgIHByb3h5OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXI6IGBodHRwOi8vMTI3LjAuMC4zOiR7cHJvdGVjdGVkUHJveHkucG9ydH1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXNlcm5hbWU6ICdmb28nLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFzc3dvcmQ6ICdiYXInLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnlwYXNzOiAnPC1sb29wYmFjaz4nLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBwYWdlLmdvdG8oYGh0dHA6Ly8xMjcuMC4wLjE6JHsodGFyZ2V0LmFkZHJlc3MoKSBhcyBBZGRyZXNzSW5mbykucG9ydH1gKTtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UhLnRleHQoKTtcblxuICAgICAgICAgICAgICAgIGV4cGVjdCh0ZXh0KS50b0JlKCcxMjcuMC4wLjMnKTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0ZXN0KCdzaG91bGQgdXNlIGluY29nbml0byBjb250ZXh0IGJ5IG9wdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwbHVnaW4gPSBuZXcgUGxheXdyaWdodFBsdWdpbihwbGF5d3JpZ2h0W2Jyb3dzZXJOYW1lXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgYnJvd3NlckNvbnRyb2xsZXIgPSBwbHVnaW4uY3JlYXRlQ29udHJvbGxlcigpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHsgdXNlSW5jb2duaXRvUGFnZXM6IHRydWUgfSk7XG5cbiAgICAgICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChsYXVuY2hDb250ZXh0KTtcbiAgICAgICAgICAgICAgICBicm93c2VyQ29udHJvbGxlci5hc3NpZ25Ccm93c2VyKGJyb3dzZXIsIGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgICAgIGJyb3dzZXJDb250cm9sbGVyLmFjdGl2YXRlKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlckNvbnRyb2xsZXIubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250ZXh0ID0gcGFnZS5jb250ZXh0KCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgYnJvd3NlckNvbnRyb2xsZXIubmV3UGFnZSgpO1xuXG4gICAgICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJDb250ZXh0LnBhZ2VzKCkpLnRvSGF2ZUxlbmd0aCgxKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0ZXN0KCdzaG91bGQgdXNlIHBlcnNpc3RlbnQgY29udGV4dCBieSBkZWZhdWx0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQbGF5d3JpZ2h0UGx1Z2luKHBsYXl3cmlnaHRbYnJvd3Nlck5hbWVdKTtcbiAgICAgICAgICAgICAgICBjb25zdCBicm93c2VyQ29udHJvbGxlciA9IHBsdWdpbi5jcmVhdGVDb250cm9sbGVyKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoKTtcblxuICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgICAgIGJyb3dzZXJDb250cm9sbGVyLmFzc2lnbkJyb3dzZXIoYnJvd3NlciwgbGF1bmNoQ29udGV4dCk7XG4gICAgICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIuYWN0aXZhdGUoKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyQ29udHJvbGxlci5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IHBhZ2UuY29udGV4dCgpO1xuICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJDb250cm9sbGVyLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgICAgIGV4cGVjdChjb250ZXh0LnBhZ2VzKCkpLnRvSGF2ZUxlbmd0aCgzKTsgLy8gMyBwYWdlcyBiZWNhdXNlIG9mIHRoZSBhYm91dDpibGFuay5cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0ZXN0KCdzaG91bGQgcGFzcyBsYXVuY2ggb3B0aW9ucyB0byBicm93c2VyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQbGF5d3JpZ2h0UGx1Z2luKHBsYXl3cmlnaHRbYnJvd3Nlck5hbWVdKTtcblxuICAgICAgICAgICAgICAgIGxldCByYW4gPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGxhdW5jaE9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNFbmFibGVkOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgbG9nOiAoKSA9PiB7fSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHsgbGF1bmNoT3B0aW9ucyB9KTtcbiAgICAgICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChsYXVuY2hDb250ZXh0KTtcblxuICAgICAgICAgICAgICAgIGV4cGVjdChyYW4pLnRvQmUodHJ1ZSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZGVzY3JpYmUoJ1BsYXl3cmlnaHRCcm93c2VyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCBjcmVhdGUgbmV3IHBhZ2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQbGF5d3JpZ2h0UGx1Z2luKHBsYXl3cmlnaHRbYnJvd3Nlck5hbWVdKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlciA9IGF3YWl0IHBsdWdpbi5sYXVuY2gobGF1bmNoQ29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QodHlwZW9mIHBhZ2UuY2xvc2UpLnRvQmUoJ2Z1bmN0aW9uJyk7XG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdCh0eXBlb2YgcGFnZS5ldmFsdWF0ZSkudG9CZSgnZnVuY3Rpb24nKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCBlbWl0IGRpc2Nvbm5lY3RlZCBldmVudCBvbiBjbG9zZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGx1Z2luID0gbmV3IFBsYXl3cmlnaHRQbHVnaW4ocGxheXdyaWdodFticm93c2VyTmFtZV0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxhdW5jaENvbnRleHQgPSBwbHVnaW4uY3JlYXRlTGF1bmNoQ29udGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChsYXVuY2hDb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNhbGxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXIub24oJ2Rpc2Nvbm5lY3RlZCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXIuY2xvc2UoKTtcblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QoY2FsbGVkKS50b0JlKHRydWUpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGJlIHVzZWQgb25seSB3aXRoIGluY29nbml0byBwYWdlcyBjb250ZXh0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwbHVnaW4gPSBuZXcgUGxheXdyaWdodFBsdWdpbihwbGF5d3JpZ2h0W2Jyb3dzZXJOYW1lXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHsgdXNlSW5jb2duaXRvUGFnZXM6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChsYXVuY2hDb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXIpLnRvQmVJbnN0YW5jZU9mKFBsYXl3cmlnaHRCcm93c2VyKTtcblxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyLmNsb3NlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dDIgPSBwbHVnaW4uY3JlYXRlTGF1bmNoQ29udGV4dCh7IHVzZUluY29nbml0b1BhZ2VzOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyID0gYXdhaXQgcGx1Z2luLmxhdW5jaChsYXVuY2hDb250ZXh0Mik7XG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdChicm93c2VyKS5ub3QudG9CZUluc3RhbmNlT2YoUGxheXdyaWdodEJyb3dzZXIpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIHJldHVybiBjb3JyZWN0IHZlcnNpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQbGF5d3JpZ2h0UGx1Z2luKHBsYXl3cmlnaHRbYnJvd3Nlck5hbWVdKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoeyB1c2VJbmNvZ25pdG9QYWdlczogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2ZXJzaW9uMSA9IGJyb3dzZXIudmVyc2lvbigpO1xuXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXIuY2xvc2UoKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0MiA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KHsgdXNlSW5jb2duaXRvUGFnZXM6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQyKTtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KHZlcnNpb24xKS50b0VxdWFsKGJyb3dzZXIudmVyc2lvbigpKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCByZXR1cm4gYWxsIGNvbnRleHRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwbHVnaW4gPSBuZXcgUGxheXdyaWdodFBsdWdpbihwbGF5d3JpZ2h0W2Jyb3dzZXJOYW1lXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0cyA9IGJyb3dzZXIuY29udGV4dHMoKTtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGNvbnRleHRzKS50b0hhdmVMZW5ndGgoMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2FzdCB0byBhbnkgdG8gYWNjZXNzIHByaXZhdGUgcHJvcGVydHlcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGNvbnRleHRzWzBdKS50b0VxdWFsKChicm93c2VyIGFzIGFueSkuX2Jyb3dzZXJDb250ZXh0KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCByZXR1cm4gY29ycmVjdCBjb25uZWN0ZWQgc3RhdHVzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwbHVnaW4gPSBuZXcgUGxheXdyaWdodFBsdWdpbihwbGF5d3JpZ2h0W2Jyb3dzZXJOYW1lXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3Nlci5pc0Nvbm5lY3RlZCgpKS50b0JlKHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXIuY2xvc2UoKTtcblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3Nlci5pc0Nvbm5lY3RlZCgpKS50b0JlKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCB0aHJvdyBvbiBuZXdDb250ZXh0IGNhbGwnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQbGF5d3JpZ2h0UGx1Z2luKHBsYXl3cmlnaHRbYnJvd3Nlck5hbWVdKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF1bmNoQ29udGV4dCA9IHBsdWdpbi5jcmVhdGVMYXVuY2hDb250ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXIgPSBhd2FpdCBwbHVnaW4ubGF1bmNoKGxhdW5jaENvbnRleHQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV4cGVjdChicm93c2VyLm5ld0NvbnRleHQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5yZWplY3RzXG4gICAgICAgICAgICAgICAgICAgICAgICAudG9UaHJvdygnRnVuY3Rpb24gYG5ld0NvbnRleHQoKWAgaXMgbm90IGF2YWlsYWJsZSBpbiBpbmNvZ25pdG8gbW9kZScpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGhhdmUgc2FtZSBwdWJsaWMgaW50ZXJmYWNlIGFzIHBsYXl3cmlnaHQgYnJvd3NlclR5cGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IG5ldyBQbGF5d3JpZ2h0UGx1Z2luKHBsYXl3cmlnaHRbYnJvd3Nlck5hbWVdKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxGdW5jdGlvbk5hbWVzID0gWydjbG9zZScsICdjb250ZXh0cycsICdpc0Nvbm5lY3RlZCcsICduZXdDb250ZXh0JywgJ25ld1BhZ2UnLCAndmVyc2lvbiddIGFzIGNvbnN0O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXVuY2hDb250ZXh0ID0gcGx1Z2luLmNyZWF0ZUxhdW5jaENvbnRleHQoeyB1c2VJbmNvZ25pdG9QYWdlczogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlciA9IGF3YWl0IHBsdWdpbi5sYXVuY2gobGF1bmNoQ29udGV4dCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvcmlnaW5hbEZ1bmN0aW9uTmFtZSBvZiBvcmlnaW5hbEZ1bmN0aW9uTmFtZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdCh0eXBlb2YgYnJvd3NlcltvcmlnaW5hbEZ1bmN0aW9uTmFtZV0pLnRvQmUoJ2Z1bmN0aW9uJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QuaGFzQXNzZXJ0aW9ucygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgcnVuUGx1Z2luVGVzdChQbGF5d3JpZ2h0UGx1Z2luLCBQbGF5d3JpZ2h0Q29udHJvbGxlciwgcGxheXdyaWdodC5jaHJvbWl1bSk7XG4gICAgcnVuUGx1Z2luVGVzdChQbGF5d3JpZ2h0UGx1Z2luLCBQbGF5d3JpZ2h0Q29udHJvbGxlciwgcGxheXdyaWdodC5maXJlZm94KTtcbiAgICBydW5QbHVnaW5UZXN0KFBsYXl3cmlnaHRQbHVnaW4sIFBsYXl3cmlnaHRDb250cm9sbGVyLCBwbGF5d3JpZ2h0LndlYmtpdCk7XG59KTtcbiJdLCJmaWxlIjoiL1VzZXJzL3ZsYWQvRGV2ZWxvcG1lbnQvQXBpZnkvY3Jhd2xlZS90ZXN0L2Jyb3dzZXItcG9vbC9icm93c2VyLXBsdWdpbnMvcGx1Z2lucy50ZXN0LnRzIn0=
// /Users/vlad/Development/Apify/crawlee/test/browser-pool/browser-pool.test.ts
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var import_http = __toESM(require("http"));
var import_util = require("util");
var import_timeout = require("@apify/timeout");
var import_playwright = __toESM(require("playwright"));
var import_puppeteer = __toESM(require("puppeteer"));
var import_create_proxy_server = require("./browser-plugins/create-proxy-server");
var import_browser_pool = require("../../packages/browser-pool/src/browser-pool");
var import_events = require("../../packages/browser-pool/src/events");
var import_types = require("../../packages/browser-pool/src/fingerprinting/types");
var import_playwright_plugin = require("../../packages/browser-pool/src/playwright/playwright-plugin");
var import_puppeteer_plugin = require("../../packages/browser-pool/src/puppeteer/puppeteer-plugin");
const fingerprintingMatrix = [
[
"Playwright - persistent",
new import_playwright_plugin.PlaywrightPlugin(
import_playwright.default.chromium,
{
useIncognitoPages: false
}
)
],
[
"Playwright - Incognito",
new import_playwright_plugin.PlaywrightPlugin(
import_playwright.default.chromium,
{
useIncognitoPages: true
}
)
],
[
"Puppeteer - Persistent",
new import_puppeteer_plugin.PuppeteerPlugin(
import_puppeteer.default,
{
useIncognitoPages: false
}
)
],
[
"Puppeteer - Incognito",
new import_puppeteer_plugin.PuppeteerPlugin(
import_puppeteer.default,
{
useIncognitoPages: true
}
)
]
];
describe.each([
["Puppeteer", new import_puppeteer_plugin.PuppeteerPlugin(import_puppeteer.default)],
["Playwright", new import_playwright_plugin.PlaywrightPlugin(import_playwright.default.chromium)]
// Chromium is faster than firefox and webkit
])("BrowserPool - %s", (_, plugin) => {
let browserPool;
beforeEach(async () => {
vitest.clearAllMocks();
browserPool = new import_browser_pool.BrowserPool({
browserPlugins: [plugin],
closeInactiveBrowserAfterSecs: 2
});
});
afterEach(async () => {
await browserPool?.destroy();
});
let target;
let unprotectedProxy;
let protectedProxy;
beforeAll(async () => {
target = import_http.default.createServer((request, response) => {
response.end(request.socket.remoteAddress);
});
await (0, import_util.promisify)(target.listen.bind(target))(0, "127.0.0.1");
unprotectedProxy = (0, import_create_proxy_server.createProxyServer)("127.0.0.2", "", "");
await unprotectedProxy.listen();
protectedProxy = (0, import_create_proxy_server.createProxyServer)("127.0.0.3", "foo", "bar");
await protectedProxy.listen();
});
afterAll(async () => {
await (0, import_util.promisify)(target.close.bind(target))();
await unprotectedProxy.close(false);
await protectedProxy.close(false);
});
describe("Initialization & retirement", () => {
test("should retire browsers", async () => {
await browserPool.newPage();
browserPool.retireAllBrowsers();
expect(browserPool.activeBrowserControllers.size).toBe(0);
expect(browserPool.retiredBrowserControllers.size).toBe(1);
});
test("should destroy pool", async () => {
const page = await browserPool.newPage();
const browserController = browserPool.getBrowserControllerByPage(page);
vitest.spyOn(browserController, "close");
await browserPool.destroy();
expect(browserController.close).toHaveBeenCalled();
expect(browserPool.activeBrowserControllers.size).toBe(0);
expect(browserPool.retiredBrowserControllers.size).toBe(0);
expect(browserPool["browserKillerInterval"]).toBeUndefined();
});
});
describe("Basic user functionality", () => {
test("should open new page", async () => {
const page = await browserPool.newPage();
expect(page.goto).toBeDefined();
expect(page.close).toBeDefined();
});
test.skip("should allow early aborting in case of outer timeout", async () => {
const timeout = browserPool.operationTimeoutMillis;
browserPool.operationTimeoutMillis = 500;
const spy = vitest.spyOn(import_browser_pool.BrowserPool.prototype, "_executeHooks");
await browserPool.newPage();
expect(spy).toBeCalledTimes(4);
spy.mockReset();
await expect((0, import_timeout.addTimeoutToPromise)(
() => browserPool.newPage(),
10,
"opening new page timed out"
)).rejects.toThrowError("opening new page timed out");
expect(spy).toBeCalledTimes(1);
spy.mockRestore();
browserPool.operationTimeoutMillis = timeout;
browserPool.retireAllBrowsers();
});
test("should open new page in incognito context", async () => {
const browserPoolIncognito = new import_browser_pool.BrowserPool({
browserPlugins: [new import_playwright_plugin.PlaywrightPlugin(import_playwright.default.chromium, { useIncognitoPages: true })],
closeInactiveBrowserAfterSecs: 2
});
const page = await browserPoolIncognito.newPage();
await browserPoolIncognito.newPage();
await browserPoolIncognito.newPage();
expect(page.context().pages()).toHaveLength(1);
});
test("should open new page in new browser", async () => {
vitest.spyOn(plugin, "launch");
await browserPool.newPage();
await browserPool.newPageInNewBrowser();
await browserPool.newPageInNewBrowser();
expect(browserPool.activeBrowserControllers.size).toBe(3);
expect(plugin.launch).toHaveBeenCalledTimes(3);
});
test("should correctly override page close", async () => {
vitest.spyOn(browserPool, "_overridePageClose");
const page = await browserPool.newPage();
expect(browserPool["_overridePageClose"]).toBeCalled();
const controller = browserPool.getBrowserControllerByPage(page);
expect(controller.activePages).toEqual(1);
expect(controller.totalPages).toEqual(1);
await page.close();
expect(controller.activePages).toEqual(0);
expect(controller.totalPages).toEqual(1);
});
test("should retire browser after page count", async () => {
browserPool.retireBrowserAfterPageCount = 2;
vitest.spyOn(browserPool, "retireBrowserController");
expect(browserPool.activeBrowserControllers.size).toBe(0);
await browserPool.newPage();
await browserPool.newPage();
await browserPool.newPage();
expect(browserPool.activeBrowserControllers.size).toBe(1);
expect(browserPool.retiredBrowserControllers.size).toBe(1);
expect(browserPool.retireBrowserController).toBeCalledTimes(1);
});
test("should allow max pages per browser", async () => {
browserPool.maxOpenPagesPerBrowser = 1;
vitest.spyOn(browserPool, "_launchBrowser");
await browserPool.newPage();
expect(browserPool.activeBrowserControllers.size).toBe(1);
await browserPool.newPage();
expect(browserPool.activeBrowserControllers.size).toBe(2);
await browserPool.newPage();
expect(browserPool.activeBrowserControllers.size).toBe(3);
expect(browserPool["_launchBrowser"]).toBeCalledTimes(3);
});
test("should allow max pages per browser - no race condition", async () => {
browserPool.maxOpenPagesPerBrowser = 1;
vitest.spyOn(browserPool, "_launchBrowser");
const usePlugin = {
browserPlugin: plugin
};
await Promise.all([
browserPool.newPage(usePlugin),
browserPool.newPage(usePlugin)
]);
expect(browserPool.activeBrowserControllers.size).toBe(2);
expect(browserPool["_launchBrowser"]).toBeCalledTimes(2);
});
test("should close retired browsers", async () => {
browserPool.retireBrowserAfterPageCount = 1;
clearInterval(browserPool["browserKillerInterval"]);
browserPool["browserKillerInterval"] = setInterval(
() => browserPool["_closeInactiveRetiredBrowsers"](),
100
);
vitest.spyOn(browserPool, "_closeRetiredBrowserWithNoPages");
expect(browserPool.retiredBrowserControllers.size).toBe(0);
const page = await browserPool.newPage();
const controller = browserPool.getBrowserControllerByPage(page);
vitest.spyOn(controller, "close");
expect(browserPool.retiredBrowserControllers.size).toBe(1);
await page.close();
await new Promise((resolve) => setTimeout(() => {
resolve();
}, 1e3));
expect(browserPool["_closeRetiredBrowserWithNoPages"]).toHaveBeenCalled();
expect(controller.close).toHaveBeenCalled();
expect(browserPool.retiredBrowserControllers.size).toBe(0);
});
describe("hooks", () => {
test("should run hooks in series with custom args", async () => {
const indexArray = [];
const createAsyncHookReturningIndex = (i) => async () => {
const index = await new Promise((resolve) => setTimeout(() => resolve(i), 100));
indexArray.push(index);
};
const hooks = new Array(10);
for (let i = 0; i < hooks.length; i++) {
hooks[i] = createAsyncHookReturningIndex(i);
}
await browserPool["_executeHooks"](hooks);
expect(indexArray).toHaveLength(10);
indexArray.forEach((v, index) => expect(v).toEqual(index));
});
describe("preLaunchHooks", () => {
test("should evaluate hook before launching browser with correct args", async () => {
const myAsyncHook = () => Promise.resolve();
browserPool.preLaunchHooks.push(myAsyncHook);
vitest.spyOn(browserPool, "_executeHooks");
const page = await browserPool.newPage();
const pageId = browserPool.getPageId(page);
const { launchContext } = browserPool.getBrowserControllerByPage(page);
expect(browserPool["_executeHooks"]).toHaveBeenNthCalledWith(1, browserPool.preLaunchHooks, pageId, launchContext);
});
test("error in hook does not leave browser stuck in limbo", async () => {
const errorMessage = "pre-launch failed";
browserPool.preLaunchHooks = [
async () => {
throw new Error(errorMessage);
}
];
const attempts = 5;
for (let i = 0; i < attempts; i++) {
try {
await browserPool.newPage();
} catch (err) {
expect(err.message).toBe(errorMessage);
}
}
expect(browserPool.activeBrowserControllers.size).toBe(0);
expect.assertions(attempts + 1);
});
});
describe("postLaunchHooks", () => {
test("should evaluate hook after launching browser with correct args", async () => {
const myAsyncHook = () => Promise.resolve();
browserPool.postLaunchHooks = [myAsyncHook];
vitest.spyOn(browserPool, "_executeHooks");
const page = await browserPool.newPage();
const pageId = browserPool.getPageId(page);
const browserController = browserPool.getBrowserControllerByPage(page);
expect(browserPool["_executeHooks"]).toHaveBeenNthCalledWith(2, browserPool.postLaunchHooks, pageId, browserController);
});
test("error in hook does not leave browser stuck in limbo", async () => {
const errorMessage = "post-launch failed";
const controllers = [];
browserPool.postLaunchHooks = [
async (_pageId, browserController) => {
controllers.push(browserController);
throw new Error(errorMessage);
}
];
const attempts = 5;
for (let i = 0; i < attempts; i++) {
try {
await browserPool.newPage();
} catch (err) {
expect(err.message).toBe(errorMessage);
}
}
await new Promise((resolve) => {
const int = setInterval(() => {
const stillWaiting = controllers.some((c) => c.isActive === true);
if (!stillWaiting) {
clearInterval(int);
resolve();
}
}, 10);
});
expect(browserPool.activeBrowserControllers.size).toBe(0);
expect.assertions(attempts + 1);
});
});
describe("prePageCreateHooks", () => {
test("should evaluate hook after launching browser with correct args", async () => {
const myAsyncHook = () => Promise.resolve();
browserPool.prePageCreateHooks = [myAsyncHook];
vitest.spyOn(browserPool, "_executeHooks");
const page = await browserPool.newPage();
const pageId = browserPool.getPageId(page);
const browserController = browserPool.getBrowserControllerByPage(page);
expect(browserPool["_executeHooks"]).toHaveBeenNthCalledWith(
3,
browserPool.prePageCreateHooks,
pageId,
browserController,
browserController.launchContext.useIncognitoPages ? {} : void 0
);
});
});
describe("postPageCreateHooks", () => {
test("should evaluate hook after launching browser with correct args", async () => {
const myAsyncHook = () => Promise.resolve();
browserPool.postPageCreateHooks = [myAsyncHook];
vitest.spyOn(browserPool, "_executeHooks");
const page = await browserPool.newPage();
const browserController = browserPool.getBrowserControllerByPage(page);
expect(browserPool["_executeHooks"]).toHaveBeenNthCalledWith(4, browserPool.postPageCreateHooks, page, browserController);
});
});
describe("prePageCloseHooks", () => {
test("should evaluate hook after launching browser with correct args", async () => {
const myAsyncHook = () => Promise.resolve();
browserPool.prePageCloseHooks = [myAsyncHook];
vitest.spyOn(browserPool, "_executeHooks");
const page = await browserPool.newPage();
await page.close();
const browserController = browserPool.getBrowserControllerByPage(page);
expect(browserPool["_executeHooks"]).toHaveBeenNthCalledWith(5, browserPool.prePageCloseHooks, page, browserController);
});
});
describe("postPageCloseHooks", () => {
test("should evaluate hook after launching browser with correct args", async () => {
const myAsyncHook = () => Promise.resolve();
browserPool.postPageCloseHooks = [myAsyncHook];
vitest.spyOn(browserPool, "_executeHooks");
const page = await browserPool.newPage();
const pageId = browserPool.getPageId(page);
await page.close();
const browserController = browserPool.getBrowserControllerByPage(page);
expect(browserPool["_executeHooks"]).toHaveBeenNthCalledWith(6, browserPool.postPageCloseHooks, pageId, browserController);
});
});
describe("default browser automation masking", () => {
describe.each(fingerprintingMatrix)("%s", (_name, fingerprintPlugin) => {
let browserPoolWithDefaults;
let page;
beforeEach(async () => {
browserPoolWithDefaults = new import_browser_pool.BrowserPool({
browserPlugins: [fingerprintPlugin],
closeInactiveBrowserAfterSecs: 2
});
page = await browserPoolWithDefaults.newPage();
});
afterEach(async () => {
if (page)
await page.close();
await browserPoolWithDefaults.destroy();
});
test("should hide webdriver", async () => {
await page.goto(`file://${__dirname}/test.html`);
const webdriver = await page.evaluate(() => {
return navigator.webdriver;
});
expect(webdriver).toBeFalsy();
});
});
});
describe("fingerprinting", () => {
describe.each(fingerprintingMatrix)("%s", (_name, fingerprintPlugin) => {
let browserPoolWithFP;
let page;
beforeEach(async () => {
browserPoolWithFP = new import_browser_pool.BrowserPool({
browserPlugins: [fingerprintPlugin],
closeInactiveBrowserAfterSecs: 2,
useFingerprints: true
});
page = await browserPoolWithFP.newPage();
});
afterEach(async () => {
if (page)
await page.close();
await browserPoolWithFP.destroy();
});
test("should override fingerprint", async () => {
await page.goto(`file://${__dirname}/test.html`);
const browserController = browserPoolWithFP.getBrowserControllerByPage(page);
const data = await page.evaluate(() => {
return {
hardwareConcurrency: navigator.hardwareConcurrency,
userAgent: navigator.userAgent
};
});
const { fingerprint } = browserController.launchContext.fingerprint;
expect(data.hardwareConcurrency).toBe(fingerprint?.navigator.hardwareConcurrency);
expect(data.userAgent).toBe(fingerprint?.navigator.userAgent);
});
test("should hide webdriver", async () => {
await page.goto(`file://${__dirname}/test.html`);
const webdriver = await page.evaluate(() => {
return navigator.webdriver;
});
expect(webdriver).toBeFalsy();
});
});
describe("caching", () => {
const commonOptions = {
browserPlugins: [new import_playwright_plugin.PlaywrightPlugin(
import_playwright.default.chromium,
{
useIncognitoPages: true
}
)]
};
let browserPoolCache;
afterEach(async () => {
await browserPoolCache.destroy();
});
test("should use fingerprint cache by default", async () => {
browserPoolCache = new import_browser_pool.BrowserPool({
...commonOptions,
useFingerprints: true
});
expect(browserPoolCache.fingerprintCache).toBeDefined();
});
test("should turn off cache", async () => {
browserPoolCache = new import_browser_pool.BrowserPool({
...commonOptions,
useFingerprints: true,
fingerprintOptions: {
useFingerprintCache: false
}
});
expect(browserPoolCache.fingerprintCache).toBeUndefined();
});
test("should limit cache size", async () => {
browserPoolCache = new import_browser_pool.BrowserPool({
...commonOptions,
useFingerprints: true,
fingerprintOptions: {
fingerprintCacheSize: 1
}
});
const cache = browserPoolCache.fingerprintCache;
expect(cache.maxSize).toBe(1);
});
test("should cache fingerprints", async () => {
browserPoolCache = new import_browser_pool.BrowserPool({
...commonOptions,
useFingerprints: true,
preLaunchHooks: [
(_pageId, launchContext) => {
launchContext.extend({ session: { id: "123" } });
}
]
});
const mock = vitest.fn();
browserPoolCache.fingerprintInjector.attachFingerprintToPlaywright = mock;
const page = await browserPoolCache.newPageInNewBrowser();
expect(mock.mock.calls[0][1]).toBeDefined();
const page2 = await browserPoolCache.newPageInNewBrowser();
await page.close();
await page2.close();
expect(mock.mock.calls[0][1]).toBe(mock.mock.calls[1][1]);
});
});
});
describe("generator configuration", () => {
const commonOptions = {
browserPlugins: [new import_playwright_plugin.PlaywrightPlugin(
import_playwright.default.firefox,
{
useIncognitoPages: true
}
)]
};
let browserPoolConfig;
afterEach(async () => {
await browserPoolConfig.destroy();
});
test("should use native os and browser", async () => {
browserPoolConfig = new import_browser_pool.BrowserPool({
...commonOptions,
useFingerprints: true
});
const oldGet = browserPoolConfig.fingerprintGenerator.getFingerprint;
const mock = vitest.fn((options) => {
return oldGet.bind(browserPoolConfig.fingerprintGenerator)(options);
});
browserPoolConfig.fingerprintGenerator.getFingerprint = mock;
const page = await browserPoolConfig.newPage();
await page.close();
const defaultOptions = mock.mock.calls[0][0];
expect(defaultOptions.browsers.includes("firefox")).toBe(true);
let os;
switch (process.platform) {
case "darwin":
os = "macos";
break;
case "win32":
os = "windows";
break;
default:
os = "linux";
}
expect(defaultOptions.operatingSystems.includes(os)).toBe(true);
});
test("should allow changing options", async () => {
browserPoolConfig = new import_browser_pool.BrowserPool({
...commonOptions,
useFingerprints: true,
fingerprintOptions: {
fingerprintGeneratorOptions: {
operatingSystems: [import_types.OperatingSystemsName.windows],
browsers: [import_types.BrowserName.chrome]
}
}
});
const oldGet = browserPoolConfig.fingerprintGenerator.getFingerprint;
const mock = vitest.fn((options2) => {
return oldGet.bind(browserPoolConfig.fingerprintGenerator)(options2);
});
browserPoolConfig.fingerprintGenerator.getFingerprint = mock;
const page = await browserPoolConfig.newPageInNewBrowser();
await page.close();
const [options] = mock.mock.calls[0];
expect(options.operatingSystems.includes("windows")).toBe(true);
expect(options.browsers.includes("chrome")).toBe(true);
});
});
});
describe("events", () => {
test(`should emit ${import_events.BROWSER_POOL_EVENTS.BROWSER_LAUNCHED} event`, async () => {
browserPool.maxOpenPagesPerBrowser = 1;
let calls = 0;
let argument;
browserPool.on(import_events.BROWSER_POOL_EVENTS.BROWSER_LAUNCHED, (arg) => {
argument = arg;
calls++;
});
await browserPool.newPage();
const page = await browserPool.newPage();
expect(calls).toEqual(2);
expect(argument).toEqual(browserPool.getBrowserControllerByPage(page));
});
test(`should emit ${import_events.BROWSER_POOL_EVENTS.BROWSER_RETIRED} event`, async () => {
browserPool.retireBrowserAfterPageCount = 1;
let calls = 0;
let argument;
browserPool.on(import_events.BROWSER_POOL_EVENTS.BROWSER_RETIRED, (arg) => {
argument = arg;
calls++;
});
await browserPool.newPage();
const page = await browserPool.newPage();
expect(calls).toEqual(2);
expect(argument).toEqual(browserPool.getBrowserControllerByPage(page));
});
test(`should emit ${import_events.BROWSER_POOL_EVENTS.PAGE_CREATED} event`, async () => {
let calls = 0;
let argument;
browserPool.on(import_events.BROWSER_POOL_EVENTS.PAGE_CREATED, (arg) => {
argument = arg;
calls++;
});
const page = await browserPool.newPage();
expect(argument).toEqual(page);
const page2 = await browserPool.newPage();
expect(calls).toEqual(2);
expect(argument).toEqual(page2);
});
test(`should emit ${import_events.BROWSER_POOL_EVENTS.PAGE_CLOSED} event`, async () => {
let calls = 0;
let argument;
browserPool.on(import_events.BROWSER_POOL_EVENTS.PAGE_CLOSED, (arg) => {
argument = arg;
calls++;
});
const page = await browserPool.newPage();
await page.close();
expect(argument).toEqual(page);
const page2 = await browserPool.newPage();
await page2.close();
expect(calls).toEqual(2);
expect(argument).toEqual(page2);
});
});
});
});
//# sourceMappingSource=vite-node
//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUN4QyxlQUFPLEtBQUssRUFBRSxRQUFRLENBQUM7QUFDdkIsZUFBTyxRQUFRLEVBQUUsUUFBUSxLQUFLO0FBQUEsTUFDbEMsQ0FBQztBQUVELFdBQUssZUFBZSxrQ0FBb0IsV0FBVyxVQUFVLFlBQVk7QUFDckUsWUFBSSxRQUFRO0FBQ1osWUFBSTtBQUNKLG9CQUFZLEdBQUcsa0NBQW9CLGFBQWEsQ0FBQyxRQUFRO0FBQ3JELHFCQUFXO0FBQ1g7QUFBQSxRQUNKLENBQUM7QUFFRCxjQUFNLE9BQU8sTUFBTSxZQUFZLFFBQVE7QUFDdkMsY0FBTSxLQUFLLE1BQU07QUFDakIsZUFBTyxRQUFRLEVBQUUsUUFBUSxJQUFJO0FBQzdCLGNBQU0sUUFBUSxNQUFNLFlBQVksUUFBUTtBQUN4QyxjQUFNLE1BQU0sTUFBTTtBQUNsQixlQUFPLEtBQUssRUFBRSxRQUFRLENBQUM7QUFDdkIsZUFBTyxRQUFRLEVBQUUsUUFBUSxLQUFLO0FBQUEsTUFDbEMsQ0FBQztBQUFBLElBQ0wsQ0FBQztBQUFBLEVBQ0wsQ0FBQztBQUNMLENBQUMiLCJuYW1lcyI6WyJwbGF5d3JpZ2h0IiwicHVwcGV0ZWVyIiwiaHR0cCIsIm9wdGlvbnMiXSwic291cmNlcyI6WyJicm93c2VyLXBvb2wudGVzdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBkb3Qtbm90YXRpb24gLS0gQWNjZXNzaW5nIHByaXZhdGUgcHJvcGVydGllcyAqL1xuaW1wb3J0IGh0dHAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJztcblxuaW1wb3J0IHsgYWRkVGltZW91dFRvUHJvbWlzZSB9IGZyb20gJ0BhcGlmeS90aW1lb3V0JztcbmltcG9ydCB0eXBlIHsgQnJvd3NlckZpbmdlcnByaW50V2l0aEhlYWRlcnMgfSBmcm9tICdmaW5nZXJwcmludC1nZW5lcmF0b3InO1xuaW1wb3J0IHBsYXl3cmlnaHQgZnJvbSAncGxheXdyaWdodCc7XG5pbXBvcnQgdHlwZSB7IFNlcnZlciBhcyBQcm94eUNoYWluU2VydmVyIH0gZnJvbSAncHJveHktY2hhaW4nO1xuaW1wb3J0IHR5cGUgeyBQYWdlIH0gZnJvbSAncHVwcGV0ZWVyJztcbmltcG9ydCBwdXBwZXRlZXIgZnJvbSAncHVwcGV0ZWVyJztcblxuaW1wb3J0IHsgY3JlYXRlUHJveHlTZXJ2ZXIgfSBmcm9tICcuL2Jyb3dzZXItcGx1Z2lucy9jcmVhdGUtcHJveHktc2VydmVyJztcbmltcG9ydCB0eXBlIHsgQnJvd3NlckNvbnRyb2xsZXIgfSBmcm9tICcuLi8uLi9wYWNrYWdlcy9icm93c2VyLXBvb2wvc3JjL2Fic3RyYWN0LWNsYXNzZXMvYnJvd3Nlci1jb250cm9sbGVyJztcbmltcG9ydCB7IEJyb3dzZXJQb29sIH0gZnJvbSAnLi4vLi4vcGFja2FnZXMvYnJvd3Nlci1wb29sL3NyYy9icm93c2VyLXBvb2wnO1xuaW1wb3J0IHsgQlJPV1NFUl9QT09MX0VWRU5UUyB9IGZyb20gJy4uLy4uL3BhY2thZ2VzL2Jyb3dzZXItcG9vbC9zcmMvZXZlbnRzJztcbmltcG9ydCB7IEJyb3dzZXJOYW1lLCBPcGVyYXRpbmdTeXN0ZW1zTmFtZSB9IGZyb20gJy4uLy4uL3BhY2thZ2VzL2Jyb3dzZXItcG9vbC9zcmMvZmluZ2VycHJpbnRpbmcvdHlwZXMnO1xuaW1wb3J0IHsgUGxheXdyaWdodFBsdWdpbiB9IGZyb20gJy4uLy4uL3BhY2thZ2VzL2Jyb3dzZXItcG9vbC9zcmMvcGxheXdyaWdodC9wbGF5d3JpZ2h0LXBsdWdpbic7XG5pbXBvcnQgeyBQdXBwZXRlZXJQbHVnaW4gfSBmcm9tICcuLi8uLi9wYWNrYWdlcy9icm93c2VyLXBvb2wvc3JjL3B1cHBldGVlci9wdXBwZXRlZXItcGx1Z2luJztcblxuY29uc3QgZmluZ2VycHJpbnRpbmdNYXRyaXg6IFtzdHJpbmcsIFBsYXl3cmlnaHRQbHVnaW4gfCBQdXBwZXRlZXJQbHVnaW5dW10gPSBbXG4gICAgW1xuICAgICAgICAnUGxheXdyaWdodCAtIHBlcnNpc3RlbnQnLFxuICAgICAgICBuZXcgUGxheXdyaWdodFBsdWdpbihcbiAgICAgICAgICAgIHBsYXl3cmlnaHQuY2hyb21pdW0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdXNlSW5jb2duaXRvUGFnZXM6IGZhbHNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICBdLFxuICAgIFtcbiAgICAgICAgJ1BsYXl3cmlnaHQgLSBJbmNvZ25pdG8nLFxuICAgICAgICBuZXcgUGxheXdyaWdodFBsdWdpbihcbiAgICAgICAgICAgIHBsYXl3cmlnaHQuY2hyb21pdW0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdXNlSW5jb2duaXRvUGFnZXM6IHRydWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICApLFxuICAgIF0sXG4gICAgW1xuICAgICAgICAnUHVwcGV0ZWVyIC0gUGVyc2lzdGVudCcsXG4gICAgICAgIG5ldyBQdXBwZXRlZXJQbHVnaW4oXG4gICAgICAgICAgICBwdXBwZXRlZXIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdXNlSW5jb2duaXRvUGFnZXM6IGZhbHNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICBdLFxuICAgIFtcbiAgICAgICAgJ1B1cHBldGVlciAtIEluY29nbml0bycsXG4gICAgICAgIG5ldyBQdXBwZXRlZXJQbHVnaW4oXG4gICAgICAgICAgICBwdXBwZXRlZXIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdXNlSW5jb2duaXRvUGFnZXM6IHRydWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICApLFxuICAgIF0sXG5dO1xuLy8gVGVzdHMgY291bGQgYmUgZ2VuZXJhdGVkIGZyb20gdGhpcyBibHVlcHJpbnQgZm9yIGVhY2ggcGx1Z2luXG5kZXNjcmliZS5lYWNoKFtcbiAgICBbJ1B1cHBldGVlcicsIG5ldyBQdXBwZXRlZXJQbHVnaW4ocHVwcGV0ZWVyKV0sXG4gICAgWydQbGF5d3JpZ2h0JywgbmV3IFBsYXl3cmlnaHRQbHVnaW4ocGxheXdyaWdodC5jaHJvbWl1bSldLCAvLyBDaHJvbWl1bSBpcyBmYXN0ZXIgdGhhbiBmaXJlZm94IGFuZCB3ZWJraXRcbl0pKCdCcm93c2VyUG9vbCAtICVzJywgKF8sIHBsdWdpbikgPT4ge1xuICAgIGxldCBicm93c2VyUG9vbDogQnJvd3NlclBvb2w8eyBicm93c2VyUGx1Z2luczogW3R5cGVvZiBwbHVnaW5dOyBjbG9zZUluYWN0aXZlQnJvd3NlckFmdGVyU2VjczogMiB9PjtcblxuICAgIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xuICAgICAgICB2aXRlc3QuY2xlYXJBbGxNb2NrcygpO1xuICAgICAgICBicm93c2VyUG9vbCA9IG5ldyBCcm93c2VyUG9vbCh7XG4gICAgICAgICAgICBicm93c2VyUGx1Z2luczogW3BsdWdpbl0sXG4gICAgICAgICAgICBjbG9zZUluYWN0aXZlQnJvd3NlckFmdGVyU2VjczogMixcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBicm93c2VyUG9vbD8uZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgbGV0IHRhcmdldDogaHR0cC5TZXJ2ZXI7XG4gICAgbGV0IHVucHJvdGVjdGVkUHJveHk6IFByb3h5Q2hhaW5TZXJ2ZXI7XG4gICAgbGV0IHByb3RlY3RlZFByb3h5OiBQcm94eUNoYWluU2VydmVyO1xuXG4gICAgYmVmb3JlQWxsKGFzeW5jICgpID0+IHtcbiAgICAgICAgdGFyZ2V0ID0gaHR0cC5jcmVhdGVTZXJ2ZXIoKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICByZXNwb25zZS5lbmQocmVxdWVzdC5zb2NrZXQucmVtb3RlQWRkcmVzcyk7XG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBwcm9taXNpZnkodGFyZ2V0Lmxpc3Rlbi5iaW5kKHRhcmdldCkgYXMgYW55KSgwLCAnMTI3LjAuMC4xJyk7XG5cbiAgICAgICAgdW5wcm90ZWN0ZWRQcm94eSA9IGNyZWF0ZVByb3h5U2VydmVyKCcxMjcuMC4wLjInLCAnJywgJycpO1xuICAgICAgICBhd2FpdCB1bnByb3RlY3RlZFByb3h5Lmxpc3RlbigpO1xuXG4gICAgICAgIHByb3RlY3RlZFByb3h5ID0gY3JlYXRlUHJveHlTZXJ2ZXIoJzEyNy4wLjAuMycsICdmb28nLCAnYmFyJyk7XG4gICAgICAgIGF3YWl0IHByb3RlY3RlZFByb3h5Lmxpc3RlbigpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJBbGwoYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBwcm9taXNpZnkodGFyZ2V0LmNsb3NlLmJpbmQodGFyZ2V0KSkoKTtcblxuICAgICAgICBhd2FpdCB1bnByb3RlY3RlZFByb3h5LmNsb3NlKGZhbHNlKTtcbiAgICAgICAgYXdhaXQgcHJvdGVjdGVkUHJveHkuY2xvc2UoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ0luaXRpYWxpemF0aW9uICYgcmV0aXJlbWVudCcsICgpID0+IHtcbiAgICAgICAgdGVzdCgnc2hvdWxkIHJldGlyZSBicm93c2VycycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgYnJvd3NlclBvb2wucmV0aXJlQWxsQnJvd3NlcnMoKTtcbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbC5hY3RpdmVCcm93c2VyQ29udHJvbGxlcnMuc2l6ZSkudG9CZSgwKTtcbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbC5yZXRpcmVkQnJvd3NlckNvbnRyb2xsZXJzLnNpemUpLnRvQmUoMSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCBkZXN0cm95IHBvb2wnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlclBvb2wubmV3UGFnZSgpO1xuICAgICAgICAgICAgY29uc3QgYnJvd3NlckNvbnRyb2xsZXIgPSBicm93c2VyUG9vbC5nZXRCcm93c2VyQ29udHJvbGxlckJ5UGFnZShwYWdlKSE7XG4gICAgICAgICAgICB2aXRlc3Quc3B5T24oYnJvd3NlckNvbnRyb2xsZXIsICdjbG9zZScpO1xuXG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5kZXN0cm95KCk7XG5cbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyQ29udHJvbGxlci5jbG9zZSkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLmFjdGl2ZUJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDApO1xuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLnJldGlyZWRCcm93c2VyQ29udHJvbGxlcnMuc2l6ZSkudG9CZSgwKTtcbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbFsnYnJvd3NlcktpbGxlckludGVydmFsJ10pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnQmFzaWMgdXNlciBmdW5jdGlvbmFsaXR5JywgKCkgPT4ge1xuICAgICAgICAvLyBCYXNpYyB1c2VyIGZhY2luZyBmdW5jdGlvbmFsaXR5XG4gICAgICAgIHRlc3QoJ3Nob3VsZCBvcGVuIG5ldyBwYWdlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgZXhwZWN0KHBhZ2UuZ290bykudG9CZURlZmluZWQoKTtcbiAgICAgICAgICAgIGV4cGVjdChwYWdlLmNsb3NlKS50b0JlRGVmaW5lZCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUT0RPOiB0aGlzIHRlc3QgaXMgdmVyeSBmbGFreSBpbiB0aGUgQ0lcbiAgICAgICAgdGVzdC5za2lwKCdzaG91bGQgYWxsb3cgZWFybHkgYWJvcnRpbmcgaW4gY2FzZSBvZiBvdXRlciB0aW1lb3V0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdGltZW91dCA9IGJyb3dzZXJQb29sLm9wZXJhdGlvblRpbWVvdXRNaWxsaXM7XG4gICAgICAgICAgICBicm93c2VyUG9vbC5vcGVyYXRpb25UaW1lb3V0TWlsbGlzID0gNTAwO1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBtb2NraW5nIHByaXZhdGUgbWV0aG9kXG4gICAgICAgICAgICBjb25zdCBzcHkgPSB2aXRlc3Quc3B5T24oQnJvd3NlclBvb2wucHJvdG90eXBlLCAnX2V4ZWN1dGVIb29rcycpO1xuXG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICBleHBlY3Qoc3B5KS50b0JlQ2FsbGVkVGltZXMoNCk7XG4gICAgICAgICAgICBzcHkubW9ja1Jlc2V0KCk7XG5cbiAgICAgICAgICAgIGF3YWl0IGV4cGVjdChhZGRUaW1lb3V0VG9Qcm9taXNlKFxuICAgICAgICAgICAgICAgICgpID0+IGJyb3dzZXJQb29sLm5ld1BhZ2UoKSxcbiAgICAgICAgICAgICAgICAxMCxcbiAgICAgICAgICAgICAgICAnb3BlbmluZyBuZXcgcGFnZSB0aW1lZCBvdXQnLFxuICAgICAgICAgICAgKSkucmVqZWN0cy50b1Rocm93RXJyb3IoJ29wZW5pbmcgbmV3IHBhZ2UgdGltZWQgb3V0Jyk7XG5cbiAgICAgICAgICAgIC8vIFdlIHRlcm1pbmF0ZWQgZWFybHkgZW5vdWdoIHNvIG9ubHkgcHJlTGF1bmNoSG9va3Mgd2VyZSBub3QgZXhlY3V0ZWQsXG4gICAgICAgICAgICAvLyB0aGFua3MgdG8gYHRyeUNhbmNlbCgpYCBjYWxscyBhZnRlciBlYWNoIGF3YWl0LiBJZiB3ZSBkaWQgbm90IHJ1blxuICAgICAgICAgICAgLy8gaW5zaWRlIGBhZGRUaW1lb3V0VG9Qcm9taXNlKClgLCB0aGlzIHdvdWxkIG5vdCB3b3JrIGFuZCB3ZSB3b3VsZCBnZXRcbiAgICAgICAgICAgIC8vIDQgY2FsbHMgaW5zdGVhZCBvZiBqdXN0IG9uZS5cbiAgICAgICAgICAgIGV4cGVjdChzcHkpLnRvQmVDYWxsZWRUaW1lcygxKTtcblxuICAgICAgICAgICAgc3B5Lm1vY2tSZXN0b3JlKCk7XG4gICAgICAgICAgICBicm93c2VyUG9vbC5vcGVyYXRpb25UaW1lb3V0TWlsbGlzID0gdGltZW91dDtcbiAgICAgICAgICAgIGJyb3dzZXJQb29sLnJldGlyZUFsbEJyb3dzZXJzKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCBvcGVuIG5ldyBwYWdlIGluIGluY29nbml0byBjb250ZXh0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYnJvd3NlclBvb2xJbmNvZ25pdG8gPSBuZXcgQnJvd3NlclBvb2woe1xuICAgICAgICAgICAgICAgIGJyb3dzZXJQbHVnaW5zOiBbbmV3IFBsYXl3cmlnaHRQbHVnaW4ocGxheXdyaWdodC5jaHJvbWl1bSwgeyB1c2VJbmNvZ25pdG9QYWdlczogdHJ1ZSB9KV0sXG4gICAgICAgICAgICAgICAgY2xvc2VJbmFjdGl2ZUJyb3dzZXJBZnRlclNlY3M6IDIsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sSW5jb2duaXRvLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sSW5jb2duaXRvLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sSW5jb2duaXRvLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgZXhwZWN0KHBhZ2UuY29udGV4dCgpLnBhZ2VzKCkpLnRvSGF2ZUxlbmd0aCgxKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGVzdCgnc2hvdWxkIG9wZW4gbmV3IHBhZ2UgaW4gbmV3IGJyb3dzZXInLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB2aXRlc3Quc3B5T24ocGx1Z2luLCAnbGF1bmNoJyk7XG5cbiAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2VJbk5ld0Jyb3dzZXIoKTtcbiAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2VJbk5ld0Jyb3dzZXIoKTtcblxuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLmFjdGl2ZUJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDMpO1xuICAgICAgICAgICAgZXhwZWN0KHBsdWdpbi5sYXVuY2gpLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygzKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGVzdCgnc2hvdWxkIGNvcnJlY3RseSBvdmVycmlkZSBwYWdlIGNsb3NlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBQcml2YXRlIGZ1bmN0aW9uXG4gICAgICAgICAgICB2aXRlc3Quc3B5T24oYnJvd3NlclBvb2whLCAnX292ZXJyaWRlUGFnZUNsb3NlJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG5cbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbFsnX292ZXJyaWRlUGFnZUNsb3NlJ10pLnRvQmVDYWxsZWQoKTtcblxuICAgICAgICAgICAgY29uc3QgY29udHJvbGxlciA9IGJyb3dzZXJQb29sLmdldEJyb3dzZXJDb250cm9sbGVyQnlQYWdlKHBhZ2UpITtcblxuICAgICAgICAgICAgZXhwZWN0KGNvbnRyb2xsZXIuYWN0aXZlUGFnZXMpLnRvRXF1YWwoMSk7XG4gICAgICAgICAgICBleHBlY3QoY29udHJvbGxlci50b3RhbFBhZ2VzKS50b0VxdWFsKDEpO1xuXG4gICAgICAgICAgICBhd2FpdCBwYWdlLmNsb3NlKCk7XG5cbiAgICAgICAgICAgIGV4cGVjdChjb250cm9sbGVyLmFjdGl2ZVBhZ2VzKS50b0VxdWFsKDApO1xuICAgICAgICAgICAgZXhwZWN0KGNvbnRyb2xsZXIudG90YWxQYWdlcykudG9FcXVhbCgxKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGVzdCgnc2hvdWxkIHJldGlyZSBicm93c2VyIGFmdGVyIHBhZ2UgY291bnQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBicm93c2VyUG9vbC5yZXRpcmVCcm93c2VyQWZ0ZXJQYWdlQ291bnQgPSAyO1xuXG4gICAgICAgICAgICB2aXRlc3Quc3B5T24oYnJvd3NlclBvb2wsICdyZXRpcmVCcm93c2VyQ29udHJvbGxlcicpO1xuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLmFjdGl2ZUJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDApO1xuXG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG5cbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbC5hY3RpdmVCcm93c2VyQ29udHJvbGxlcnMuc2l6ZSkudG9CZSgxKTtcbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbC5yZXRpcmVkQnJvd3NlckNvbnRyb2xsZXJzLnNpemUpLnRvQmUoMSk7XG5cbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbC5yZXRpcmVCcm93c2VyQ29udHJvbGxlcikudG9CZUNhbGxlZFRpbWVzKDEpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0KCdzaG91bGQgYWxsb3cgbWF4IHBhZ2VzIHBlciBicm93c2VyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYnJvd3NlclBvb2wubWF4T3BlblBhZ2VzUGVyQnJvd3NlciA9IDE7XG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFByaXZhdGUgZnVuY3Rpb25cbiAgICAgICAgICAgIHZpdGVzdC5zcHlPbihicm93c2VyUG9vbCEsICdfbGF1bmNoQnJvd3NlcicpO1xuXG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2wuYWN0aXZlQnJvd3NlckNvbnRyb2xsZXJzLnNpemUpLnRvQmUoMSk7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2wuYWN0aXZlQnJvd3NlckNvbnRyb2xsZXJzLnNpemUpLnRvQmUoMik7XG4gICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2wuYWN0aXZlQnJvd3NlckNvbnRyb2xsZXJzLnNpemUpLnRvQmUoMyk7XG5cbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbFsnX2xhdW5jaEJyb3dzZXInXSkudG9CZUNhbGxlZFRpbWVzKDMpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0KCdzaG91bGQgYWxsb3cgbWF4IHBhZ2VzIHBlciBicm93c2VyIC0gbm8gcmFjZSBjb25kaXRpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBicm93c2VyUG9vbC5tYXhPcGVuUGFnZXNQZXJCcm93c2VyID0gMTtcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgUHJpdmF0ZSBmdW5jdGlvblxuICAgICAgICAgICAgdml0ZXN0LnNweU9uKGJyb3dzZXJQb29sLCAnX2xhdW5jaEJyb3dzZXInKTtcblxuICAgICAgICAgICAgY29uc3QgdXNlUGx1Z2luID0ge1xuICAgICAgICAgICAgICAgIGJyb3dzZXJQbHVnaW46IHBsdWdpbixcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgICBicm93c2VyUG9vbC5uZXdQYWdlKHVzZVBsdWdpbiksXG4gICAgICAgICAgICAgICAgYnJvd3NlclBvb2wubmV3UGFnZSh1c2VQbHVnaW4pLFxuICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbC5hY3RpdmVCcm93c2VyQ29udHJvbGxlcnMuc2l6ZSkudG9CZSgyKTtcblxuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sWydfbGF1bmNoQnJvd3NlciddKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3QoJ3Nob3VsZCBjbG9zZSByZXRpcmVkIGJyb3dzZXJzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYnJvd3NlclBvb2wucmV0aXJlQnJvd3NlckFmdGVyUGFnZUNvdW50ID0gMTtcblxuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChicm93c2VyUG9vbFsnYnJvd3NlcktpbGxlckludGVydmFsJ10hKTtcblxuICAgICAgICAgICAgYnJvd3NlclBvb2xbJ2Jyb3dzZXJLaWxsZXJJbnRlcnZhbCddID0gc2V0SW50ZXJ2YWwoXG4gICAgICAgICAgICAgICAgKCkgPT4gYnJvd3NlclBvb2xbJ19jbG9zZUluYWN0aXZlUmV0aXJlZEJyb3dzZXJzJ10oKSxcbiAgICAgICAgICAgICAgICAxMDAsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFByaXZhdGUgZnVuY3Rpb25cbiAgICAgICAgICAgIHZpdGVzdC5zcHlPbihicm93c2VyUG9vbCEsICdfY2xvc2VSZXRpcmVkQnJvd3NlcldpdGhOb1BhZ2VzJyk7XG4gICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2wucmV0aXJlZEJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDApO1xuXG4gICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlclBvb2wubmV3UGFnZSgpO1xuICAgICAgICAgICAgY29uc3QgY29udHJvbGxlciA9IGJyb3dzZXJQb29sLmdldEJyb3dzZXJDb250cm9sbGVyQnlQYWdlKHBhZ2UpITtcbiAgICAgICAgICAgIHZpdGVzdC5zcHlPbihjb250cm9sbGVyLCAnY2xvc2UnKTtcblxuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLnJldGlyZWRCcm93c2VyQ29udHJvbGxlcnMuc2l6ZSkudG9CZSgxKTtcbiAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcblxuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0sIDEwMDApKTtcblxuICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sWydfY2xvc2VSZXRpcmVkQnJvd3NlcldpdGhOb1BhZ2VzJ10pLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgICAgICAgIGV4cGVjdChjb250cm9sbGVyLmNsb3NlKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2wucmV0aXJlZEJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDApO1xuICAgICAgICB9KTtcblxuICAgICAgICBkZXNjcmliZSgnaG9va3MnLCAoKSA9PiB7XG4gICAgICAgICAgICB0ZXN0KCdzaG91bGQgcnVuIGhvb2tzIGluIHNlcmllcyB3aXRoIGN1c3RvbSBhcmdzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4QXJyYXk6IG51bWJlcltdID0gW107XG4gICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlQXN5bmNIb29rUmV0dXJuaW5nSW5kZXggPSAoaTogbnVtYmVyKSA9PiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gYXdhaXQgbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSkgPT4gc2V0VGltZW91dCgoKSA9PiByZXNvbHZlKGkpLCAxMDApKTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXhBcnJheS5wdXNoKGluZGV4KTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgY29uc3QgaG9va3MgPSBuZXcgQXJyYXkoMTApO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaG9va3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaG9va3NbaV0gPSBjcmVhdGVBc3luY0hvb2tSZXR1cm5pbmdJbmRleChpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbFsnX2V4ZWN1dGVIb29rcyddKGhvb2tzKTtcbiAgICAgICAgICAgICAgICBleHBlY3QoaW5kZXhBcnJheSkudG9IYXZlTGVuZ3RoKDEwKTtcbiAgICAgICAgICAgICAgICBpbmRleEFycmF5LmZvckVhY2goKHYsIGluZGV4KSA9PiBleHBlY3QodikudG9FcXVhbChpbmRleCkpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlc2NyaWJlKCdwcmVMYXVuY2hIb29rcycsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0ZXN0KCdzaG91bGQgZXZhbHVhdGUgaG9vayBiZWZvcmUgbGF1bmNoaW5nIGJyb3dzZXIgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG15QXN5bmNIb29rID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnByZUxhdW5jaEhvb2tzLnB1c2gobXlBc3luY0hvb2spO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgUHJpdmF0ZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICB2aXRlc3Quc3B5T24oYnJvd3NlclBvb2whLCAnX2V4ZWN1dGVIb29rcycpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2VJZCA9IGJyb3dzZXJQb29sLmdldFBhZ2VJZChwYWdlKSE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgbGF1bmNoQ29udGV4dCB9ID0gYnJvd3NlclBvb2wuZ2V0QnJvd3NlckNvbnRyb2xsZXJCeVBhZ2UocGFnZSkhO1xuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2xbJ19leGVjdXRlSG9va3MnXSkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMSwgYnJvd3NlclBvb2wucHJlTGF1bmNoSG9va3MsIHBhZ2VJZCwgbGF1bmNoQ29udGV4dCk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBoYWQgYSBwcm9ibGVtIHdoZXJlIGlmIHRoZSBmaXJzdCBuZXdQYWdlKCkgY2FsbCwgd2hpY2ggbGF1bmNoZXNcbiAgICAgICAgICAgICAgICAvLyBhIGJyb3dzZXIgZmFpbGVkIGluIGhvb2tzLCB0aGVuIHRoZSBicm93c2VyQ29udHJvbGxlciB3b3VsZCBnZXQgc3R1Y2tcbiAgICAgICAgICAgICAgICAvLyBpbiBsaW1ibyBhbmQgc3Vic2VxdWVudCBuZXdQYWdlKCkgY2FsbHMgd291bGQgbmV2ZXIgcmVzb2x2ZS5cbiAgICAgICAgICAgICAgICB0ZXN0KCdlcnJvciBpbiBob29rIGRvZXMgbm90IGxlYXZlIGJyb3dzZXIgc3R1Y2sgaW4gbGltYm8nLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9ICdwcmUtbGF1bmNoIGZhaWxlZCc7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnByZUxhdW5jaEhvb2tzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgYXN5bmMgKCkgPT4geyB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTsgfSxcbiAgICAgICAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBhdHRlbXB0cyA9IDU7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0ZW1wdHM7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBlY3QoKGVyciBhcyBFcnJvcikubWVzc2FnZSkudG9CZShlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLmFjdGl2ZUJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDApO1xuICAgICAgICAgICAgICAgICAgICBleHBlY3QuYXNzZXJ0aW9ucyhhdHRlbXB0cyArIDEpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlc2NyaWJlKCdwb3N0TGF1bmNoSG9va3MnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGV2YWx1YXRlIGhvb2sgYWZ0ZXIgbGF1bmNoaW5nIGJyb3dzZXIgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG15QXN5bmNIb29rID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnBvc3RMYXVuY2hIb29rcyA9IFtteUFzeW5jSG9va107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBQcml2YXRlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgIHZpdGVzdC5zcHlPbihicm93c2VyUG9vbCwgJ19leGVjdXRlSG9va3MnKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlclBvb2wubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlSWQgPSBicm93c2VyUG9vbC5nZXRQYWdlSWQocGFnZSkhO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBicm93c2VyQ29udHJvbGxlciA9IGJyb3dzZXJQb29sLmdldEJyb3dzZXJDb250cm9sbGVyQnlQYWdlKHBhZ2UpITtcblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2xbJ19leGVjdXRlSG9va3MnXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCgyLCBicm93c2VyUG9vbC5wb3N0TGF1bmNoSG9va3MsIHBhZ2VJZCwgYnJvd3NlckNvbnRyb2xsZXIpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gV2UgaGFkIGEgcHJvYmxlbSB3aGVyZSBpZiB0aGUgZmlyc3QgbmV3UGFnZSgpIGNhbGwsIHdoaWNoIGxhdW5jaGVzXG4gICAgICAgICAgICAgICAgLy8gYSBicm93c2VyIGZhaWxlZCBpbiBob29rcywgdGhlbiB0aGUgYnJvd3NlckNvbnRyb2xsZXIgd291bGQgZ2V0IHN0dWNrXG4gICAgICAgICAgICAgICAgLy8gaW4gbGltYm8gYW5kIHN1YnNlcXVlbnQgbmV3UGFnZSgpIGNhbGxzIHdvdWxkIG5ldmVyIHJlc29sdmUuXG4gICAgICAgICAgICAgICAgdGVzdCgnZXJyb3IgaW4gaG9vayBkb2VzIG5vdCBsZWF2ZSBicm93c2VyIHN0dWNrIGluIGxpbWJvJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSAncG9zdC1sYXVuY2ggZmFpbGVkJztcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udHJvbGxlcnM6IEJyb3dzZXJDb250cm9sbGVyW10gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2wucG9zdExhdW5jaEhvb2tzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgYXN5bmMgKF9wYWdlSWQsIGJyb3dzZXJDb250cm9sbGVyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlcnMucHVzaChicm93c2VyQ29udHJvbGxlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGF0dGVtcHRzID0gNTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhdHRlbXB0czsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdCgoZXJyIGFzIEVycm9yKS5tZXNzYWdlKS50b0JlKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBXYWl0IHVudGlsIGFsbCBicm93c2VycyBhcmUgY2xvc2VkLiBUaGlzIHdpbGwgb25seSByZXNvbHZlIGlmIGFsbCBjbG9zZSxcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgaXQgZG9lcyBub3QgcmVzb2x2ZSwgdGhlIHRlc3Qgd2lsbCB0aW1lb3V0IGFuZCBmYWlsLlxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW50ID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0aWxsV2FpdGluZyA9IGNvbnRyb2xsZXJzLnNvbWUoKGMpID0+IGMuaXNBY3RpdmUgPT09IHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc3RpbGxXYWl0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGJyb3dzZXJQb29sLmFjdGl2ZUJyb3dzZXJDb250cm9sbGVycy5zaXplKS50b0JlKDApO1xuICAgICAgICAgICAgICAgICAgICBleHBlY3QuYXNzZXJ0aW9ucyhhdHRlbXB0cyArIDEpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlc2NyaWJlKCdwcmVQYWdlQ3JlYXRlSG9va3MnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGV2YWx1YXRlIGhvb2sgYWZ0ZXIgbGF1bmNoaW5nIGJyb3dzZXIgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG15QXN5bmNIb29rID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnByZVBhZ2VDcmVhdGVIb29rcyA9IFtteUFzeW5jSG9va107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBQcml2YXRlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgIHZpdGVzdC5zcHlPbihicm93c2VyUG9vbCwgJ19leGVjdXRlSG9va3MnKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlclBvb2wubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlSWQgPSBicm93c2VyUG9vbC5nZXRQYWdlSWQocGFnZSkhO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBicm93c2VyQ29udHJvbGxlciA9IGJyb3dzZXJQb29sLmdldEJyb3dzZXJDb250cm9sbGVyQnlQYWdlKHBhZ2UpITtcblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2xbJ19leGVjdXRlSG9va3MnXSkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoXG4gICAgICAgICAgICAgICAgICAgICAgICAzLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2wucHJlUGFnZUNyZWF0ZUhvb2tzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlckNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyQ29udHJvbGxlci5sYXVuY2hDb250ZXh0LnVzZUluY29nbml0b1BhZ2VzID8ge30gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZGVzY3JpYmUoJ3Bvc3RQYWdlQ3JlYXRlSG9va3MnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGV2YWx1YXRlIGhvb2sgYWZ0ZXIgbGF1bmNoaW5nIGJyb3dzZXIgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG15QXN5bmNIb29rID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnBvc3RQYWdlQ3JlYXRlSG9va3MgPSBbbXlBc3luY0hvb2tdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgUHJpdmF0ZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICB2aXRlc3Quc3B5T24oYnJvd3NlclBvb2wsICdfZXhlY3V0ZUhvb2tzJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnJvd3NlckNvbnRyb2xsZXIgPSBicm93c2VyUG9vbC5nZXRCcm93c2VyQ29udHJvbGxlckJ5UGFnZShwYWdlKTtcblxuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2xbJ19leGVjdXRlSG9va3MnXSkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoNCwgYnJvd3NlclBvb2wucG9zdFBhZ2VDcmVhdGVIb29rcywgcGFnZSwgYnJvd3NlckNvbnRyb2xsZXIpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlc2NyaWJlKCdwcmVQYWdlQ2xvc2VIb29rcycsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0ZXN0KCdzaG91bGQgZXZhbHVhdGUgaG9vayBhZnRlciBsYXVuY2hpbmcgYnJvd3NlciB3aXRoIGNvcnJlY3QgYXJncycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbXlBc3luY0hvb2sgPSAoKSA9PiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2wucHJlUGFnZUNsb3NlSG9va3MgPSBbbXlBc3luY0hvb2tdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgUHJpdmF0ZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICB2aXRlc3Quc3B5T24oYnJvd3NlclBvb2wsICdfZXhlY3V0ZUhvb2tzJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcGFnZS5jbG9zZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250cm9sbGVyID0gYnJvd3NlclBvb2wuZ2V0QnJvd3NlckNvbnRyb2xsZXJCeVBhZ2UocGFnZSk7XG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbFsnX2V4ZWN1dGVIb29rcyddKS50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCg1LCBicm93c2VyUG9vbC5wcmVQYWdlQ2xvc2VIb29rcywgcGFnZSwgYnJvd3NlckNvbnRyb2xsZXIpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlc2NyaWJlKCdwb3N0UGFnZUNsb3NlSG9va3MnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGV2YWx1YXRlIGhvb2sgYWZ0ZXIgbGF1bmNoaW5nIGJyb3dzZXIgd2l0aCBjb3JyZWN0IGFyZ3MnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG15QXN5bmNIb29rID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnBvc3RQYWdlQ2xvc2VIb29rcyA9IFtteUFzeW5jSG9va107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBQcml2YXRlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgIHZpdGVzdC5zcHlPbihicm93c2VyUG9vbCwgJ19leGVjdXRlSG9va3MnKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgYnJvd3NlclBvb2wubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlSWQgPSBicm93c2VyUG9vbC5nZXRQYWdlSWQocGFnZSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBicm93c2VyQ29udHJvbGxlciA9IGJyb3dzZXJQb29sLmdldEJyb3dzZXJDb250cm9sbGVyQnlQYWdlKHBhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBleHBlY3QoYnJvd3NlclBvb2xbJ19leGVjdXRlSG9va3MnXSkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoNiwgYnJvd3NlclBvb2wucG9zdFBhZ2VDbG9zZUhvb2tzLCBwYWdlSWQsIGJyb3dzZXJDb250cm9sbGVyKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBkZXNjcmliZSgnZGVmYXVsdCBicm93c2VyIGF1dG9tYXRpb24gbWFza2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICBkZXNjcmliZS5lYWNoKGZpbmdlcnByaW50aW5nTWF0cml4KSgnJXMnLCAoX25hbWUsIGZpbmdlcnByaW50UGx1Z2luKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBicm93c2VyUG9vbFdpdGhEZWZhdWx0czogQnJvd3NlclBvb2w7XG4gICAgICAgICAgICAgICAgICAgIGxldCBwYWdlOiBhbnk7XG5cbiAgICAgICAgICAgICAgICAgICAgYmVmb3JlRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyUG9vbFdpdGhEZWZhdWx0cyA9IG5ldyBCcm93c2VyUG9vbCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBsdWdpbnM6IFtmaW5nZXJwcmludFBsdWdpbl0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VJbmFjdGl2ZUJyb3dzZXJBZnRlclNlY3M6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2UgPSBhd2FpdCBicm93c2VyUG9vbFdpdGhEZWZhdWx0cy5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFnZSkgYXdhaXQgcGFnZS5jbG9zZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbFdpdGhEZWZhdWx0cy5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCBoaWRlIHdlYmRyaXZlcicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UuZ290byhgZmlsZTovLyR7X19kaXJuYW1lfS90ZXN0Lmh0bWxgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdlYmRyaXZlciA9IGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXZpZ2F0b3Iud2ViZHJpdmVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDYW4gYmUgdW5kZWZpbmVkIG9yIGZhbHNlLCBkZXBlbmRpbmcgb24gdGhlIGNocm9tZSB2ZXJzaW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0KHdlYmRyaXZlcikudG9CZUZhbHN5KCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlc2NyaWJlKCdmaW5nZXJwcmludGluZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICBkZXNjcmliZS5lYWNoKGZpbmdlcnByaW50aW5nTWF0cml4KSgnJXMnLCAoX25hbWUsIGZpbmdlcnByaW50UGx1Z2luKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBicm93c2VyUG9vbFdpdGhGUDogQnJvd3NlclBvb2w7XG4gICAgICAgICAgICAgICAgICAgIGxldCBwYWdlOiBhbnk7XG5cbiAgICAgICAgICAgICAgICAgICAgYmVmb3JlRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyUG9vbFdpdGhGUCA9IG5ldyBCcm93c2VyUG9vbCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBsdWdpbnM6IFtmaW5nZXJwcmludFBsdWdpbl0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VJbmFjdGl2ZUJyb3dzZXJBZnRlclNlY3M6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlRmluZ2VycHJpbnRzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYWdlID0gYXdhaXQgYnJvd3NlclBvb2xXaXRoRlAubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBhZnRlckVhY2goYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhZ2UpIGF3YWl0IHBhZ2UuY2xvc2UoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgYnJvd3NlclBvb2xXaXRoRlAuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICB0ZXN0KCdzaG91bGQgb3ZlcnJpZGUgZmluZ2VycHJpbnQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBwYWdlLmdvdG8oYGZpbGU6Ly8ke19fZGlybmFtZX0vdGVzdC5odG1sYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIG1pc3R5cGluZ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJDb250cm9sbGVyID0gYnJvd3NlclBvb2xXaXRoRlAuZ2V0QnJvd3NlckNvbnRyb2xsZXJCeVBhZ2UocGFnZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGE6IHsgaGFyZHdhcmVDb25jdXJyZW5jeTogbnVtYmVyOyB1c2VyQWdlbnQ6IHN0cmluZyB9ID0gYXdhaXQgcGFnZS5ldmFsdWF0ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFyZHdhcmVDb25jdXJyZW5jeTogbmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJBZ2VudDogbmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIG1pc3R5cGluZ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgZmluZ2VycHJpbnQgfSA9IGJyb3dzZXJDb250cm9sbGVyIS5sYXVuY2hDb250ZXh0IS5maW5nZXJwcmludCBhcyBCcm93c2VyRmluZ2VycHJpbnRXaXRoSGVhZGVycztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGRhdGEuaGFyZHdhcmVDb25jdXJyZW5jeSkudG9CZShmaW5nZXJwcmludD8ubmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3kpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGRhdGEudXNlckFnZW50KS50b0JlKGZpbmdlcnByaW50Py5uYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGhpZGUgd2ViZHJpdmVyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgcGFnZS5nb3RvKGBmaWxlOi8vJHtfX2Rpcm5hbWV9L3Rlc3QuaHRtbGApO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2ViZHJpdmVyID0gYXdhaXQgcGFnZS5ldmFsdWF0ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRvci53ZWJkcml2ZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENhbiBiZSB1bmRlZmluZWQgb3IgZmFsc2UsIGRlcGVuZGluZyBvbiB0aGUgY2hyb21lIHZlcnNpb24uXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3Qod2ViZHJpdmVyKS50b0JlRmFsc3koKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBkZXNjcmliZSgnY2FjaGluZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tbW9uT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQbHVnaW5zOiBbbmV3IFBsYXl3cmlnaHRQbHVnaW4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxheXdyaWdodC5jaHJvbWl1bSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZUluY29nbml0b1BhZ2VzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICApXSxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGJyb3dzZXJQb29sQ2FjaGU6IEJyb3dzZXJQb29sO1xuXG4gICAgICAgICAgICAgICAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbENhY2hlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCB1c2UgZmluZ2VycHJpbnQgY2FjaGUgYnkgZGVmYXVsdCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sQ2FjaGUgPSBuZXcgQnJvd3NlclBvb2woe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmNvbW1vbk9wdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlRmluZ2VycHJpbnRzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbENhY2hlLmZpbmdlcnByaW50Q2FjaGUpLnRvQmVEZWZpbmVkKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRlc3QoJ3Nob3VsZCB0dXJuIG9mZiBjYWNoZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sQ2FjaGUgPSBuZXcgQnJvd3NlclBvb2woe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmNvbW1vbk9wdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlRmluZ2VycHJpbnRzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmdlcnByaW50T3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VGaW5nZXJwcmludENhY2hlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdChicm93c2VyUG9vbENhY2hlLmZpbmdlcnByaW50Q2FjaGUpLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGVzdCgnc2hvdWxkIGxpbWl0IGNhY2hlIHNpemUnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyUG9vbENhY2hlID0gbmV3IEJyb3dzZXJQb29sKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jb21tb25PcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZUZpbmdlcnByaW50czogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5nZXJwcmludE9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluZ2VycHJpbnRDYWNoZVNpemU6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FzdCB0byBhbnkgdHlwZSBpbiBvcmRlciB0byBhY2NlcyB0aGUgbWF4U2l6ZSBwcm9wZXJ0eSBmb3IgdGVzdGluZyBwdXJwb3Nlcy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlOiBhbnkgPSBicm93c2VyUG9vbENhY2hlIS5maW5nZXJwcmludENhY2hlITtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdChjYWNoZS5tYXhTaXplKS50b0JlKDEpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICB0ZXN0KCdzaG91bGQgY2FjaGUgZmluZ2VycHJpbnRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2xDYWNoZSA9IG5ldyBCcm93c2VyUG9vbCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uY29tbW9uT3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VGaW5nZXJwcmludHM6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlTGF1bmNoSG9va3M6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF9wYWdlSWQsIGxhdW5jaENvbnRleHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgaXNzdWUgY2F1c2VkIGJ5IGdlbmVyaWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXVuY2hDb250ZXh0LmV4dGVuZCh7IHNlc3Npb246IHsgaWQ6ICcxMjMnIH0gfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbW9jayA9IHZpdGVzdC5mbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2xDYWNoZS5maW5nZXJwcmludEluamVjdG9yIS5hdHRhY2hGaW5nZXJwcmludFRvUGxheXdyaWdodCA9IG1vY2s7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlOiBQYWdlID0gYXdhaXQgYnJvd3NlclBvb2xDYWNoZS5uZXdQYWdlSW5OZXdCcm93c2VyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3QobW9jay5tb2NrLmNhbGxzWzBdWzFdKS50b0JlRGVmaW5lZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFnZTI6IFBhZ2UgPSBhd2FpdCBicm93c2VyUG9vbENhY2hlLm5ld1BhZ2VJbk5ld0Jyb3dzZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UyLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBleHBlY3QgZmluZ2VycHJpbnQgcGFyYW1ldGVyIG9mIHRoZSBmaXJzdCBjYWxsIHRvIGVxdWFsIGZpbmdlcnByaW50IHBhcmFtZXRlciBvZiB0aGUgc2Vjb25kIGNhbGxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdChtb2NrLm1vY2suY2FsbHNbMF1bMV0pLnRvQmUobW9jay5tb2NrLmNhbGxzWzFdWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlc2NyaWJlKCdnZW5lcmF0b3IgY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb21tb25PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyUGx1Z2luczogW25ldyBQbGF5d3JpZ2h0UGx1Z2luKFxuICAgICAgICAgICAgICAgICAgICAgICAgcGxheXdyaWdodC5maXJlZm94LFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZUluY29nbml0b1BhZ2VzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgKV0sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBsZXQgYnJvd3NlclBvb2xDb25maWc6IEJyb3dzZXJQb29sO1xuICAgICAgICAgICAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQb29sQ29uZmlnLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0ZXN0KCdzaG91bGQgdXNlIG5hdGl2ZSBvcyBhbmQgYnJvd3NlcicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2xDb25maWcgPSBuZXcgQnJvd3NlclBvb2woe1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY29tbW9uT3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHVzZUZpbmdlcnByaW50czogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZEdldCA9IGJyb3dzZXJQb29sQ29uZmlnLmZpbmdlcnByaW50R2VuZXJhdG9yLmdldEZpbmdlcnByaW50O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtb2NrID0gdml0ZXN0LmZuKChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2xkR2V0LmJpbmQoYnJvd3NlclBvb2xDb25maWcuZmluZ2VycHJpbnRHZW5lcmF0b3IpKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2xDb25maWcuZmluZ2VycHJpbnRHZW5lcmF0b3IuZ2V0RmluZ2VycHJpbnQgPSBtb2NrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2U6IFBhZ2UgPSBhd2FpdCBicm93c2VyUG9vbENvbmZpZy5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdE9wdGlvbnMgPSBtb2NrLm1vY2suY2FsbHNbMF1bMF07XG5cbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGRlZmF1bHRPcHRpb25zLmJyb3dzZXJzLmluY2x1ZGVzKCdmaXJlZm94JykpLnRvQmUodHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IG9zOiBzdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAocHJvY2Vzcy5wbGF0Zm9ybSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZGFyd2luJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcyA9ICdtYWNvcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd3aW4zMic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3MgPSAnd2luZG93cyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9zID0gJ2xpbnV4JztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBleHBlY3QoZGVmYXVsdE9wdGlvbnMub3BlcmF0aW5nU3lzdGVtcy5pbmNsdWRlcyhvcykpLnRvQmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICB0ZXN0KCdzaG91bGQgYWxsb3cgY2hhbmdpbmcgb3B0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2xDb25maWcgPSBuZXcgQnJvd3NlclBvb2woe1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uY29tbW9uT3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHVzZUZpbmdlcnByaW50czogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmdlcnByaW50T3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmdlcnByaW50R2VuZXJhdG9yT3B0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVyYXRpbmdTeXN0ZW1zOiBbT3BlcmF0aW5nU3lzdGVtc05hbWUud2luZG93c10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyb3dzZXJzOiBbQnJvd3Nlck5hbWUuY2hyb21lXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZEdldCA9IGJyb3dzZXJQb29sQ29uZmlnLmZpbmdlcnByaW50R2VuZXJhdG9yLmdldEZpbmdlcnByaW50O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtb2NrID0gdml0ZXN0LmZuKChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2xkR2V0LmJpbmQoYnJvd3NlclBvb2xDb25maWcuZmluZ2VycHJpbnRHZW5lcmF0b3IpKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlclBvb2xDb25maWcuZmluZ2VycHJpbnRHZW5lcmF0b3IuZ2V0RmluZ2VycHJpbnQgPSBtb2NrO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlOiBQYWdlID0gYXdhaXQgYnJvd3NlclBvb2xDb25maWcubmV3UGFnZUluTmV3QnJvd3NlcigpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBwYWdlLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IFtvcHRpb25zXSA9IG1vY2subW9jay5jYWxsc1swXTtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0KG9wdGlvbnMub3BlcmF0aW5nU3lzdGVtcy5pbmNsdWRlcygnd2luZG93cycpKS50b0JlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBleHBlY3Qob3B0aW9ucy5icm93c2Vycy5pbmNsdWRlcygnY2hyb21lJykpLnRvQmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZGVzY3JpYmUoJ2V2ZW50cycsICgpID0+IHtcbiAgICAgICAgICAgIHRlc3QoYHNob3VsZCBlbWl0ICR7QlJPV1NFUl9QT09MX0VWRU5UUy5CUk9XU0VSX0xBVU5DSEVEfSBldmVudGAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBicm93c2VyUG9vbC5tYXhPcGVuUGFnZXNQZXJCcm93c2VyID0gMTtcbiAgICAgICAgICAgICAgICBsZXQgY2FsbHMgPSAwO1xuICAgICAgICAgICAgICAgIGxldCBhcmd1bWVudDtcblxuICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLm9uKEJST1dTRVJfUE9PTF9FVkVOVFMuQlJPV1NFUl9MQVVOQ0hFRCwgKGFyZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhcmd1bWVudCA9IGFyZztcbiAgICAgICAgICAgICAgICAgICAgY2FsbHMrKztcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgICAgIGV4cGVjdChjYWxscykudG9FcXVhbCgyKTtcbiAgICAgICAgICAgICAgICBleHBlY3QoYXJndW1lbnQpLnRvRXF1YWwoYnJvd3NlclBvb2wuZ2V0QnJvd3NlckNvbnRyb2xsZXJCeVBhZ2UocGFnZSkpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRlc3QoYHNob3VsZCBlbWl0ICR7QlJPV1NFUl9QT09MX0VWRU5UUy5CUk9XU0VSX1JFVElSRUR9IGV2ZW50YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLnJldGlyZUJyb3dzZXJBZnRlclBhZ2VDb3VudCA9IDE7XG4gICAgICAgICAgICAgICAgbGV0IGNhbGxzID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgYXJndW1lbnQ7XG4gICAgICAgICAgICAgICAgYnJvd3NlclBvb2wub24oQlJPV1NFUl9QT09MX0VWRU5UUy5CUk9XU0VSX1JFVElSRUQsIChhcmcpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYXJndW1lbnQgPSBhcmc7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxzKys7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcblxuICAgICAgICAgICAgICAgIGV4cGVjdChjYWxscykudG9FcXVhbCgyKTtcbiAgICAgICAgICAgICAgICBleHBlY3QoYXJndW1lbnQpLnRvRXF1YWwoYnJvd3NlclBvb2wuZ2V0QnJvd3NlckNvbnRyb2xsZXJCeVBhZ2UocGFnZSkpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRlc3QoYHNob3VsZCBlbWl0ICR7QlJPV1NFUl9QT09MX0VWRU5UUy5QQUdFX0NSRUFURUR9IGV2ZW50YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBjYWxscyA9IDA7XG4gICAgICAgICAgICAgICAgbGV0IGFyZ3VtZW50O1xuICAgICAgICAgICAgICAgIGJyb3dzZXJQb29sLm9uKEJST1dTRVJfUE9PTF9FVkVOVFMuUEFHRV9DUkVBVEVELCAoYXJnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50ID0gYXJnO1xuICAgICAgICAgICAgICAgICAgICBjYWxscysrO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICBleHBlY3QoYXJndW1lbnQpLnRvRXF1YWwocGFnZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFnZTIgPSBhd2FpdCBicm93c2VyUG9vbC5uZXdQYWdlKCk7XG4gICAgICAgICAgICAgICAgZXhwZWN0KGNhbGxzKS50b0VxdWFsKDIpO1xuICAgICAgICAgICAgICAgIGV4cGVjdChhcmd1bWVudCkudG9FcXVhbChwYWdlMik7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGVzdChgc2hvdWxkIGVtaXQgJHtCUk9XU0VSX1BPT0xfRVZFTlRTLlBBR0VfQ0xPU0VEfSBldmVudGAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgY2FsbHMgPSAwO1xuICAgICAgICAgICAgICAgIGxldCBhcmd1bWVudDtcbiAgICAgICAgICAgICAgICBicm93c2VyUG9vbC5vbihCUk9XU0VSX1BPT0xfRVZFTlRTLlBBR0VfQ0xPU0VELCAoYXJnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50ID0gYXJnO1xuICAgICAgICAgICAgICAgICAgICBjYWxscysrO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGJyb3dzZXJQb29sLm5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBwYWdlLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgZXhwZWN0KGFyZ3VtZW50KS50b0VxdWFsKHBhZ2UpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2UyID0gYXdhaXQgYnJvd3NlclBvb2wubmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHBhZ2UyLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgZXhwZWN0KGNhbGxzKS50b0VxdWFsKDIpO1xuICAgICAgICAgICAgICAgIGV4cGVjdChhcmd1bWVudCkudG9FcXVhbChwYWdlMik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59KTtcbiJdLCJmaWxlIjoiL1VzZXJzL3ZsYWQvRGV2ZWxvcG1lbnQvQXBpZnkvY3Jhd2xlZS90ZXN0L2Jyb3dzZXItcG9vbC9icm93c2VyLXBvb2wudGVzdC50cyJ9
// /Users/vlad/Development/Apify/crawlee/test/browser-pool/index.test.ts
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var modules = __toESM(require("@crawlee/browser-pool"));
var import_browser_pool = require("../../packages/browser-pool/src/browser-pool");
var import_playwright_plugin = require("../../packages/browser-pool/src/playwright/playwright-plugin");
var import_puppeteer_plugin = require("../../packages/browser-pool/src/puppeteer/puppeteer-plugin");
describe("Exports", () => {
test("Modules", () => {
expect(modules.BrowserPool).toEqual(import_browser_pool.BrowserPool);
expect(modules.PuppeteerPlugin).toEqual(import_puppeteer_plugin.PuppeteerPlugin);
expect(modules.PlaywrightPlugin).toEqual(import_playwright_plugin.PlaywrightPlugin);
});
});
//# sourceMappingSource=vite-node
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxjQUF5QjtBQUV6QiwwQkFBNEI7QUFDNUIsK0JBQWlDO0FBQ2pDLDhCQUFnQztBQUVoQyxTQUFTLFdBQVcsTUFBTTtBQUN0QixPQUFLLFdBQVcsTUFBTTtBQUNsQixXQUFPLFFBQVEsV0FBVyxFQUFFLFFBQVEsK0JBQVc7QUFDL0MsV0FBTyxRQUFRLGVBQWUsRUFBRSxRQUFRLHVDQUFlO0FBQ3ZELFdBQU8sUUFBUSxnQkFBZ0IsRUFBRSxRQUFRLHlDQUFnQjtBQUFBLEVBQzdELENBQUM7QUFDTCxDQUFDIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbImluZGV4LnRlc3QudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgbW9kdWxlcyBmcm9tICdAY3Jhd2xlZS9icm93c2VyLXBvb2wnO1xuXG5pbXBvcnQgeyBCcm93c2VyUG9vbCB9IGZyb20gJy4uLy4uL3BhY2thZ2VzL2Jyb3dzZXItcG9vbC9zcmMvYnJvd3Nlci1wb29sJztcbmltcG9ydCB7IFBsYXl3cmlnaHRQbHVnaW4gfSBmcm9tICcuLi8uLi9wYWNrYWdlcy9icm93c2VyLXBvb2wvc3JjL3BsYXl3cmlnaHQvcGxheXdyaWdodC1wbHVnaW4nO1xuaW1wb3J0IHsgUHVwcGV0ZWVyUGx1Z2luIH0gZnJvbSAnLi4vLi4vcGFja2FnZXMvYnJvd3Nlci1wb29sL3NyYy9wdXBwZXRlZXIvcHVwcGV0ZWVyLXBsdWdpbic7XG5cbmRlc2NyaWJlKCdFeHBvcnRzJywgKCkgPT4ge1xuICAgIHRlc3QoJ01vZHVsZXMnLCAoKSA9PiB7XG4gICAgICAgIGV4cGVjdChtb2R1bGVzLkJyb3dzZXJQb29sKS50b0VxdWFsKEJyb3dzZXJQb29sKTtcbiAgICAgICAgZXhwZWN0KG1vZHVsZXMuUHVwcGV0ZWVyUGx1Z2luKS50b0VxdWFsKFB1cHBldGVlclBsdWdpbik7XG4gICAgICAgIGV4cGVjdChtb2R1bGVzLlBsYXl3cmlnaHRQbHVnaW4pLnRvRXF1YWwoUGxheXdyaWdodFBsdWdpbik7XG4gICAgfSk7XG59KTtcbiJdLCJmaWxlIjoiL1VzZXJzL3ZsYWQvRGV2ZWxvcG1lbnQvQXBpZnkvY3Jhd2xlZS90ZXN0L2Jyb3dzZXItcG9vbC9pbmRleC50ZXN0LnRzIn0=
{
"time": "10/5/2023, 3:38:34 PM",
"externalize": {
"/Users/vlad/Development/Apify/crawlee/node_modules/@vitest/coverage-v8/dist/index.js": "/Users/vlad/Development/Apify/crawlee/node_modules/@vitest/coverage-v8/dist/index.js",
"/Users/vlad/Development/Apify/crawlee/node_modules/vitest/dist/spy.js": "/Users/vlad/Development/Apify/crawlee/node_modules/vitest/dist/spy.js",
"/Users/vlad/Development/Apify/crawlee/node_modules/vitest/dist/runners.js": "/Users/vlad/Development/Apify/crawlee/node_modules/vitest/dist/runners.js"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment