UNPKG

@decaf-ts/utils

Version:

module management utils for decaf-ts

262 lines 32.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TestReporter = exports.JestReportersTempPathEnvKey = void 0; const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const fs_2 = require("./fs.cjs"); exports.JestReportersTempPathEnvKey = "JEST_HTML_REPORTERS_TEMP_DIR_PATH"; const dependencies = ["jest-html-reporters", "json2md", "chartjs-node-canvas"]; async function normalizeImport(importPromise) { // CommonJS's `module.exports` is wrapped as `default` in ESModule. return importPromise.then((m) => (m.default || m)); } /** * @description Test reporting utility class for managing test results and evidence * @summary A comprehensive test reporter that handles various types of test artifacts including messages, * attachments, data, images, tables, and graphs. It provides methods to report and store test evidence * in different formats and manages dependencies for reporting functionality. * * @template T - Type of data being reported * @param {string} [testCase="tests"] - Name of the test case * @param {string} [basePath] - Base path for storing test reports * @class * * @example * ```typescript * const reporter = new TestReporter('login-test'); * * // Report test messages * await reporter.reportMessage('Test Started', 'Login flow initiated'); * * // Report test data * await reporter.reportData('user-credentials', { username: 'test' }, 'json'); * * // Report test results table * await reporter.reportTable('test-results', { * headers: ['Step', 'Status'], * rows: [ * { Step: 'Login', Status: 'Pass' }, * { Step: 'Validation', Status: 'Pass' } * ] * }); * * // Report test evidence * await reporter.reportAttachment('Screenshot', screenshotBuffer); * ``` * * @mermaid * sequenceDiagram * participant Client * participant TestReporter * participant FileSystem * participant Dependencies * * Client->>TestReporter: new TestReporter(testCase, basePath) * TestReporter->>FileSystem: Create report directory * * alt Report Message * Client->>TestReporter: reportMessage(title, message) * TestReporter->>Dependencies: Import helpers * TestReporter->>FileSystem: Store message * else Report Data * Client->>TestReporter: reportData(reference, data, type) * TestReporter->>Dependencies: Process data * TestReporter->>FileSystem: Store formatted data * else Report Table * Client->>TestReporter: reportTable(reference, tableDef) * TestReporter->>Dependencies: Convert to MD format * TestReporter->>FileSystem: Store table * end */ class TestReporter { constructor(testCase = "tests", basePath = path_1.default.join(process.cwd(), "workdocs", "reports", "evidences")) { this.testCase = testCase; this.basePath = basePath; this.basePath = path_1.default.join(basePath, this.testCase); if (!fs_1.default.existsSync(this.basePath)) { fs_1.default.mkdirSync(basePath, { recursive: true }); } } /** * @description Imports required helper functions * @summary Ensures all necessary dependencies are available and imports helper functions * @return {Promise<void>} Promise that resolves when helpers are imported */ async importHelpers() { this.deps = await (0, fs_2.installIfNotAvailable)([dependencies[0]], this.deps); // if (!process.env[JestReportersTempPathEnvKey]) // process.env[JestReportersTempPathEnvKey] = './workdocs/reports'; const { addMsg, addAttach } = await normalizeImport(Promise.resolve(`${`${dependencies[0]}/helper`}`).then(s => __importStar(require(s)))); TestReporter.addMsgFunction = addMsg; TestReporter.addAttachFunction = addAttach; } /** * @description Reports a message to the test report * @summary Adds a formatted message to the test report with an optional title * @param {string} title - Title of the message * @param {string | object} message - Content of the message * @return {Promise<void>} Promise that resolves when the message is reported */ async reportMessage(title, message) { if (!TestReporter.addMsgFunction) await this.importHelpers(); const msg = `${title}${message ? `\n${message}` : ""}`; await TestReporter.addMsgFunction({ message: msg }); } /** * @description Reports an attachment to the test report * @summary Adds a formatted message to the test report with an optional title * @param {string} title - Title of the message * @param {string | Buffer} attachment - Content of the message * @return {Promise<void>} Promise that resolves when the message is reported */ async reportAttachment(title, attachment) { if (!TestReporter.addAttachFunction) await this.importHelpers(); await TestReporter.addAttachFunction({ attach: attachment, description: title, }); } /** * @description Reports data with specified type * @summary Processes and stores data in the test report with formatting * @param {string} reference - Reference identifier for the data * @param {string | number | object} data - Data to be reported * @param {PayloadType} type - Type of the payload * @param {boolean} [trim=false] - Whether to trim the data * @return {Promise<void>} Promise that resolves when data is reported */ async report(reference, data, type, trim = false) { try { let attachFunction = this.reportMessage.bind(this); let extension = ".txt"; switch (type) { case "image": data = Buffer.from(data); extension = ".png"; attachFunction = this.reportAttachment.bind(this); break; case "json": if (trim) { if (data.request) delete data["request"]; if (data.config) delete data["config"]; } data = JSON.stringify(data, null, 2); extension = ".json"; break; case "md": extension = ".md"; break; case "text": extension = ".txt"; break; default: console.log(`Unsupported type ${type}. assuming text`); } reference = reference.includes("\n") ? reference : `${reference}${extension}`; await attachFunction(reference, data); } catch (e) { throw new Error(`Could not store attach artifact ${reference} under to test report ${this.testCase} - ${e}`); } } async reportData(reference, data, type = "json", trim = false) { return this.report(reference, data, type, trim); } async reportObject(reference, json, trim = false) { return this.report(reference, json, "json", trim); } /** * @description Reports a table in markdown format * @summary Converts and stores a table definition in markdown format * @param {string} reference - Reference identifier for the table * @param {MdTableDefinition} tableDef - Table definition object * @return {Promise<void>} Promise that resolves when table is reported */ async reportTable(reference, tableDef) { this.deps = await (0, fs_2.installIfNotAvailable)([dependencies[1]], this.deps); let txt; try { const json2md = await normalizeImport(Promise.resolve(`${`${dependencies[1]}`}`).then(s => __importStar(require(s)))); txt = json2md(tableDef); } catch (e) { throw new Error(`Could not convert JSON to Markdown - ${e}`); } return this.report(reference, txt, "md"); } /** * @description Reports a graph using Chart.js * @summary Generates and stores a graph visualization * @param {string} reference - Reference identifier for the graph * @param {any} config - Chart.js configuration object * @return {Promise<void>} Promise that resolves when graph is reported */ async reportGraph(reference, config) { this.deps = await (0, fs_2.installIfNotAvailable)([dependencies[2]], this.deps); const { ChartJSNodeCanvas } = await normalizeImport(Promise.resolve(`${dependencies[2]}`).then(s => __importStar(require(s)))); const width = 600; //px const height = 800; //px const backgroundColour = "white"; // Uses https://www.w3schools.com/tags/canvas_fillstyle.asp const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height, backgroundColour, }); const image = await chartJSNodeCanvas.renderToBuffer(config); return await this.reportImage(reference, image); } /** * @description Reports an image to the test report * @summary Stores an image buffer in the test report * @param {string} reference - Reference identifier for the image * @param {Buffer} buffer - Image data buffer * @return {Promise<void>} Promise that resolves when image is reported */ async reportImage(reference, buffer) { return this.report(reference, buffer, "image"); } } exports.TestReporter = TestReporter; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvdGVzdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0RBQXdCO0FBQ3hCLDRDQUFvQjtBQUVwQixpQ0FBNkM7QUFtQ2hDLFFBQUEsMkJBQTJCLEdBQUcsbUNBQW1DLENBQUM7QUFFL0UsTUFBTSxZQUFZLEdBQUcsQ0FBQyxxQkFBcUIsRUFBRSxTQUFTLEVBQUUscUJBQXFCLENBQUMsQ0FBQztBQUUvRSxLQUFLLFVBQVUsZUFBZSxDQUFJLGFBQXlCO0lBQ3pELG1FQUFtRTtJQUNuRSxPQUFPLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQU0sQ0FBQyxDQUFDO0FBQy9ELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeURHO0FBQ0gsTUFBYSxZQUFZO0lBd0J2QixZQUNZLFdBQW1CLE9BQU8sRUFDMUIsV0FBVyxjQUFJLENBQUMsSUFBSSxDQUM1QixPQUFPLENBQUMsR0FBRyxFQUFFLEVBQ2IsVUFBVSxFQUNWLFNBQVMsRUFDVCxXQUFXLENBQ1o7UUFOUyxhQUFRLEdBQVIsUUFBUSxDQUFrQjtRQUMxQixhQUFRLEdBQVIsUUFBUSxDQUtqQjtRQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsY0FBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxZQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2xDLFlBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFD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LENBQUMsQ0FBQztJQUNqRCxDQUFDO0NBQ0Y7QUFuTkQsb0NBbU5DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IE1kVGFibGVEZWZpbml0aW9uIH0gZnJvbSBcIi4vbWRcIjtcbmltcG9ydCB7IGluc3RhbGxJZk5vdEF2YWlsYWJsZSB9IGZyb20gXCIuL2ZzXCI7XG5pbXBvcnQgeyBTaW1wbGVEZXBlbmRlbmN5TWFwIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAaW50ZXJmYWNlIEFkZEF0dGFjaFBhcmFtc1xuICogQGRlc2NyaXB0aW9uIFBhcmFtZXRlcnMgZm9yIGFkZGluZyBhbiBhdHRhY2htZW50IHRvIGEgcmVwb3J0XG4gKiBAc3VtbWFyeSBJbnRlcmZhY2UgZm9yIGF0dGFjaG1lbnQgcGFyYW1ldGVyc1xuICogQG1lbWJlck9mIG1vZHVsZTpAZGVjYWYtdHMvdXRpbHNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGRBdHRhY2hQYXJhbXMge1xuICBhdHRhY2g6IHN0cmluZyB8IEJ1ZmZlcjtcbiAgZGVzY3JpcHRpb246IHN0cmluZyB8IG9iamVjdDtcbiAgY29udGV4dD86IGFueTtcbiAgYnVmZmVyRm9ybWF0Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBpbnRlcmZhY2UgQWRkTXNnUGFyYW1zXG4gKiBAZGVzY3JpcHRpb24gUGFyYW1ldGVycyBmb3IgYWRkaW5nIGEgbWVzc2FnZSB0byBhIHJlcG9ydFxuICogQHN1bW1hcnkgSW50ZXJmYWNlIGZvciBtZXNzYWdlIHBhcmFtZXRlcnNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6QGRlY2FmLXRzL3V0aWxzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkTXNnUGFyYW1zIHtcbiAgbWVzc2FnZTogc3RyaW5nIHwgb2JqZWN0O1xuICBjb250ZXh0PzogYW55O1xufVxuXG4vKipcbiAqIEB0eXBlZGVmIHsoXCJqc29uXCJ8XCJpbWFnZVwifFwidGV4dFwifFwibWRcIil9IFBheWxvYWRUeXBlXG4gKiBAZGVzY3JpcHRpb24gVHlwZXMgb2YgcGF5bG9hZHMgdGhhdCBjYW4gYmUgaGFuZGxlZFxuICogQHN1bW1hcnkgVW5pb24gdHlwZSBmb3IgcGF5bG9hZCB0eXBlc1xuICogQG1lbWJlck9mIG1vZHVsZTpAZGVjYWYtdHMvdXRpbHNcbiAqL1xuZXhwb3J0IHR5cGUgUGF5bG9hZFR5cGUgPSBcImpzb25cIiB8IFwiaW1hZ2VcIiB8IFwidGV4dFwiIHwgXCJtZFwiO1xuXG5leHBvcnQgY29uc3QgSmVzdFJlcG9ydGVyc1RlbXBQYXRoRW52S2V5ID0gXCJKRVNUX0hUTUxfUkVQT1JURVJTX1RFTVBfRElSX1BBVEhcIjtcblxuY29uc3QgZGVwZW5kZW5jaWVzID0gW1wiamVzdC1odG1sLXJlcG9ydGVyc1wiLCBcImpzb24ybWRcIiwgXCJjaGFydGpzLW5vZGUtY2FudmFzXCJdO1xuXG5hc3luYyBmdW5jdGlvbiBub3JtYWxpemVJbXBvcnQ8VD4oaW1wb3J0UHJvbWlzZTogUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICAvLyBDb21tb25KUydzIGBtb2R1bGUuZXhwb3J0c2AgaXMgd3JhcHBlZCBhcyBgZGVmYXVsdGAgaW4gRVNNb2R1bGUuXG4gIHJldHVybiBpbXBvcnRQcm9taXNlLnRoZW4oKG06IGFueSkgPT4gKG0uZGVmYXVsdCB8fCBtKSBhcyBUKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVGVzdCByZXBvcnRpbmcgdXRpbGl0eSBjbGFzcyBmb3IgbWFuYWdpbmcgdGVzdCByZXN1bHRzIGFuZCBldmlkZW5jZVxuICogQHN1bW1hcnkgQSBjb21wcmVoZW5zaXZlIHRlc3QgcmVwb3J0ZXIgdGhhdCBoYW5kbGVzIHZhcmlvdXMgdHlwZXMgb2YgdGVzdCBhcnRpZmFjdHMgaW5jbHVkaW5nIG1lc3NhZ2VzLFxuICogYXR0YWNobWVudHMsIGRhdGEsIGltYWdlcywgdGFibGVzLCBhbmQgZ3JhcGhzLiBJdCBwcm92aWRlcyBtZXRob2RzIHRvIHJlcG9ydCBhbmQgc3RvcmUgdGVzdCBldmlkZW5jZVxuICogaW4gZGlmZmVyZW50IGZvcm1hdHMgYW5kIG1hbmFnZXMgZGVwZW5kZW5jaWVzIGZvciByZXBvcnRpbmcgZnVuY3Rpb25hbGl0eS5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFR5cGUgb2YgZGF0YSBiZWluZyByZXBvcnRlZFxuICogQHBhcmFtIHtzdHJpbmd9IFt0ZXN0Q2FzZT1cInRlc3RzXCJdIC0gTmFtZSBvZiB0aGUgdGVzdCBjYXNlXG4gKiBAcGFyYW0ge3N0cmluZ30gW2Jhc2VQYXRoXSAtIEJhc2UgcGF0aCBmb3Igc3RvcmluZyB0ZXN0IHJlcG9ydHNcbiAqIEBjbGFzc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByZXBvcnRlciA9IG5ldyBUZXN0UmVwb3J0ZXIoJ2xvZ2luLXRlc3QnKTtcbiAqXG4gKiAvLyBSZXBvcnQgdGVzdCBtZXNzYWdlc1xuICogYXdhaXQgcmVwb3J0ZXIucmVwb3J0TWVzc2FnZSgnVGVzdCBTdGFydGVkJywgJ0xvZ2luIGZsb3cgaW5pdGlhdGVkJyk7XG4gKlxuICogLy8gUmVwb3J0IHRlc3QgZGF0YVxuICogYXdhaXQgcmVwb3J0ZXIucmVwb3J0RGF0YSgndXNlci1jcmVkZW50aWFscycsIHsgdXNlcm5hbWU6ICd0ZXN0JyB9LCAnanNvbicpO1xuICpcbiAqIC8vIFJlcG9ydCB0ZXN0IHJlc3VsdHMgdGFibGVcbiAqIGF3YWl0IHJlcG9ydGVyLnJlcG9ydFRhYmxlKCd0ZXN0LXJlc3VsdHMnLCB7XG4gKiAgIGhlYWRlcnM6IFsnU3RlcCcsICdTdGF0dXMnXSxcbiAqICAgcm93czogW1xuICogICAgIHsgU3RlcDogJ0xvZ2luJywgU3RhdHVzOiAnUGFzcycgfSxcbiAqICAgICB7IFN0ZXA6ICdWYWxpZGF0aW9uJywgU3RhdHVzOiAnUGFzcycgfVxuICogICBdXG4gKiB9KTtcbiAqXG4gKiAvLyBSZXBvcnQgdGVzdCBldmlkZW5jZVxuICogYXdhaXQgcmVwb3J0ZXIucmVwb3J0QXR0YWNobWVudCgnU2NyZWVuc2hvdCcsIHNjcmVlbnNob3RCdWZmZXIpO1xuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgVGVzdFJlcG9ydGVyXG4gKiAgIHBhcnRpY2lwYW50IEZpbGVTeXN0ZW1cbiAqICAgcGFydGljaXBhbnQgRGVwZW5kZW5jaWVzXG4gKlxuICogICBDbGllbnQtPj5UZXN0UmVwb3J0ZXI6IG5ldyBUZXN0UmVwb3J0ZXIodGVzdENhc2UsIGJhc2VQYXRoKVxuICogICBUZXN0UmVwb3J0ZXItPj5GaWxlU3lzdGVtOiBDcmVhdGUgcmVwb3J0IGRpcmVjdG9yeVxuICpcbiAqICAgYWx0IFJlcG9ydCBNZXNzYWdlXG4gKiAgICAgQ2xpZW50LT4+VGVzdFJlcG9ydGVyOiByZXBvcnRNZXNzYWdlKHRpdGxlLCBtZXNzYWdlKVxuICogICAgIFRlc3RSZXBvcnRlci0+PkRlcGVuZGVuY2llczogSW1wb3J0IGhlbHBlcnNcbiAqICAgICBUZXN0UmVwb3J0ZXItPj5GaWxlU3lzdGVtOiBTdG9yZSBtZXNzYWdlXG4gKiAgIGVsc2UgUmVwb3J0IERhdGFcbiAqICAgICBDbGllbnQtPj5UZXN0UmVwb3J0ZXI6IHJlcG9ydERhdGEocmVmZXJlbmNlLCBkYXRhLCB0eXBlKVxuICogICAgIFRlc3RSZXBvcnRlci0+PkRlcGVuZGVuY2llczogUHJvY2VzcyBkYXRhXG4gKiAgICAgVGVzdFJlcG9ydGVyLT4+RmlsZVN5c3RlbTogU3RvcmUgZm9ybWF0dGVkIGRhdGFcbiAqICAgZWxzZSBSZXBvcnQgVGFibGVcbiAqICAgICBDbGllbnQtPj5UZXN0UmVwb3J0ZXI6IHJlcG9ydFRhYmxlKHJlZmVyZW5jZSwgdGFibGVEZWYpXG4gKiAgICAgVGVzdFJlcG9ydGVyLT4+RGVwZW5kZW5jaWVzOiBDb252ZXJ0IHRvIE1EIGZvcm1hdFxuICogICAgIFRlc3RSZXBvcnRlci0+PkZpbGVTeXN0ZW06IFN0b3JlIHRhYmxlXG4gKiAgIGVuZFxuICovXG5leHBvcnQgY2xhc3MgVGVzdFJlcG9ydGVyIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGdW5jdGlvbiBmb3IgYWRkaW5nIG1lc3NhZ2VzIHRvIHRoZSB0ZXN0IHJlcG9ydFxuICAgKiBAc3VtbWFyeSBTdGF0aWMgaGFuZGxlciBmb3IgcHJvY2Vzc2luZyBhbmQgc3RvcmluZyB0ZXN0IG1lc3NhZ2VzXG4gICAqIEB0eXBlIHtmdW5jdGlvbihBZGRNc2dQYXJhbXMpOiBQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgcHJvdGVjdGVkIHN0YXRpYyBhZGRNc2dGdW5jdGlvbjogKHBhcmFtczogQWRkTXNnUGFyYW1zKSA9PiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRnVuY3Rpb24gZm9yIGFkZGluZyBhdHRhY2htZW50cyB0byB0aGUgdGVzdCByZXBvcnRcbiAgICogQHN1bW1hcnkgU3RhdGljIGhhbmRsZXIgZm9yIHByb2Nlc3NpbmcgYW5kIHN0b3JpbmcgdGVzdCBhdHRhY2htZW50c1xuICAgKiBAdHlwZSB7ZnVuY3Rpb24oQWRkQXR0YWNoUGFyYW1zKTogUHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIHByb3RlY3RlZCBzdGF0aWMgYWRkQXR0YWNoRnVuY3Rpb246IChcbiAgICBwYXJhbXM6IEFkZEF0dGFjaFBhcmFtc1xuICApID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNYXAgb2YgZGVwZW5kZW5jaWVzIHJlcXVpcmVkIGJ5IHRoZSByZXBvcnRlclxuICAgKiBAc3VtbWFyeSBTdG9yZXMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgZGVwZW5kZW5jaWVzXG4gICAqIEB0eXBlIHtTaW1wbGVEZXBlbmRlbmN5TWFwfVxuICAgKi9cbiAgcHJpdmF0ZSBkZXBzPzogU2ltcGxlRGVwZW5kZW5jeU1hcDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgdGVzdENhc2U6IHN0cmluZyA9IFwidGVzdHNcIixcbiAgICBwcm90ZWN0ZWQgYmFzZVBhdGggPSBwYXRoLmpvaW4oXG4gICAgICBwcm9jZXNzLmN3ZCgpLFxuICAgICAgXCJ3b3JrZG9jc1wiLFxuICAgICAgXCJyZXBvcnRzXCIsXG4gICAgICBcImV2aWRlbmNlc1wiXG4gICAgKVxuICApIHtcbiAgICB0aGlzLmJhc2VQYXRoID0gcGF0aC5qb2luKGJhc2VQYXRoLCB0aGlzLnRlc3RDYXNlKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmModGhpcy5iYXNlUGF0aCkpIHtcbiAgICAgIGZzLm1rZGlyU3luYyhiYXNlUGF0aCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbXBvcnRzIHJlcXVpcmVkIGhlbHBlciBmdW5jdGlvbnNcbiAgICogQHN1bW1hcnkgRW5zdXJlcyBhbGwgbmVjZXNzYXJ5IGRlcGVuZGVuY2llcyBhcmUgYXZhaWxhYmxlIGFuZCBpbXBvcnRzIGhlbHBlciBmdW5jdGlvbnNcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gaGVscGVycyBhcmUgaW1wb3J0ZWRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaW1wb3J0SGVscGVycygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmRlcHMgPSBhd2FpdCBpbnN0YWxsSWZOb3RBdmFpbGFibGUoW2RlcGVuZGVuY2llc1swXV0sIHRoaXMuZGVwcyk7XG4gICAgLy8gaWYgKCFwcm9jZXNzLmVudltKZXN0UmVwb3J0ZXJzVGVtcFBhdGhFbnZLZXldKVxuICAgIC8vICAgcHJvY2Vzcy5lbnZbSmVzdFJlcG9ydGVyc1RlbXBQYXRoRW52S2V5XSA9ICcuL3dvcmtkb2NzL3JlcG9ydHMnO1xuICAgIGNvbnN0IHsgYWRkTXNnLCBhZGRBdHRhY2ggfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChcbiAgICAgIGltcG9ydChgJHtkZXBlbmRlbmNpZXNbMF19L2hlbHBlcmApXG4gICAgKTtcbiAgICBUZXN0UmVwb3J0ZXIuYWRkTXNnRnVuY3Rpb24gPSBhZGRNc2c7XG4gICAgVGVzdFJlcG9ydGVyLmFkZEF0dGFjaEZ1bmN0aW9uID0gYWRkQXR0YWNoO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBvcnRzIGEgbWVzc2FnZSB0byB0aGUgdGVzdCByZXBvcnRcbiAgICogQHN1bW1hcnkgQWRkcyBhIGZvcm1hdHRlZCBtZXNzYWdlIHRvIHRoZSB0ZXN0IHJlcG9ydCB3aXRoIGFuIG9wdGlvbmFsIHRpdGxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZSAtIFRpdGxlIG9mIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgb2JqZWN0fSBtZXNzYWdlIC0gQ29udGVudCBvZiB0aGUgbWVzc2FnZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbWVzc2FnZSBpcyByZXBvcnRlZFxuICAgKi9cbiAgYXN5bmMgcmVwb3J0TWVzc2FnZSh0aXRsZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcgfCBvYmplY3QpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIVRlc3RSZXBvcnRlci5hZGRNc2dGdW5jdGlvbikgYXdhaXQgdGhpcy5pbXBvcnRIZWxwZXJzKCk7XG4gICAgY29uc3QgbXNnID0gYCR7dGl0bGV9JHttZXNzYWdlID8gYFxcbiR7bWVzc2FnZX1gIDogXCJcIn1gO1xuICAgIGF3YWl0IFRlc3RSZXBvcnRlci5hZGRNc2dGdW5jdGlvbih7IG1lc3NhZ2U6IG1zZyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVwb3J0cyBhbiBhdHRhY2htZW50IHRvIHRoZSB0ZXN0IHJlcG9ydFxuICAgKiBAc3VtbWFyeSBBZGRzIGEgZm9ybWF0dGVkIG1lc3NhZ2UgdG8gdGhlIHRlc3QgcmVwb3J0IHdpdGggYW4gb3B0aW9uYWwgdGl0bGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRpdGxlIC0gVGl0bGUgb2YgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBCdWZmZXJ9IGF0dGFjaG1lbnQgLSBDb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBtZXNzYWdlIGlzIHJlcG9ydGVkXG4gICAqL1xuICBhc3luYyByZXBvcnRBdHRhY2htZW50KFxuICAgIHRpdGxlOiBzdHJpbmcsXG4gICAgYXR0YWNobWVudDogc3RyaW5nIHwgQnVmZmVyXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghVGVzdFJlcG9ydGVyLmFkZEF0dGFjaEZ1bmN0aW9uKSBhd2FpdCB0aGlzLmltcG9ydEhlbHBlcnMoKTtcbiAgICBhd2FpdCBUZXN0UmVwb3J0ZXIuYWRkQXR0YWNoRnVuY3Rpb24oe1xuICAgICAgYXR0YWNoOiBhdHRhY2htZW50LFxuICAgICAgZGVzY3JpcHRpb246IHRpdGxlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBvcnRzIGRhdGEgd2l0aCBzcGVjaWZpZWQgdHlwZVxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgYW5kIHN0b3JlcyBkYXRhIGluIHRoZSB0ZXN0IHJlcG9ydCB3aXRoIGZvcm1hdHRpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlZmVyZW5jZSAtIFJlZmVyZW5jZSBpZGVudGlmaWVyIGZvciB0aGUgZGF0YVxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlciB8IG9iamVjdH0gZGF0YSAtIERhdGEgdG8gYmUgcmVwb3J0ZWRcbiAgICogQHBhcmFtIHtQYXlsb2FkVHlwZX0gdHlwZSAtIFR5cGUgb2YgdGhlIHBheWxvYWRcbiAgICogQHBhcmFtIHtib29sZWFufSBbdHJpbT1mYWxzZV0gLSBXaGV0aGVyIHRvIHRyaW0gdGhlIGRhdGFcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gZGF0YSBpcyByZXBvcnRlZFxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlcG9ydChcbiAgICByZWZlcmVuY2U6IHN0cmluZyxcbiAgICBkYXRhOiBzdHJpbmcgfCBudW1iZXIgfCBvYmplY3QgfCBCdWZmZXIsXG4gICAgdHlwZTogUGF5bG9hZFR5cGUsXG4gICAgdHJpbTogYm9vbGVhbiA9IGZhbHNlXG4gICkge1xuICAgIHRyeSB7XG4gICAgICBsZXQgYXR0YWNoRnVuY3Rpb246XG4gICAgICAgIHwgdHlwZW9mIHRoaXMucmVwb3J0TWVzc2FnZVxuICAgICAgICB8IHR5cGVvZiB0aGlzLnJlcG9ydEF0dGFjaG1lbnQgPSB0aGlzLnJlcG9ydE1lc3NhZ2UuYmluZCh0aGlzKTtcbiAgICAgIGxldCBleHRlbnNpb246IFwiLnBuZ1wiIHwgXCIudHh0XCIgfCBcIi5tZFwiIHwgXCIuanNvblwiID0gXCIudHh0XCI7XG5cbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIFwiaW1hZ2VcIjpcbiAgICAgICAgICBkYXRhID0gQnVmZmVyLmZyb20oZGF0YSBhcyBCdWZmZXIpO1xuICAgICAgICAgIGV4dGVuc2lvbiA9IFwiLnBuZ1wiO1xuICAgICAgICAgIGF0dGFjaEZ1bmN0aW9uID0gdGhpcy5yZXBvcnRBdHRhY2htZW50LmJpbmQodGhpcyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJqc29uXCI6XG4gICAgICAgICAgaWYgKHRyaW0pIHtcbiAgICAgICAgICAgIGlmICgoZGF0YSBhcyB7IHJlcXVlc3Q/OiB1bmtub3duIH0pLnJlcXVlc3QpXG4gICAgICAgICAgICAgIGRlbGV0ZSAoZGF0YSBhcyB7IHJlcXVlc3Q/OiB1bmtub3duIH0pW1wicmVxdWVzdFwiXTtcbiAgICAgICAgICAgIGlmICgoZGF0YSBhcyB7IGNvbmZpZz86IHVua25vd24gfSkuY29uZmlnKVxuICAgICAgICAgICAgICBkZWxldGUgKGRhdGEgYXMgeyBjb25maWc/OiB1bmtub3duIH0pW1wiY29uZmlnXCJdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkYXRhID0gSlNPTi5zdHJpbmdpZnkoZGF0YSwgbnVsbCwgMik7XG4gICAgICAgICAgZXh0ZW5zaW9uID0gXCIuanNvblwiO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwibWRcIjpcbiAgICAgICAgICBleHRlbnNpb24gPSBcIi5tZFwiO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwidGV4dFwiOlxuICAgICAgICAgIGV4dGVuc2lvbiA9IFwiLnR4dFwiO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGNvbnNvbGUubG9nKGBVbnN1cHBvcnRlZCB0eXBlICR7dHlwZX0uIGFzc3VtaW5nIHRleHRgKTtcbiAgICAgIH1cbiAgICAgIHJlZmVyZW5jZSA9IHJlZmVyZW5jZS5pbmNsdWRlcyhcIlxcblwiKVxuICAgICAgICA/IHJlZmVyZW5jZVxuICAgICAgICA6IGAke3JlZmVyZW5jZX0ke2V4dGVuc2lvbn1gO1xuICAgICAgYXdhaXQgYXR0YWNoRnVuY3Rpb24ocmVmZXJlbmNlLCBkYXRhIGFzIEJ1ZmZlciB8IHN0cmluZyk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ291bGQgbm90IHN0b3JlIGF0dGFjaCBhcnRpZmFjdCAke3JlZmVyZW5jZX0gdW5kZXIgdG8gdGVzdCByZXBvcnQgJHt0aGlzLnRlc3RDYXNlfSAtICR7ZX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlcG9ydERhdGEoXG4gICAgcmVmZXJlbmNlOiBzdHJpbmcsXG4gICAgZGF0YTogc3RyaW5nIHwgbnVtYmVyIHwgb2JqZWN0LFxuICAgIHR5cGU6IFBheWxvYWRUeXBlID0gXCJqc29uXCIsXG4gICAgdHJpbSA9IGZhbHNlXG4gICkge1xuICAgIHJldHVybiB0aGlzLnJlcG9ydChyZWZlcmVuY2UsIGRhdGEsIHR5cGUsIHRyaW0pO1xuICB9XG5cbiAgYXN5bmMgcmVwb3J0T2JqZWN0KHJlZmVyZW5jZTogc3RyaW5nLCBqc29uOiBvYmplY3QsIHRyaW0gPSBmYWxzZSkge1xuICAgIHJldHVybiB0aGlzLnJlcG9ydChyZWZlcmVuY2UsIGpzb24sIFwianNvblwiLCB0cmltKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVwb3J0cyBhIHRhYmxlIGluIG1hcmtkb3duIGZvcm1hdFxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhbmQgc3RvcmVzIGEgdGFibGUgZGVmaW5pdGlvbiBpbiBtYXJrZG93biBmb3JtYXRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlZmVyZW5jZSAtIFJlZmVyZW5jZSBpZGVudGlmaWVyIGZvciB0aGUgdGFibGVcbiAgICogQHBhcmFtIHtNZFRhYmxlRGVmaW5pdGlvbn0gdGFibGVEZWYgLSBUYWJsZSBkZWZpbml0aW9uIG9iamVjdFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0YWJsZSBpcyByZXBvcnRlZFxuICAgKi9cbiAgYXN5bmMgcmVwb3J0VGFibGUocmVmZXJlbmNlOiBzdHJpbmcsIHRhYmxlRGVmOiBNZFRhYmxlRGVmaW5pdGlvbikge1xuICAgIHRoaXMuZGVwcyA9IGF3YWl0IGluc3RhbGxJZk5vdEF2YWlsYWJsZShbZGVwZW5kZW5jaWVzWzFdXSwgdGhpcy5kZXBzKTtcbiAgICBsZXQgdHh0OiBzdHJpbmc7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGpzb24ybWQgPSBhd2FpdCBub3JtYWxpemVJbXBvcnQoaW1wb3J0KGAke2RlcGVuZGVuY2llc1sxXX1gKSk7XG4gICAgICB0eHQgPSBqc29uMm1kKHRhYmxlRGVmKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBjb252ZXJ0IEpTT04gdG8gTWFya2Rvd24gLSAke2V9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVwb3J0KHJlZmVyZW5jZSwgdHh0LCBcIm1kXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBvcnRzIGEgZ3JhcGggdXNpbmcgQ2hhcnQuanNcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIGFuZCBzdG9yZXMgYSBncmFwaCB2aXN1YWxpemF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWZlcmVuY2UgLSBSZWZlcmVuY2UgaWRlbnRpZmllciBmb3IgdGhlIGdyYXBoXG4gICAqIEBwYXJhbSB7YW55fSBjb25maWcgLSBDaGFydC5qcyBjb25maWd1cmF0aW9uIG9iamVjdFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBncmFwaCBpcyByZXBvcnRlZFxuICAgKi9cbiAgYXN5bmMgcmVwb3J0R3JhcGgocmVmZXJlbmNlOiBzdHJpbmcsIGNvbmZpZzogYW55KSB7XG4gICAgdGhpcy5kZXBzID0gYXdhaXQgaW5zdGFsbElmTm90QXZhaWxhYmxlKFtkZXBlbmRlbmNpZXNbMl1dLCB0aGlzLmRlcHMpO1xuICAgIGNvbnN0IHsgQ2hhcnRKU05vZGVDYW52YXMgfSA9IGF3YWl0IG5vcm1hbGl6ZUltcG9ydChcbiAgICAgIGltcG9ydChkZXBlbmRlbmNpZXNbMl0pXG4gICAgKTtcblxuICAgIGNvbnN0IHdpZHRoID0gNjAwOyAvL3B4XG4gICAgY29uc3QgaGVpZ2h0ID0gODAwOyAvL3B4XG4gICAgY29uc3QgYmFja2dyb3VuZENvbG91ciA9IFwid2hpdGVcIjsgLy8gVXNlcyBodHRwczovL3d3dy53M3NjaG9vbHMuY29tL3RhZ3MvY2FudmFzX2ZpbGxzdHlsZS5hc3BcbiAgICBjb25zdCBjaGFydEpTTm9kZUNhbnZhcyA9IG5ldyBDaGFydEpTTm9kZUNhbnZhcyh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIGJhY2tncm91bmRDb2xvdXIsXG4gICAgfSk7XG5cbiAgICBjb25zdCBpbWFnZSA9IGF3YWl0IGNoYXJ0SlNOb2RlQ2FudmFzLnJlbmRlclRvQnVmZmVyKGNvbmZpZyk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucmVwb3J0SW1hZ2UocmVmZXJlbmNlLCBpbWFnZSk7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBvcnRzIGFuIGltYWdlIHRvIHRoZSB0ZXN0IHJlcG9ydFxuICAgKiBAc3VtbWFyeSBTdG9yZXMgYW4gaW1hZ2UgYnVmZmVyIGluIHRoZSB0ZXN0IHJlcG9ydFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmVmZXJlbmNlIC0gUmVmZXJlbmNlIGlkZW50aWZpZXIgZm9yIHRoZSBpbWFnZVxuICAgKiBAcGFyYW0ge0J1ZmZlcn0gYnVmZmVyIC0gSW1hZ2UgZGF0YSBidWZmZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gaW1hZ2UgaXMgcmVwb3J0ZWRcbiAgICovXG4gIGFzeW5jIHJlcG9ydEltYWdlKHJlZmVyZW5jZTogc3RyaW5nLCBidWZmZXI6IEJ1ZmZlcikge1xuICAgIHJldHVybiB0aGlzLnJlcG9ydChyZWZlcmVuY2UsIGJ1ZmZlciwgXCJpbWFnZVwiKTtcbiAgfVxufVxuIl19