UNPKG

@honeybook/jest-stare

Version:

jest html reporter (results processor) to view HTML jest results, save raw JSON, and invoke multiple reporters

1,256 lines (1,239 loc) 1.08 MB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Constants = void 0; const chalk = require("chalk"); class Constants { } exports.Constants = Constants; Constants.NAME = "jest-stare"; Constants.LOGO = chalk.green("** ") + chalk.green("jest") + chalk.yellow("-") + chalk.red("stare"); Constants.SUFFIX = chalk.green("\t**"); Constants.DEFAULT_RESULTS_DIR = "./" + Constants.NAME; Constants.HTML_EXTENSION = ".html"; Constants.MAIN_HTML = "index" + Constants.HTML_EXTENSION; Constants.JEST_STARE_JS = "view.js"; Constants.REPORTER_WRITTING = " will write each completed run to "; Constants.RESULTS_RAW = "jest-results.json"; Constants.JEST_STARE_CSS = Constants.NAME + ".css"; Constants.TEMPLATE_HTML = "template.html"; Constants.CSS_DIR = "css/"; Constants.JS_DIR = "js/"; Constants.IMAGE_SNAPSHOT_DIFF_DIR = "image_snapshot_diff/"; Constants.TEST_RESULTS_PROCESSOR = "--testResultsProcessor"; Constants.REPORTERS = "--reporters"; Constants.LOG_MESSAGE = ": wrote output report to "; Constants.MERGE_MESSAGE = ": will merge with "; Constants.NO_INPUT = Constants.NAME + " was called without input results"; Constants.NO_CLI_INPUT = Constants.NAME + " CLI was called without input JSON file to read"; Constants.OVERRIDE_JEST_STARE_CONFIG = Constants.NAME + " was called with programmatic config"; },{"chalk":17}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Constants = void 0; class Constants { } exports.Constants = Constants; Constants.PASSED_LABEL = "Passed"; Constants.FAILED_LABEL = "Failed"; Constants.PENDING_LABEL = "Pending"; Constants.TODO_LABEL = "Todo"; Constants.OBSOLETE_SNAPSHOT_TEST_LABEL = "Obsolete Test"; Constants.CHANGED_LABEL = "Changed"; Constants.ADDED_LABEL = "Added"; Constants.UPDATED_SNAPSHOT_TEST_LABEL = "Updated Snapshot Test"; Constants.REMOVED_OBSOLETE_SNAPSHOT_FILE_LABEL = "Removed Obsolete Snapshot File"; Constants.OBSOLETE_SNAPSHOT_FILE_LABEL = "Obsolete File"; Constants.TEST_STATUS_PASS = "passed"; Constants.TEST_STATUS_FAIL = "failed"; Constants.TEST_STATUS_PEND = "pending"; Constants.TEST_STATUS_TODO = "todo"; Constants.OBSOLETE_SNAPSHOT_FILE = "#f8f9fa"; Constants.OBSOLETE_SNAPSHOT_TEST = "#ffc107"; Constants.ADDED = "#007bff"; Constants.UPDATED_SNAPSHOT_TEST = "#17a2b8"; Constants.REMOVED_OBSOLETE_SNAPSHOT_FILE = "#343a40"; Constants.CHANGED = "#6c757d"; Constants.PASS_RAW = "28a745"; Constants.PASS = "#" + Constants.PASS_RAW; Constants.FAIL_RAW = "dc3545"; Constants.FAIL = "#" + Constants.FAIL_RAW; Constants.PENDING_RAW = "ffc107"; Constants.PENDING = "#" + Constants.PENDING_RAW; Constants.TODO_RAW = "17a2b8"; Constants.TODO = "#" + Constants.TODO_RAW; Constants.PASSED_TEST = "passed-test"; Constants.FAILED_TEST = "failed-test"; Constants.PENDING_TEST = "pending-test"; Constants.TODO_TEST = "todo-test"; },{}],3:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Render = void 0; const $ = require("jquery"); const Switch_1 = require("./navigation/Switch"); const Constants_1 = require("./Constants"); const Status_1 = require("./charts/Status"); const Doughnut_1 = require("./charts/Doughnut"); const TestSuite_1 = require("./suites/TestSuite"); const TestSummary_1 = require("./summary/TestSummary"); class Render { static init() { document.addEventListener("DOMContentLoaded", () => { const config = JSON.parse($("#test-config").text()); const results = JSON.parse($("#test-results").text()); try { const globalConfig = JSON.parse($("#test-global-config").text()); const regex = new RegExp(Render.escapeRegExp(globalConfig.rootDir), "g"); results.testResults.forEach((testResult) => { testResult.testFilePath = testResult.testFilePath.replace(regex, ""); }); } catch (e) { } Render.show(results, config); }); } static escapeRegExp(str) { return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); } static show(results, config) { const labels = [Constants_1.Constants.PASSED_LABEL, Constants_1.Constants.FAILED_LABEL]; const backgroundColor = [Constants_1.Constants.PASS, Constants_1.Constants.FAIL]; Render.setReportTitle(config); Render.setReportHeadline(config); Render.setCoverageLink(config); if (!config.disableCharts) { const suitesData = Render.buildChartsData(results.numPassedTestSuites, results.numFailedTestSuites, results.numPendingTestSuites); Doughnut_1.Doughnut.createChart($("#test-suites-canvas"), suitesData); const testsChart = Render.buildChartsData(results.numPassedTests, results.numFailedTests, results.numPendingTests, results.numTodoTests); Doughnut_1.Doughnut.createChart($("#tests-canvas"), testsChart); let snapshotChart = Render.buildChartsData(results.snapshot.matched, results.snapshot.unmatched); snapshotChart = Render.addSnapshotChartData(results, snapshotChart); Doughnut_1.Doughnut.createChart($("#snapshots-canvas"), snapshotChart); } this.updateStatusArea(results); const tableHtml = TestSuite_1.TestSuite.create(results); $("#loading-info").hide(); $("#test-results").replaceWith($(tableHtml)); if (config.reportSummary) { const testSummary = TestSummary_1.TestSummary.create(results); $("#test-summary").replaceWith($(testSummary)); } if (config.hidePassing) { $("#lab-passoff-switch").prop("checked", false); $(`.${Constants_1.Constants.PASSED_TEST}`).hide(); } if (config.hideFailing) { $("#lab-failoff-switch").prop("checked", false); $(`.${Constants_1.Constants.FAILED_TEST}`).hide(); } if (config.hidePending) { $("#lab-pendingoff-switch").prop("checked", false); $(`.${Constants_1.Constants.PENDING_TEST}`).hide(); } if (config.hideTodo) { $("#lab-todooff-switch").prop("checked", false); $(`.${Constants_1.Constants.TODO_TEST}`).hide(); } if (config.hideFailing && config.hidePassing) { $(`.${Constants_1.Constants.FAILED_TEST}\\.${Constants_1.Constants.PASSED_TEST}`).hide(); } if (config.hidePending && config.hidePassing) { $(`.${Constants_1.Constants.PASSED_TEST}\\.${Constants_1.Constants.PENDING_TEST}`).hide(); } if (config.hideFailing && config.hidePending) { $(`.${Constants_1.Constants.FAILED_TEST}\\.${Constants_1.Constants.PENDING_TEST}`).hide(); } if (config.hideFailing && config.hidePassing && config.hidePending) { $(`.${Constants_1.Constants.FAILED_TEST}\\.${Constants_1.Constants.PASSED_TEST}\\.${Constants_1.Constants.PENDING_TEST}`).hide(); } const allCheckArray = new Array(); allCheckArray.push($("#lab-passoff-switch")); allCheckArray.push($("#lab-failoff-switch")); allCheckArray.push($("#lab-pendingoff-switch")); allCheckArray.push($("#lab-todooff-switch")); const allStylesArray = [Constants_1.Constants.PASSED_TEST, Constants_1.Constants.FAILED_TEST, Constants_1.Constants.PENDING_TEST, Constants_1.Constants.TODO_TEST]; const allSwitchArray = ["#lab-passoff-switch", "#lab-failoff-switch", "#lab-pendingoff-switch", "#lab-todooff-switch"]; allStylesArray.forEach((style, index) => { const checksMinusCurrentOne = allCheckArray.slice(); checksMinusCurrentOne.splice(index, 1); const stylesMinusCurrentOne = allStylesArray.slice(); stylesMinusCurrentOne.splice(index, 1); const switchElement = new Switch_1.Switch($(allSwitchArray[index]), $("." + style), style, checksMinusCurrentOne, stylesMinusCurrentOne); }); } static updateStatusArea(results) { Status_1.Status.setResultsClass($("#test-suites-results"), results.numPassedTestSuites, results.numTotalTestSuites - results.numPassedTestSuites - results.numPendingTestSuites); Status_1.Status.setResultsClass($("#tests-results"), results.numPassedTests, results.numTotalTests - results.numPassedTests - results.numPendingTests); Status_1.Status.setResultsClass($("#snapshots-results"), results.snapshot.matched, results.snapshot.unmatched); if (results.snapshot.added === 0 && results.snapshot.matched === 0 && results.snapshot.unchecked === 0 && results.snapshot.unmatched === 0 && results.snapshot.updated === 0) { $("#snapshots-group").hide(); } } static setReportTitle(config) { const tabTitle = config.reportTitle != null ? config.reportTitle : "jest-stare!"; document.title = tabTitle; } static setReportHeadline(config) { const brandTitle = config.reportHeadline != null ? config.reportHeadline : "jest-stare"; const a = $("#navbar-title"); a.text(brandTitle); } static setCoverageLink(config) { if (config.coverageLink != null) { const a = $("#coverage-link"); a.addClass("active"); a.removeClass("disabled"); a.attr("href", config.coverageLink); } } static buildChartsData(passedTests, failedTests, pendingTests, todoTests) { const chartData = { labels: [], backgroundColor: [], data: [], }; if (passedTests > 0) { chartData.labels.push(Constants_1.Constants.PASSED_LABEL); chartData.backgroundColor.push(Constants_1.Constants.PASS); chartData.data.push(passedTests); } if (failedTests > 0) { chartData.labels.push(Constants_1.Constants.FAILED_LABEL); chartData.backgroundColor.push(Constants_1.Constants.FAIL); chartData.data.push(failedTests); } if (pendingTests > 0) { chartData.labels.push(Constants_1.Constants.PENDING_LABEL); chartData.backgroundColor.push(Constants_1.Constants.PENDING); chartData.data.push(pendingTests); } if (todoTests > 0) { chartData.labels.push(Constants_1.Constants.TODO_LABEL); chartData.backgroundColor.push(Constants_1.Constants.TODO); chartData.data.push(todoTests); } return chartData; } static addSnapshotChartData(results, snapshotChart) { if (results.snapshot.filesAdded > 0) { snapshotChart.labels.push(Constants_1.Constants.ADDED_LABEL); snapshotChart.backgroundColor.push(Constants_1.Constants.ADDED); snapshotChart.data.push(results.snapshot.filesAdded); } if (results.snapshot.unchecked > 0) { if (results.snapshot.didUpdate) { snapshotChart.labels.push(Constants_1.Constants.UPDATED_SNAPSHOT_TEST_LABEL); snapshotChart.backgroundColor.push(Constants_1.Constants.UPDATED_SNAPSHOT_TEST); snapshotChart.data.push(results.snapshot.unchecked); } else { snapshotChart.labels.push(Constants_1.Constants.OBSOLETE_SNAPSHOT_TEST_LABEL); snapshotChart.backgroundColor.push(Constants_1.Constants.OBSOLETE_SNAPSHOT_TEST); snapshotChart.data.push(results.snapshot.unchecked); } } if (results.snapshot.updated > 0) { snapshotChart.labels.push(Constants_1.Constants.CHANGED_LABEL); snapshotChart.backgroundColor.push(Constants_1.Constants.CHANGED); snapshotChart.data.push(results.snapshot.updated); } if (results.snapshot.filesRemoved > 0) { if (results.snapshot.didUpdate) { snapshotChart.labels.push(Constants_1.Constants.REMOVED_OBSOLETE_SNAPSHOT_FILE_LABEL); snapshotChart.backgroundColor.push(Constants_1.Constants.REMOVED_OBSOLETE_SNAPSHOT_FILE); snapshotChart.data.push(results.snapshot.filesRemoved); } else { snapshotChart.labels.push(Constants_1.Constants.OBSOLETE_SNAPSHOT_FILE_LABEL); snapshotChart.backgroundColor.push(Constants_1.Constants.OBSOLETE_SNAPSHOT_FILE); snapshotChart.data.push(results.snapshot.filesRemoved); } } return snapshotChart; } } exports.Render = Render; },{"./Constants":2,"./charts/Doughnut":4,"./charts/Status":5,"./navigation/Switch":8,"./suites/TestSuite":9,"./summary/TestSummary":11,"jquery":41}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Doughnut = void 0; const chart_js_1 = require("chart.js"); class Doughnut { static createChart(canvas, chartData) { chart_js_1.Chart.register(...chart_js_1.registerables); const doughnut = "doughnut"; const config = { type: doughnut, data: { labels: chartData.labels, datasets: [ { backgroundColor: chartData.backgroundColor, data: chartData.data, } ] } }; Doughnut.buildCanvas(canvas.get(0), config); } static buildCanvas(canvas, config) { const doughnut = new chart_js_1.Chart(canvas, config); } } exports.Doughnut = Doughnut; },{"chart.js":20}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Status = void 0; class Status { static setResultsClass(statusElement, passed, failed) { const total = passed + failed; if (total === 0) { statusElement.addClass("list-group-item-info"); } else { if (passed === 0) { statusElement.addClass("list-group-item-danger"); } else if (passed === total) { statusElement.addClass("list-group-item-success"); } else { statusElement.addClass("list-group-item-warning"); } } } } exports.Status = Status; },{}],6:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImageSnapshotDifference = void 0; const $ = require("jquery"); const Constants_1 = require("../../processor/Constants"); const AnsiParser = require("ansi-parser"); class ImageSnapshotDifference { static containsDiff(jestFailureMessage) { let isFailure = false; for (const indicator of ImageSnapshotDifference.DIFF_INDICATOR) { if (jestFailureMessage.indexOf(indicator) >= 0) { isFailure = true; break; } } return isFailure; } static generate(jestFailureMessage) { const imageDiffFilename = ImageSnapshotDifference.parseDiffImageName(jestFailureMessage); const errorMessage = ImageSnapshotDifference.parseDiffError(jestFailureMessage); const diffDiv = document.createElement("div"); diffDiv.className = "image-snapshot-diff"; const diffMessage = document.createElement("span"); diffMessage.textContent = errorMessage; diffMessage.className = "text-muted"; diffDiv.appendChild(diffMessage); const diffImageLink = document.createElement("a"); diffImageLink.href = Constants_1.Constants.IMAGE_SNAPSHOT_DIFF_DIR + imageDiffFilename; diffDiv.appendChild(diffImageLink); const diffImage = document.createElement("img"); diffImage.src = Constants_1.Constants.IMAGE_SNAPSHOT_DIFF_DIR + imageDiffFilename; diffImageLink.appendChild(diffImage); return $(diffDiv).get(0); } static parseDiffImagePath(jestFailureMessage) { const match = ImageSnapshotDifference.DIFF_IMAGE.exec(jestFailureMessage); if (match) { return AnsiParser.removeAnsi(match[1]).trim(); } return null; } static parseDiffImageName(jestFailureMessage) { const path = ImageSnapshotDifference.parseDiffImagePath(jestFailureMessage); if (path) { return path.replace(/^.*[\\\/]/, ""); } } static parseDiffError(jestFailureMessage) { const match = ImageSnapshotDifference.DIFF_DETAILS.exec(jestFailureMessage); if (match) { return match[1]; } return null; } } exports.ImageSnapshotDifference = ImageSnapshotDifference; ImageSnapshotDifference.DIFF_INDICATOR = ["different from snapshot", "image to be the same size"]; ImageSnapshotDifference.DIFF_IMAGE = /See diff for details:\s*((.*?)\.png)/; ImageSnapshotDifference.DIFF_DETAILS = /Error: (.*)/; },{"../../processor/Constants":1,"ansi-parser":15,"jquery":41}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TestDifference = void 0; const diff2html = require("diff2html"); const $ = require("jquery"); class TestDifference { static containsDiff(jestFailureMessage) { return jestFailureMessage.search(TestDifference.DIFF_INDICATOR) >= 0; } static generate(jestFailureMessage) { const jestDiff = TestDifference.isolateDiff(jestFailureMessage); const diffjson = diff2html.parse(jestDiff); const diffHtml = diff2html.html(diffjson, { drawFileList: false, outputFormat: "side-by-side", matching: "lines" }); return $(diffHtml).get(0); } static isolateDiff(jestFailureMessage) { const beginIndex = jestFailureMessage.search(TestDifference.DIFF_INDICATOR); const endIndex = jestFailureMessage.search(TestDifference.DIFF_END_INDICATOR); let isolated = jestFailureMessage.substring(beginIndex, endIndex); let snapshotChanges = 0; let receivedChanges = 0; const changeLines = isolated.split(/\r?\n/g); for (const line of changeLines) { if (/^- /.test(line)) { snapshotChanges++; } else if (/^\+ /.test(line)) { receivedChanges++; } } const changesIndicator = `\n@@ -0,${snapshotChanges} +0,${receivedChanges} @@\n`; isolated = isolated.replace("- Snapshot", "--- Snapshot"); isolated = isolated.replace("+ Received", "+++ Received"); const lines = isolated.split(/\r?\n/g); lines.splice(2, 0, changesIndicator); return lines.join(`\n`); } } exports.TestDifference = TestDifference; TestDifference.DIFF_INDICATOR = /- Snapshot\s*(\-\s*[0-9]+)?\n\s*\+ Received\s*(\+\s*[0-9]+)?/g; TestDifference.DIFF_END_INDICATOR = /(at .*? \(.*?:[0-9]+:[0-9]+\)\s)/g; },{"diff2html":29,"jquery":41}],8:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Switch = void 0; class Switch { static mixStatus(currentStatus, oldStatus) { const statusArray = oldStatus.split(Switch.JOIN_CHAR); statusArray.push(currentStatus); const sortedUniqueStatusArray = [...new Set(statusArray)].sort(); return sortedUniqueStatusArray.join(Switch.JOIN_CHAR); } constructor(checkBox, divClass, divClassName, addtnlCheckBoxArray, addtnlClassNameArray) { this.activateFilters(checkBox, divClass, divClassName, addtnlCheckBoxArray, addtnlClassNameArray); } activateFilters(checkBox, divClass, divClassName, addtnlCheckBoxArray, addtnlClassNameArray) { checkBox.change(() => { if (checkBox.is(":checked")) { divClass.show(); if (addtnlCheckBoxArray != null) { addtnlCheckBoxArray.forEach((addtnlCheckBox, index) => { const mixedDualClass = Switch.mixStatus(addtnlClassNameArray[index], divClassName); const mixedClassDiv = $("." + mixedDualClass); mixedClassDiv.show(); }); const mixedClass = Switch.mixStatus(addtnlClassNameArray[0], divClassName); const allMixedClass = Switch.mixStatus(addtnlClassNameArray[1], mixedClass); const allMixedClassDiv = $("." + allMixedClass); allMixedClassDiv.show(); } } else { divClass.hide(); if (addtnlCheckBoxArray != null) { let allUnchecked = true; addtnlCheckBoxArray.forEach((addtnlCheckBox, index) => { if (!addtnlCheckBox.is(":checked")) { const mixedClass = Switch.mixStatus(addtnlClassNameArray[index], divClassName); const mixedClassDiv = $("." + mixedClass); mixedClassDiv.hide(); } else { allUnchecked = false; } }); if (allUnchecked) { const mixedClass = Switch.mixStatus(addtnlClassNameArray[0], divClassName); const allMixedClass = Switch.mixStatus(addtnlClassNameArray[1], mixedClass); const allMixedClassDiv = $("." + allMixedClass); allMixedClassDiv.hide(); } } } }); } } exports.Switch = Switch; Switch.JOIN_CHAR = "\\."; },{}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TestSuite = void 0; const Constants_1 = require("../Constants"); const Test_1 = require("../tests/Test"); class TestSuite { static create(results) { const elements = []; results.testResults.forEach((testResult) => { if (testResult.testResults == null) { console.error("Unexpected testResults field missing"); if (testResult.assertionResults != null) { console.warn("Attempting to use assertionResults: results are unpredictable"); testResult.testResults = testResult.assertionResults; } } let testStatusClass; const testSectionStatus = new Map(); for (const result of testResult.testResults) { testStatusClass = TestSuite.asignStatus(testStatusClass, result, testSectionStatus); } if (testStatusClass === undefined) { testStatusClass = Constants_1.Constants.PASSED_TEST; } const accordionCard = TestSuite.buildAccordionCard(testResult, testStatusClass); const divMap = new Map(); testResult.testResults.forEach((test) => { const element = Test_1.Test.create(test); if (test.ancestorTitles.length > 0) { test.ancestorTitles.forEach((title, index) => { const titlesCopy = test.ancestorTitles.slice(); titlesCopy.splice(index + 1); const key = titlesCopy.join(TestSuite.JOIN_CHAR); if (divMap.has(key)) { divMap.get(key).appendChild(element); } else { const nestDiv = document.createElement("div"); const statusClass = testSectionStatus.get(key) || Constants_1.Constants.PASSED_TEST; nestDiv.classList.add("my-3", "p-3", "bg-white", "rounded", "box-shadow", statusClass); const h6 = document.createElement("h6"); h6.classList.add("border-bottom", "pb-2", "mb-0", "display-6"); h6.textContent = title; nestDiv.appendChild(h6); nestDiv.appendChild(element); nestDiv.id = key; divMap.set(key, nestDiv); if (index === 0) { accordionCard .querySelector(".card-body") .appendChild(nestDiv); } else { titlesCopy.pop(); const parentKey = titlesCopy.join(TestSuite.JOIN_CHAR); divMap.get(parentKey).appendChild(nestDiv); } } }); } else { accordionCard .querySelector(".card-body") .appendChild(element); } }); elements.push(accordionCard); }); return elements; } static asignStatus(testStatusClass, result, testSectionStatus) { const currentStatus = TestSuite.getStatusClassFromJestStatus(result.status); if (!testStatusClass) { testStatusClass = currentStatus; } else if (testStatusClass !== currentStatus) { testStatusClass = TestSuite.mixStatus(currentStatus, testStatusClass); } else { testStatusClass = currentStatus; } for (let index = 0; index < result.ancestorTitles.length; index++) { const titlesCopy = result.ancestorTitles.slice(); titlesCopy.splice(index + 1); const key = titlesCopy.join(TestSuite.JOIN_CHAR); if (testSectionStatus.has(key)) { if (testStatusClass !== currentStatus) { testSectionStatus.set(key, TestSuite.mixStatus(currentStatus, testStatusClass)); } else { testSectionStatus.set(key, currentStatus); } } else { testSectionStatus.set(key, currentStatus); } } return testStatusClass; } static getStatusClassFromJestStatus(jestStatus) { if (jestStatus === Constants_1.Constants.TEST_STATUS_PEND) { return Constants_1.Constants.PENDING_TEST; } else if (jestStatus === Constants_1.Constants.TEST_STATUS_FAIL) { return Constants_1.Constants.FAILED_TEST; } else { return Constants_1.Constants.PASSED_TEST; } } static mixStatus(currentStatus, oldStatus) { const statusArray = oldStatus.split(TestSuite.JOIN_CHAR); statusArray.push(currentStatus); const sortedUniqueStatusArray = [...new Set(statusArray)].sort(); return sortedUniqueStatusArray.join(TestSuite.JOIN_CHAR); } static buildAccordionCard(testResult, testStatusClass) { const accordionCard = document.createElement("div"); accordionCard.classList.add("my-3", "p-3", "bg-white", "rounded", "box-shadow", "card", testStatusClass); const cardHeader = TestSuite.buildAccordionCardHeader(testResult.testFilePath, testResult.numPassingTests, testResult.numFailingTests, testResult.numPendingTests, testResult.numTodoTests); accordionCard.appendChild(cardHeader); const cardBody = TestSuite.buildAccordionCardBody(testResult.testFilePath); accordionCard.appendChild(cardBody); return accordionCard; } static buildAccordionCardHeader(testFilePath, passCount, failCount, pendingCount, todoCount) { const fileName = TestSuite.sanitizeFilePath(testFilePath); const cardHeader = document.createElement("div"); cardHeader.classList.add("card-header"); cardHeader.classList.add("text-center"); cardHeader.id = `${fileName}_header`; const h5 = document.createElement("h5"); h5.classList.add("border-bottom", "pb-2", "mb-0", "display-5"); const btn = document.createElement("button"); btn.style.userSelect = "text"; btn.classList.add("btn", "btn-block"); btn.setAttribute("data-bs-toggle", "collapse"); btn.setAttribute("data-bs-target", `#${fileName}_detail`); btn.textContent = testFilePath; const resultCounts = document.createElement("div"); resultCounts.style.userSelect = "none"; const passBadge = document.createElement("span"); passBadge.classList.add("badge", "bg-success", "border"); passBadge.textContent = passCount.toString(); resultCounts.appendChild(passBadge); const failBadge = document.createElement("span"); failBadge.classList.add("badge", "bg-danger", "border"); failBadge.textContent = failCount.toString(); resultCounts.appendChild(failBadge); const skipBadge = document.createElement("span"); skipBadge.classList.add("badge", "bg-warning", "border"); skipBadge.textContent = pendingCount.toString(); resultCounts.appendChild(skipBadge); const todoBadge = document.createElement("span"); todoBadge.classList.add("badge", "bg-info", "border"); todoBadge.textContent = todoCount.toString(); resultCounts.appendChild(todoBadge); btn.appendChild(resultCounts); h5.appendChild(btn); cardHeader.appendChild(h5); return cardHeader; } static buildAccordionCardBody(testFilePath) { const fileName = TestSuite.sanitizeFilePath(testFilePath); const cardContainer = document.createElement("div"); cardContainer.classList.add("collapse"); cardContainer.setAttribute("data-parent", "#accordion"); cardContainer.id = `${fileName}_detail`; const cardBody = document.createElement("div"); cardBody.classList.add("card-body"); cardContainer.appendChild(cardBody); return cardContainer; } static sanitizeFilePath(testFilePath) { return testFilePath.replace(/(\/)|\\|(:)|(\s)|\.|(@)/g, "_"); } } exports.TestSuite = TestSuite; TestSuite.JOIN_CHAR = "."; },{"../Constants":2,"../tests/Test":12}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Test = void 0; const Constants_1 = require("../Constants"); class Test { static create(innerTestResult) { const containerDiv = document.createElement("div"); const anchor = document.createElement("a"); anchor.href = "#" + innerTestResult.title.replace(/\s+/g, "-").toLowerCase(); const testName = document.createElement("span"); testName.textContent = innerTestResult.title; anchor.appendChild(Test.getSimbolSpanFromStatus(innerTestResult.status)); anchor.appendChild(testName); containerDiv.appendChild(anchor); return containerDiv; } static getSimbolSpanFromStatus(status) { const span = document.createElement("span"); span.classList.add("summary-test-label", "test"); if (status === Constants_1.Constants.TEST_STATUS_PASS) { span.textContent = "✓"; span.classList.add("pass"); } if (status === Constants_1.Constants.TEST_STATUS_PEND) { span.textContent = "O"; span.classList.add("pending"); } if (status === Constants_1.Constants.TEST_STATUS_FAIL) { span.textContent = "X"; span.classList.add("fail"); } return span; } } exports.Test = Test; },{"../Constants":2}],11:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TestSummary = void 0; const Test_1 = require("./Test"); class TestSummary { static create(results) { const elements = []; const div = document.createElement("div"); div.classList.add("my-3", "p-3", "bg-white", "rounded", "box-shadow", "summary"); const h5 = document.createElement("h5"); h5.classList.add("border-bottom", "pb-2", "display-5", "summary-title"); h5.textContent = "Summary"; div.appendChild(h5); div.id = "test-summary"; elements.push(div); results.testResults.forEach((testResult) => { if (testResult.testResults == null) { console.error("Unexpected testResults field missing"); if (testResult.assertionResults != null) { console.warn("Attempting to use assertionResults: results are unpredictable"); testResult.testResults = testResult.assertionResults; } } const divMap = new Map(); const testTitleDiv = document.createElement("div"); testTitleDiv.classList.add("summary-test-suite"); const testFileLink = document.createElement("a"); const passingTestsCount = "[" + testResult.numPassingTests + "/" + testResult.testResults.length + "]"; const isPass = (testResult.testResults.length - (testResult.numPassingTests + testResult.numPendingTests)) === 0; const testStatus = document.createElement("strong"); testStatus.classList.add("summary-test-label"); if (isPass) { testStatus.classList.add("pass"); testStatus.textContent = "PASS"; } else { testStatus.classList.add("fail"); testStatus.textContent = "FAIL"; } const testFileLine = document.createElement("strong"); testFileLine.classList.add("summary-test-label", "path"); testFileLine.textContent = testResult.testFilePath; const testCount = document.createElement("strong"); testCount.classList.add("summary-test-count"); testCount.textContent = passingTestsCount; testFileLink.href = "#" + testResult.testFilePath; testFileLink.appendChild(testStatus); testFileLink.appendChild(testFileLine); testFileLink.appendChild(testCount); testTitleDiv.appendChild(testFileLink); div.appendChild(testTitleDiv); testResult.testResults.forEach((test) => { const testDetail = Test_1.Test.create(test); div.appendChild(testDetail); }); }); return elements; } } exports.TestSummary = TestSummary; TestSummary.JOIN_CHAR = "."; },{"./Test":10}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Test = void 0; const Constants_1 = require("../Constants"); const AnsiParser = require("ansi-parser"); const TestDifference_1 = require("../diff/TestDifference"); const ImageSnapshotDifference_1 = require("../diff/ImageSnapshotDifference"); class Test { static create(innerTestResult) { let color = Constants_1.Constants.PASS_RAW; let testStatusClass = Constants_1.Constants.PASSED_TEST; let failed = false; switch (innerTestResult.status) { case Constants_1.Constants.TEST_STATUS_FAIL: color = Constants_1.Constants.FAIL_RAW; testStatusClass = Constants_1.Constants.FAILED_TEST; failed = true; break; case Constants_1.Constants.TEST_STATUS_PEND: color = Constants_1.Constants.PENDING_RAW; testStatusClass = Constants_1.Constants.PENDING_TEST; break; case Constants_1.Constants.TEST_STATUS_TODO: color = Constants_1.Constants.TODO_RAW; testStatusClass = Constants_1.Constants.TODO_TEST; break; case Constants_1.Constants.TEST_STATUS_PASS: break; default: break; } const firstDiv = document.createElement("div"); firstDiv.classList.add("media", "text-muted", "pt-3", testStatusClass); const img = document.createElement("img"); img.classList.add("mr-2", "rounded"); img.alt = ""; img.setAttribute("data-src", "holder.js/32x32?theme=thumb&bg=" + color + "&fg=" + color + "&size=1"); firstDiv.appendChild(img); const secondDiv = document.createElement("div"); secondDiv.classList.add("media-body", "pb-3", "mb-0", "small", "lh-125", "border-bottom", "overflow-auto"); firstDiv.appendChild(secondDiv); const thirdDiv = document.createElement("div"); thirdDiv.classList.add("d-flex", "justify-content-between", "align-items-center", "w-100"); secondDiv.appendChild(thirdDiv); const strong = document.createElement("strong"); strong.classList.add("text-gray-dark"); strong.textContent = innerTestResult.title; const titleId = innerTestResult.title .replace(/\s+/g, "-") .toLowerCase(); const diffId = titleId + "-diff"; thirdDiv.appendChild(strong); const small = document.createElement("small"); small.classList.add("d-block", "text-right", "mt-3"); const conversionValu = 1000; small.textContent = innerTestResult.duration / conversionValu + "s"; thirdDiv.appendChild(small); const span = document.createElement("span"); span.classList.add("d-block", "mb-2"); span.textContent = innerTestResult.status; secondDiv.appendChild(span); if (failed) { const failMessage = AnsiParser.removeAnsi(innerTestResult.failureMessages[0]); const failMessageSplit = failMessage.split("\n"); let show = true; if (failMessage.search(TestDifference_1.TestDifference.DIFF_INDICATOR) >= 0) { const diffHtml = TestDifference_1.TestDifference.generate(failMessage); secondDiv.appendChild(diffHtml); show = false; } if (ImageSnapshotDifference_1.ImageSnapshotDifference.containsDiff(failMessage)) { const diffHtml = ImageSnapshotDifference_1.ImageSnapshotDifference.generate(failMessage); secondDiv.appendChild(diffHtml); show = false; } const collapseDiv = document.createElement("div"); collapseDiv.classList.add("d-flex", "justify-content-between", "align-items-center", "w-100"); const worthlessDiv = document.createElement("div"); secondDiv.appendChild(collapseDiv); collapseDiv.appendChild(worthlessDiv); const button = document.createElement("button"); button.classList.add("btn", "btn-light", "btn-sm"); button.type = "button"; button.setAttribute("data-bs-toggle", "collapse"); button.setAttribute("data-bs-target", "#" + diffId); button.setAttribute("aria-expanded", "false"); button.setAttribute("aria-controls", diffId); button.textContent = "raw"; collapseDiv.appendChild(button); const pre = document.createElement("pre"); secondDiv.appendChild(pre); pre.classList.add("collapse"); if (show) { pre.classList.add("show"); } pre.id = diffId; const code = document.createElement("code"); pre.appendChild(code); if (innerTestResult.domSnapshot) { const iframe = createIframeForDOMSnapshot(innerTestResult.domSnapshot); const iframeVisibilityCheckbox = createIframeVisibilityCheckbox(iframe); secondDiv.appendChild(iframeVisibilityCheckbox); secondDiv.appendChild(iframe); } failMessageSplit.forEach((entry, index) => { const codeSpan = document.createElement("span"); if (entry[0] === "+") { codeSpan.setAttribute("style", "color:" + Constants_1.Constants.PASS); codeSpan.textContent = entry; } else if (entry[0] === "-") { codeSpan.setAttribute("style", "color:" + Constants_1.Constants.FAIL); codeSpan.textContent = entry; } else { codeSpan.textContent = entry; } const spanDiv = document.createElement("div"); spanDiv.appendChild(codeSpan); code.appendChild(spanDiv); }); } firstDiv.id = titleId; return firstDiv; } } exports.Test = Test; function createIframeForDOMSnapshot(content) { const iframe = document.createElement("iframe"); Object.assign(iframe.style, { width: "100%", height: "1100px", border: "1px solid black", }); iframe.onload = () => { var _a; const doc = iframe.contentDocument || ((_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document); if (doc) { doc.open(); doc.write(content); doc.close(); } }; return iframe; } function createIframeVisibilityCheckbox(iframe) { const checkboxId = `iframe-visibility"_${Math.random() .toString(36) .substring(7)}`; const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.id = checkboxId; checkbox.checked = true; checkbox.addEventListener("change", (event) => { const checked = event.target.checked; iframe.style.display = checked ? "" : "none"; }); Object.assign(checkbox.style, { cursor: "pointer", }); const label = document.createElement("label"); label.htmlFor = checkboxId; label.textContent = "Show DOM Snapshot"; Object.assign(label.style, { cursor: "pointer", }); const container = document.createElement("div"); container.appendChild(checkbox); container.appendChild(label); Object.assign(container.style, { display: "flex", gap: "4px", marginBottom: "6px", }); return container; } },{"../Constants":2,"../diff/ImageSnapshotDifference":6,"../diff/TestDifference":7,"ansi-parser":15}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Render_1 = require("./Render"); Render_1.Render.init(); },{"./Render":3}],14:[function(require,module,exports){ /*! * @kurkle/color v0.3.4 * https://github.com/kurkle/color#readme * (c) 2024 Jukka Kurkela * Released under the MIT License */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["@kurkle/color"] = factory()); })(this, (function () { 'use strict'; function round(v) { return v + 0.5 | 0; } const lim = (v, l, h) => Math.max(Math.min(v, h), l); function p2b(v) { return lim(round(v * 2.55), 0, 255); } function b2p(v) { return lim(round(v / 2.55), 0, 100); } function n2b(v) { return lim(round(v * 255), 0, 255); } function b2n(v) { return lim(round(v / 2.55) / 100, 0, 1); } function n2p(v) { return lim(round(v * 100), 0, 100); } const map$1 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15}; const hex = [...'0123456789ABCDEF']; const h1 = b => hex[b & 0xF]; const h2 = b => hex[(b & 0xF0) >> 4] + hex[b & 0xF]; const eq = b => ((b & 0xF0) >> 4) === (b & 0xF); const isShort = v => eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a); function hexParse(str) { var len = str.length; var ret; if (str[0] === '#') { if (len === 4 || len === 5) { ret = { r: 255 & map$1[str[1]] * 17, g: 255 & map$1[str[2]] * 17, b: 255 & map$1[str[3]] * 17, a: len === 5 ? map$1[str[4]] * 17 : 255 }; } else if (len === 7 || len === 9) { ret = { r: map$1[str[1]] << 4 | map$1[str[2]], g: map$1[str[3]] << 4 | map$1[str[4]], b: map$1[str[5]] << 4 | map$1[str[6]], a: len === 9 ? (map$1[str[7]] << 4 | map$1[str[8]]) : 255 }; } } return ret; } const alpha = (a, f) => a < 255 ? f(a) : ''; function hexString(v) { var f = isShort(v) ? h1 : h2; return v ? '#' + f(v.r) + f(v.g) + f(v.b) + alpha(v.a, f) : undefined; } const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/; function hsl2rgbn(h, s, l) { const a = s * Math.min(l, 1 - l); const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); return [f(0), f(8), f(4)]; } function hsv2rgbn(h, s, v) { const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0); return [f(5), f(3), f(1)]; } function hwb2rgbn(h, w, b) { const rgb = hsl2rgbn(h, 1, 0.5); let i; if (w + b > 1) { i = 1 / (w + b); w *= i; b *= i; } for (i = 0; i < 3; i++) { rgb[i] *= 1 - w - b; rgb[i] += w; } return rgb; } function hueValue(r, g, b, d, max) { if (r === max) { return ((g - b) / d) + (g < b ? 6 : 0); } if (g === max) { return (b - r) / d + 2; } return (r - g) / d + 4; } function rgb2hsl(v) { const range = 255; const r = v.r / range; const g = v.g / range; const b = v.b / range; const max = Math.max(r, g, b); const min = Math.min(r, g, b); const l = (max + min) / 2; let h, s, d; if (max !== min) { d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); h = hueValue(r, g, b, d, max); h = h * 60 + 0.5; } return [h | 0, s || 0, l]; } function calln(f, a, b, c) { return ( Array.isArray(a) ? f(a[0], a[1], a[2]) : f(a, b, c) ).map(n2b); } function hsl2rgb(h, s, l) { return calln(hsl2rgbn, h, s, l); } function hwb2rgb(h, w, b) { return calln(hwb2rgbn, h, w, b); } function hsv2rgb(h, s, v) { return calln(hsv2rgbn, h, s, v); } function hue(h) { return (h % 360 + 360) % 360; } function hueParse(str) { const m = HUE_RE.exec(str); let a = 255; let v; if (!m) { return; } if (m[5] !== v) { a = m[6] ? p2b(+m[5]) : n2b(+m[5]); } const h = hue(+m[2]); const p1 = +m[3] / 100; const p2 = +m[4] / 100; if (m[1] === 'hwb') { v = hwb2rgb(h, p1, p2); } else if (m[1] === 'hsv') { v = hsv2rgb(h, p1, p2); } else { v = hsl2rgb(h, p1, p2); } return { r: v[0], g: v[1], b: v[2], a: a }; } function rotate(v, deg) { var h = rgb2hsl(v); h[0] = hue(h[0] + deg); h = hsl2rgb(h); v.r = h[0]; v.g = h[1]; v.b = h[2]; } function hslString(v) { if (!v) { return; } const a = rgb2hsl(v); const h = a[0]; const s = n2p(a[1]); const l = n2p(a[2]); return v.a < 255 ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})` : `hsl(${h}, ${s}%, ${l}%)`; } const map = { x: 'dark', Z: 'light', Y: 're', X: 'blu', W: 'gr', V: 'medium', U: 'slate', A: 'ee', T: 'ol', S: 'or', B: 'ra', C: 'lateg', D: 'ights', R: 'in', Q: 'turquois', E: 'hi', P: 'ro', O: 'al', N: 'le', M: 'de', L: 'yello', F: 'en', K: 'ch', G: 'arks', H: 'ea', I: 'ightg', J: 'wh' }; const names$1 = { OiceXe: 'f0f8ff', antiquewEte: 'faebd7', aqua: 'ffff', aquamarRe: '7fffd4', azuY: 'f0ffff', beige: 'f5f5dc', bisque: 'ffe4c4', black: '0', blanKedOmond: 'ffebcd', Xe: 'ff', XeviTet: '8a2be2', bPwn: 'a52a2a', burlywood: 'deb887', caMtXe: '5f9ea0', KartYuse: '7fff00', KocTate: 'd2691e', cSO: 'ff7f50', cSnflowerXe: '6495ed', cSnsilk: 'fff8dc', crimson: 'dc143c', cyan: 'ffff', xXe: '8b', xcyan: '8b8b', xgTMnPd: 'b8860b', xWay: 'a9a9a9', xgYF: '6400', xgYy: 'a9a9a9', xkhaki: 'bdb76b', xmagFta: '8b008b', xTivegYF: '556b2f', xSange: 'ff8c00', xScEd: '9932cc', xYd: '8b0000', xsOmon: 'e9967a', xsHgYF: '8fbc8f', xUXe: '483d8b', xUWay: '2f4f4f', xUgYy: '2f4f4f', xQe: 'ced1', xviTet: '9400d3', dAppRk: 'ff1493', dApskyXe: 'bfff', dimWay: '696969', dimgYy: '696969', dodgerXe: '1e90ff', fiYbrick: 'b22222', flSOwEte: 'fffaf0', foYstWAn: '228b22', fuKsia: 'ff00ff', gaRsbSo: 'dcdcdc', ghostwEte: 'f8f8ff', gTd: 'ffd700', gTMnPd: 'daa520', Way: '808080', gYF: '8000', gYFLw: 'adff2f', gYy: '808080', honeyMw: 'f0fff0', hotpRk: 'ff69b4', RdianYd: 'cd5c5c', Rdigo: '4b0082', ivSy: 'fffff0', khaki: 'f0e68c', lavFMr: 'e6e6fa', lavFMrXsh: 'fff0f5', lawngYF: '7cfc00', NmoncEffon: 'fffacd', ZXe: 'add8e6', ZcSO: 'f08080', Zcyan: 'e0ffff', ZgTMnPdLw: 'fafad2', ZWay: 'd3d3d3', ZgYF: '90ee90', ZgYy: 'd3d3d3', ZpRk: 'ffb6c1', ZsOmon: 'ffa07a', ZsHgYF: '20b2aa', ZskyXe: '87cefa', ZUWay: '778899', ZUgYy: '778899', ZstAlXe: 'b0c4de', ZLw: 'ffffe0', lime: 'ff00', limegYF: '32cd32', lRF: