jest-html-reporter 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -92,6 +92,7 @@ or via adding a key to `package.json` named "jest-html-reporter":
92
92
  | **`customScriptPath`** | `string` | `null` | Path to an external script file injected into the report. |
93
93
  | **`dateFormat`** | `string` | `yyyy-mm-dd HH:MM:ss` | Date format for timestamps. See [documentation](https://github.com/Hargne/jest-html-reporter/wiki/Date-Format) for available formats. |
94
94
  | **`executionTimeWarningThreshold`** | `number` | `5` | Warn if a test suite exceeds this execution time (in seconds). |
95
+ | **`hideConsoleLogOrigin`** | `boolean` | `true` | Hide `console.log` origin (stack trace) in the report (**requires** `--verbose=false`). |
95
96
  | **`includeConsoleLog`** | `boolean` | `false` | Include `console.log` outputs in the report (**requires** `--verbose=false`). |
96
97
  | **`includeFailureMsg`** | `boolean` | `false` | Show detailed error messages for failed tests. |
97
98
  | **`includeStackTrace`** | `boolean` | `true` | Show stack traces for failed tests. |
@@ -104,6 +105,7 @@ or via adding a key to `package.json` named "jest-html-reporter":
104
105
  | **`statusIgnoreFilter`** | `string` | `null` | **Comma-separated** list of statuses to exclude: `"passed"`, `"pending"`, `"failed"`. |
105
106
  | **`styleOverridePath`** | `string` | `null` | Path to a CSS file to override default styles. |
106
107
  | **`useCssFile`** | `boolean` | `false` | Link to the CSS file instead of inlining styles. |
108
+ | **`theme`** | `string` | `defaultTheme` | Theme that you are able to set to report (defaultTheme or darkTheme) |
107
109
 
108
110
  ## Continuous Integration
109
111
 
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("dateformat"),t=require("fs"),s=require("mkdirp"),i=require("path"),n=require("xmlbuilder"),o=require("strip-ansi");function a(e,t){const s={default:"%s",success:"%s",error:"%s"},i=s[e]?s[e]:s.default,n=`jest-html-reporter >> ${t}`;return void 0===process.env.JEST_WORKER_ID&&console.log(i,n),{logColor:i,logMsg:n}}function r(e){return a("error",e instanceof Error?e.message:"An error occurred")}function l(e){if("string"!=typeof e)throw new TypeError("Input must be a string");return o(e).replace(/[^\t\n\r\x20-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/gu,"")}function u(e,t){if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Both rootDir and filePath must be strings.");return t.startsWith("<rootDir>")?i.resolve(e,i.normalize(`./${t.slice(9)}`)):t}function c(e,t,s=!1){return!s&&e<t||s&&e>t?-1:!s&&e>t||s&&e<t?1:0}function d(e){return"boolean"==typeof e?e:"string"==typeof e&&"true"===e}function h(e){if("string"==typeof e)return e}const g=["pending","failed","passed"];const f=(e,t)=>{const s={pending:[],failed:[],passed:[]},i=[];e.forEach((e=>{const t=[],n=[],o=[],a=[];e.testResults.forEach((e=>{"pending"===e.status?t.push(e):"failed"===e.status?n.push(e):"passed"===e.status?o.push(e):a.push(e)})),t.length>0&&s.pending.push({...e,testResults:t}),n.length>0&&s.failed.push({...e,testResults:n}),o.length>0&&s.passed.push({...e,testResults:o}),a.length>0&&i.push({...e,testResults:a})}));const n=[...t||[],...["pending","failed","passed"].filter((e=>!(t||[]).includes(e)))],o=Object.entries(s).sort((([e],[t])=>n.indexOf(e)-n.indexOf(t))).flatMap((([,e])=>e));return[...o,...i]},p=e=>(e&&e.sort(((e,t)=>t.perfStats.end-t.perfStats.start-(e.perfStats.end-e.perfStats.start))),e),m=e=>(e&&e.sort(((e,t)=>e.perfStats.end-e.perfStats.start-(t.perfStats.end-t.perfStats.start))),e),y=e=>{if(e){const t=e.sort(((e,t)=>c(e.testFilePath,t.testFilePath,!0)));return t.forEach((e=>{e.testResults.sort(((e,t)=>c(e.ancestorTitles.join(" "),t.ancestorTitles.join(" "),!0))),e.testResults.sort(((e,t)=>c(e.title,t.title,!0)))})),t}return e},v=e=>{if(e){const t=e.sort(((e,t)=>c(e.testFilePath,t.testFilePath)));return t.forEach((e=>{e.testResults.sort(((e,t)=>c(e.ancestorTitles.join(" "),t.ancestorTitles.join(" ")))),e.testResults.sort(((e,t)=>c(e.title,t.title)))})),t}return e},S={additionalInformation:[],append:!1,boilerplate:void 0,collapseSuitesByDefault:!1,customScriptPath:void 0,dateFormat:"yyyy-mm-dd HH:MM:ss",executionTimeWarningThreshold:5,includeConsoleLog:!1,includeFailureMsg:!1,includeStackTrace:!0,includeSuiteFailure:!1,includeObsoleteSnapshots:!1,logo:void 0,outputPath:i.join(process.cwd(),"test-report.html"),pageTitle:"Test Report",sort:void 0,statusIgnoreFilter:void 0,styleOverridePath:void 0,theme:"defaultTheme",useCssFile:!1};function T(e){try{if(t.existsSync(e))return JSON.parse(t.readFileSync(e,"utf8"))}catch{return{}}return{}}const C={additionalInformation:(F=function(e){return"object"==typeof e&&null!==e&&"string"==typeof e.label&&"string"==typeof e.value},e=>Array.isArray(e)?e.filter(F):[]),append:d,boilerplate:h,collapseSuitesByDefault:d,customScriptPath:h,dateFormat:h,executionTimeWarningThreshold:function(e){return"number"==typeof e?e:"string"==typeof e?Number(e):NaN},includeConsoleLog:d,includeFailureMsg:d,includeStackTrace:d,includeSuiteFailure:d,includeObsoleteSnapshots:d,logo:h,outputPath:h,pageTitle:h,sort:h,statusIgnoreFilter:h,styleOverridePath:h,theme:h,useCssFile:d};var F;function D(e){return"object"!=typeof e||null===e?{}:Object.keys(S).reduce(((t,s)=>{const i=C[s];if(i&&"function"==typeof i&&s in e){const n=i(e[s]);if(void 0!==n)return{...t,[s]:n}}return t}),{})}class b{testData;consoleLogList;jestConfig;config;constructor(e){this.testData=e.testData,this.jestConfig=e.jestConfig,this.consoleLogList=e.consoleLogs||[],this.config=function(e){const t=Object.keys(S).reduce(((e,t)=>{const s=function(e){return`JEST_HTML_REPORTER_${e.replace(/([a-z])([A-Z])/g,"$1_$2").toUpperCase()}`}(t);return void 0!==process.env[s]?{...e,[t]:process.env[s]}:e}),{}),s=T(i.join(process.cwd(),"jesthtmlreporter.config.json")),n=T(i.join(process.cwd(),"package.json"))["jest-html-reporter"]||{};return{...S,...D(n),...D(s),...D(e),...D(t)}}(e.options)}async generate(){try{const e=await this.renderTestReport(),n=u(this.jestConfig?this.jestConfig.rootDir:"",this.getConfigValue("outputPath"));await s(i.dirname(n));let o=!0;if(this.getConfigValue("append")){t.existsSync(n)&&(await async function(e,s){try{await t.promises.access(e);const i=await t.promises.readFile(e,"utf8"),n=/<body>(.*?)<\/body>/s.exec(s),o=n?n[1]:s,a=/<\/body>/i.exec(i),r=a?a.index:0,l=[i.slice(0,r),o,i.slice(r)].join("");await t.promises.writeFile(e,l,"utf8")}catch(e){let t="An unknown error occurred while appending to the file";throw e instanceof Error&&(t=e.message),new Error(t)}}(n,e.content.toString()),o=!1)}return o&&t.writeFileSync(n,e.fullHtml.toString()),a("success",`Report generated (${n})`),e.fullHtml}catch(e){r(e)}}async renderTestReport(){const e=await this.renderTestReportContent();if(this.getConfigValue("boilerplate")){const s=u(this.jestConfig?this.jestConfig.rootDir:"",this.getConfigValue("boilerplate")),i=t.readFileSync(s,"utf8"),n=e?e.toString():"";return{content:n,fullHtml:i.replace("{jesthtmlreporter-content}",n)}}const s=n.create({html:{}}),o=s.ele("head");o.ele("meta",{charset:"utf-8"}),o.ele("title",{},this.getConfigValue("pageTitle"));let a=i.join(__dirname,`../style/${this.getConfigValue("theme")}.css`);this.getConfigValue("styleOverridePath")&&(a=this.getConfigValue("styleOverridePath"));if(!this.getConfigValue("useCssFile")&&!this.getConfigValue("styleOverridePath")){const e=t.readFileSync(a,"utf8");o.raw(`<style type="text/css">${e}</style>`)}else o.ele("link",{rel:"stylesheet",type:"text/css",href:a});const r=s.ele("body");return e&&r.raw(e.toString()),this.getConfigValue("customScriptPath")&&r.raw(`<script src="${this.getConfigValue("customScriptPath")}"><\/script>`),{fullHtml:s.toString(),content:e?e.toString():""}}renderTestSuiteHeader(e,t){const s=e.ele("summary",{class:"suite-info"});s.ele("div",{class:"suite-path"},t.testFilePath);const i=(t.perfStats.end-t.perfStats.start)/1e3,n=["suite-time"];i>this.getConfigValue("executionTimeWarningThreshold")&&n.push("warn"),s.ele("div",{class:n.join(" ")},`${i}s`)}async renderTestReportContent(){try{if(!this.testData||0===Object.entries(this.testData).length)throw Error("No test data provided");const t=n.begin().element("main",{class:"jesthtml-content"}),s=t.ele("header");s.ele("h1",{id:"title"},this.getConfigValue("pageTitle"));const i=this.getConfigValue("logo");i&&s.ele("img",{id:"logo",src:i});const o=t.ele("section",{id:"metadata-container"});if(this.testData.startTime&&!isNaN(this.testData.startTime)){const t=new Date(this.testData.startTime);if(t){const s=e(t,this.getConfigValue("dateFormat"));o.ele("div",{id:"timestamp"},`Started: ${s}`)}}this.renderAdditionalInformation(o);const a=o.ele("div",{id:"summary"}),r=a.ele("div",{id:"suite-summary"}),u=(e,t)=>[`summary-${e}`,t>0?"":" summary-empty"].join(" ");r.ele("div",{class:"summary-total"},`Suites (${this.testData.numTotalTestSuites})`),r.ele("div",{class:u("passed",this.testData.numPassedTestSuites)},`${this.testData.numPassedTestSuites} passed`),r.ele("div",{class:u("failed",this.testData.numFailedTestSuites)},`${this.testData.numFailedTestSuites} failed`),r.ele("div",{class:u("pending",this.testData.numPendingTestSuites)},`${this.testData.numPendingTestSuites} pending`),this.testData.snapshot&&this.testData.snapshot.unchecked>0&&this.getConfigValue("includeObsoleteSnapshots")&&r.ele("div",{class:"summary-obsolete-snapshots"},`${this.testData.snapshot.unchecked} obsolete snapshots`);const c=a.ele("div",{id:"test-summary"});c.ele("div",{class:"summary-total"},`Tests (${this.testData.numTotalTests})`),c.ele("div",{class:u("passed",this.testData.numPassedTests)},`${this.testData.numPassedTests} passed`),c.ele("div",{class:u("failed",this.testData.numFailedTests)},`${this.testData.numFailedTests} failed`),c.ele("div",{class:u("pending",this.testData.numPendingTests)},`${this.testData.numPendingTests} pending`);const d=((e,t)=>{const{sortType:s,params:i}=function(e){if(!e)return{sortType:null};const[t,s]=e.split(":").map((e=>e.trim())),i=s?.split(",").map((e=>e.trim()));if(!["status","executiondesc","executionasc","titledesc","titleasc"].includes(t.toLowerCase()))return{sortType:null};return{sortType:t.toLowerCase(),params:i}}(t);switch(s){case"status":{const t=i?.every((e=>g.includes(e)))?i:void 0;return f(e,t)}case"executiondesc":return p(e);case"executionasc":return m(e);case"titledesc":return y(e);case"titleasc":return v(e);default:return e}})(this.testData.testResults,this.getConfigValue("sort")),h=this.getConfigValue("statusIgnoreFilter");let S=[];return h&&(S=h.replace(/\s/g,"").toLowerCase().split(",")),d&&d.forEach(((e,s)=>{const i=t.ele("details",{id:`suite-${s+1}`,class:"suite-container",open:this.getConfigValue("collapseSuitesByDefault")?void 0:""});this.renderTestSuiteHeader(i,e);const n=i.ele("div",{class:"suite-tests"});if(!e.testResults||e.testResults.length<=0){if(e.failureMessage&&this.getConfigValue("includeSuiteFailure")){n.ele("div",{class:"test-result failed"}).ele("div",{class:"failureMessages suiteFailure"}," ").ele("pre",{class:"failureMsg"},l(e.failureMessage))}}else e.testResults.filter((e=>!S.includes(e.status))).forEach((async e=>{const t=n.ele("div",{class:`test-result ${e.status}`}),s=t.ele("div",{class:"test-info"});if(s.ele("div",{class:"test-suitename"},e.ancestorTitles&&e.ancestorTitles.length>0?e.ancestorTitles.join(" > "):" "),s.ele("div",{class:"test-title"},e.title),s.ele("div",{class:"test-status"},e.status),s.ele("div",{class:"test-duration"},e.duration?e.duration/1e3+"s":" "),e.failureMessages&&e.failureMessages.length>0&&this.getConfigValue("includeFailureMsg")){const s=t.ele("div",{class:"failureMessages"}," ");e.failureMessages.map((e=>this.getConfigValue("includeStackTrace")?e:e.split(/\n\s+at/)[0].trim().replace(/\n+$/,""))).forEach((e=>{s.ele("pre",{class:"failureMsg"},l(e))}))}})),this.consoleLogList&&this.consoleLogList.length>0&&this.getConfigValue("includeConsoleLog")&&this.renderSuiteConsoleLogs(e,i),e.snapshot&&e.snapshot.unchecked>0&&this.getConfigValue("includeObsoleteSnapshots")&&this.renderSuiteObsoleteSnapshots(i,e)})),t}catch(e){r(e)}}renderSuiteConsoleLogs(e,t){const s=this.consoleLogList.find((t=>t.filePath===e.testFilePath));if(s&&s.logs.length>0){const e=t.ele("div",{class:"suite-consolelog"});e.ele("div",{class:"suite-consolelog-header"},"Console Log"),s.logs.forEach((t=>{const s=e.ele("div",{class:"suite-consolelog-item"});s.ele("pre",{class:"suite-consolelog-item-origin"},l(t.origin)),s.ele("pre",{class:"suite-consolelog-item-message"},l(t.message))}))}}renderSuiteObsoleteSnapshots(e,t){const s=e.ele("div",{class:"suite-obsolete-snapshots"});s.ele("div",{class:"suite-obsolete-snapshots-header"},"Obsolete snapshots");s.ele("div",{class:"suite-obsolete-snapshots-item"}).ele("pre",{class:"suite-obsolete-snapshots-item-message"},t.snapshot.uncheckedKeys.join("\n"))}renderAdditionalInformation(e){const t=this.getConfigValue("additionalInformation");if(t&&Array.isArray(t)&&t.length>0){const s=e.ele("div",{class:"additional-information-container"});for(const e of t)s.ele("div",{class:"additional-information"},`${e.label}: ${e.value}`);return s}}getConfigValue(e){return this.config[e]}}const j=e=>new b(e).generate();module.exports=function(e,t){const s=[];if(Object.prototype.hasOwnProperty.call(e,"testResults")){const s=e;return j({testData:s,options:t}),s}this.onTestResult=(e,t)=>{t.console&&s.push({filePath:t.testFilePath,logs:t.console})},this.onRunComplete=(i,n)=>j({testData:n,options:t,jestConfig:e,consoleLogs:s})};
1
+ "use strict";var e=require("dateformat"),t=require("fs"),s=require("mkdirp"),i=require("path"),n=require("xmlbuilder"),o=require("strip-ansi");function a(e,t){const s={default:"%s",success:"%s",error:"%s"},i=s[e]?s[e]:s.default,n=`jest-html-reporter >> ${t}`;return void 0===process.env.JEST_WORKER_ID&&console.log(i,n),{logColor:i,logMsg:n}}function r(e){return a("error",e instanceof Error?e.message:"An error occurred")}function l(e){if("string"!=typeof e)throw new TypeError("Input must be a string");return o(e).replace(/[^\t\n\r\x20-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/gu,"")}function u(e,t){if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Both rootDir and filePath must be strings.");return t.startsWith("<rootDir>")?i.resolve(e,i.normalize(`./${t.slice(9)}`)):t}function c(e,t,s=!1){return!s&&e<t||s&&e>t?-1:!s&&e>t||s&&e<t?1:0}function d(e){return"boolean"==typeof e?e:"string"==typeof e&&"true"===e}function h(e){if("string"==typeof e)return e}const g=["pending","failed","passed"];const f=(e,t)=>{const s={pending:[],failed:[],passed:[]},i=[];e.forEach((e=>{const t=[],n=[],o=[],a=[];e.testResults.forEach((e=>{"pending"===e.status?t.push(e):"failed"===e.status?n.push(e):"passed"===e.status?o.push(e):a.push(e)})),t.length>0&&s.pending.push({...e,testResults:t}),n.length>0&&s.failed.push({...e,testResults:n}),o.length>0&&s.passed.push({...e,testResults:o}),a.length>0&&i.push({...e,testResults:a})}));const n=[...t||[],...["pending","failed","passed"].filter((e=>!(t||[]).includes(e)))],o=Object.entries(s).sort((([e],[t])=>n.indexOf(e)-n.indexOf(t))).flatMap((([,e])=>e));return[...o,...i]},p=e=>(e&&e.sort(((e,t)=>t.perfStats.end-t.perfStats.start-(e.perfStats.end-e.perfStats.start))),e),m=e=>(e&&e.sort(((e,t)=>e.perfStats.end-e.perfStats.start-(t.perfStats.end-t.perfStats.start))),e),y=e=>{if(e){const t=e.sort(((e,t)=>c(e.testFilePath,t.testFilePath,!0)));return t.forEach((e=>{e.testResults.sort(((e,t)=>c(e.ancestorTitles.join(" "),t.ancestorTitles.join(" "),!0))),e.testResults.sort(((e,t)=>c(e.title,t.title,!0)))})),t}return e},S=e=>{if(e){const t=e.sort(((e,t)=>c(e.testFilePath,t.testFilePath)));return t.forEach((e=>{e.testResults.sort(((e,t)=>c(e.ancestorTitles.join(" "),t.ancestorTitles.join(" ")))),e.testResults.sort(((e,t)=>c(e.title,t.title)))})),t}return e},T={additionalInformation:[],append:!1,boilerplate:void 0,collapseSuitesByDefault:!1,customScriptPath:void 0,dateFormat:"yyyy-mm-dd HH:MM:ss",executionTimeWarningThreshold:5,includeConsoleLog:!1,hideConsoleLogOrigin:!1,includeFailureMsg:!1,includeStackTrace:!0,includeSuiteFailure:!1,includeObsoleteSnapshots:!1,logo:void 0,outputPath:i.join(process.cwd(),"test-report.html"),pageTitle:"Test Report",sort:void 0,statusIgnoreFilter:void 0,styleOverridePath:void 0,theme:"defaultTheme",useCssFile:!1};function v(e){try{if(t.existsSync(e))return JSON.parse(t.readFileSync(e,"utf8"))}catch{return{}}return{}}const C={additionalInformation:(F=function(e){return"object"==typeof e&&null!==e&&"string"==typeof e.label&&"string"==typeof e.value},e=>Array.isArray(e)?e.filter(F):[]),append:d,boilerplate:h,collapseSuitesByDefault:d,customScriptPath:h,dateFormat:h,executionTimeWarningThreshold:function(e){return"number"==typeof e?e:"string"==typeof e?Number(e):NaN},includeConsoleLog:d,hideConsoleLogOrigin:d,includeFailureMsg:d,includeStackTrace:d,includeSuiteFailure:d,includeObsoleteSnapshots:d,logo:h,outputPath:h,pageTitle:h,sort:h,statusIgnoreFilter:h,styleOverridePath:h,theme:h,useCssFile:d};var F;function D(e){return"object"!=typeof e||null===e?{}:Object.keys(T).reduce(((t,s)=>{const i=C[s];if(i&&"function"==typeof i&&s in e){const n=i(e[s]);if(void 0!==n)return{...t,[s]:n}}return t}),{})}class b{testData;consoleLogList;jestConfig;config;constructor(e){this.testData=e.testData,this.jestConfig=e.jestConfig,this.consoleLogList=e.consoleLogs||[],this.config=function(e){const t=Object.keys(T).reduce(((e,t)=>{const s=function(e){return`JEST_HTML_REPORTER_${e.replace(/([a-z])([A-Z])/g,"$1_$2").toUpperCase()}`}(t);return void 0!==process.env[s]?{...e,[t]:process.env[s]}:e}),{}),s=v(i.join(process.cwd(),"jesthtmlreporter.config.json")),n=v(i.join(process.cwd(),"package.json"))["jest-html-reporter"]||{};return{...T,...D(n),...D(s),...D(e),...D(t)}}(e.options)}async generate(){try{const e=await this.renderTestReport(),n=u(this.jestConfig?this.jestConfig.rootDir:"",this.getConfigValue("outputPath"));await s(i.dirname(n));let o=!0;if(this.getConfigValue("append")){t.existsSync(n)&&(await async function(e,s){try{await t.promises.access(e);const i=await t.promises.readFile(e,"utf8"),n=/<body>(.*?)<\/body>/s.exec(s),o=n?n[1]:s,a=/<\/body>/i.exec(i),r=a?a.index:0,l=[i.slice(0,r),o,i.slice(r)].join("");await t.promises.writeFile(e,l,"utf8")}catch(e){let t="An unknown error occurred while appending to the file";throw e instanceof Error&&(t=e.message),new Error(t)}}(n,e.content.toString()),o=!1)}return o&&t.writeFileSync(n,e.fullHtml.toString()),a("success",`Report generated (${n})`),e.fullHtml}catch(e){r(e)}}async renderTestReport(){const e=await this.renderTestReportContent();if(this.getConfigValue("boilerplate")){const s=u(this.jestConfig?this.jestConfig.rootDir:"",this.getConfigValue("boilerplate")),i=t.readFileSync(s,"utf8"),n=e?e.toString():"";return{content:n,fullHtml:i.replace("{jesthtmlreporter-content}",n)}}const s=n.create({html:{}}),o=s.ele("head");o.ele("meta",{charset:"utf-8"}),o.ele("title",{},this.getConfigValue("pageTitle"));let a=i.join(__dirname,`../style/${this.getConfigValue("theme")}.css`);this.getConfigValue("styleOverridePath")&&(a=this.getConfigValue("styleOverridePath"));if(!this.getConfigValue("useCssFile")){const e=t.readFileSync(a,"utf8");o.raw(`<style type="text/css">${e}</style>`)}else o.ele("link",{rel:"stylesheet",type:"text/css",href:a});const r=s.ele("body");return e&&r.raw(e.toString()),this.getConfigValue("customScriptPath")&&r.raw(`<script src="${this.getConfigValue("customScriptPath")}"><\/script>`),{fullHtml:s.toString(),content:e?e.toString():""}}renderTestSuiteHeader(e,t){const s=e.ele("summary",{class:"suite-info"});s.ele("div",{class:"suite-path"},t.testFilePath);const i=(t.perfStats.end-t.perfStats.start)/1e3,n=["suite-time"];i>this.getConfigValue("executionTimeWarningThreshold")&&n.push("warn"),s.ele("div",{class:n.join(" ")},`${i}s`)}async renderTestReportContent(){try{if(!this.testData||0===Object.entries(this.testData).length)throw Error("No test data provided");const t=n.begin().element("main",{class:"jesthtml-content"}),s=t.ele("header");s.ele("h1",{id:"title"},this.getConfigValue("pageTitle"));const i=this.getConfigValue("logo");i&&s.ele("img",{id:"logo",src:i});const o=t.ele("section",{id:"metadata-container"});if(this.testData.startTime&&!isNaN(this.testData.startTime)){const t=new Date(this.testData.startTime);if(t){const s=e(t,this.getConfigValue("dateFormat"));o.ele("div",{id:"timestamp"},`Started: ${s}`)}}this.renderAdditionalInformation(o);const a=o.ele("div",{id:"summary"}),r=a.ele("div",{id:"suite-summary"}),u=(e,t)=>[`summary-${e}`,t>0?"":" summary-empty"].join(" ");r.ele("div",{class:"summary-total"},`Suites (${this.testData.numTotalTestSuites})`),r.ele("div",{class:u("passed",this.testData.numPassedTestSuites)},`${this.testData.numPassedTestSuites} passed`),r.ele("div",{class:u("failed",this.testData.numFailedTestSuites)},`${this.testData.numFailedTestSuites} failed`),r.ele("div",{class:u("pending",this.testData.numPendingTestSuites)},`${this.testData.numPendingTestSuites} pending`),this.testData.snapshot&&this.testData.snapshot.unchecked>0&&this.getConfigValue("includeObsoleteSnapshots")&&r.ele("div",{class:"summary-obsolete-snapshots"},`${this.testData.snapshot.unchecked} obsolete snapshots`);const c=a.ele("div",{id:"test-summary"});c.ele("div",{class:"summary-total"},`Tests (${this.testData.numTotalTests})`),c.ele("div",{class:u("passed",this.testData.numPassedTests)},`${this.testData.numPassedTests} passed`),c.ele("div",{class:u("failed",this.testData.numFailedTests)},`${this.testData.numFailedTests} failed`),c.ele("div",{class:u("pending",this.testData.numPendingTests)},`${this.testData.numPendingTests} pending`);const d=((e,t)=>{const{sortType:s,params:i}=function(e){if(!e)return{sortType:null};const[t,s]=e.split(":").map((e=>e.trim())),i=s?.split(",").map((e=>e.trim()));if(!["status","executiondesc","executionasc","titledesc","titleasc"].includes(t.toLowerCase()))return{sortType:null};return{sortType:t.toLowerCase(),params:i}}(t);switch(s){case"status":{const t=i?.every((e=>g.includes(e)))?i:void 0;return f(e,t)}case"executiondesc":return p(e);case"executionasc":return m(e);case"titledesc":return y(e);case"titleasc":return S(e);default:return e}})(this.testData.testResults,this.getConfigValue("sort")),h=this.getConfigValue("statusIgnoreFilter");let T=[];return h&&(T=h.replace(/\s/g,"").toLowerCase().split(",")),d&&d.forEach(((e,s)=>{const i=t.ele("details",{id:`suite-${s+1}`,class:"suite-container",open:this.getConfigValue("collapseSuitesByDefault")?void 0:""});this.renderTestSuiteHeader(i,e);const n=i.ele("div",{class:"suite-tests"});if(!e.testResults||e.testResults.length<=0){if(e.failureMessage&&this.getConfigValue("includeSuiteFailure")){n.ele("div",{class:"test-result failed"}).ele("div",{class:"failureMessages suiteFailure"}," ").ele("pre",{class:"failureMsg"},l(e.failureMessage))}}else e.testResults.filter((e=>!T.includes(e.status))).forEach((async e=>{const t=n.ele("div",{class:`test-result ${e.status}`}),s=t.ele("div",{class:"test-info"});if(s.ele("div",{class:"test-suitename"},e.ancestorTitles&&e.ancestorTitles.length>0?e.ancestorTitles.join(" > "):" "),s.ele("div",{class:"test-title"},e.title),s.ele("div",{class:"test-status"},e.status),s.ele("div",{class:"test-duration"},e.duration?e.duration/1e3+"s":" "),e.failureMessages&&e.failureMessages.length>0&&this.getConfigValue("includeFailureMsg")){const s=t.ele("div",{class:"failureMessages"}," ");e.failureMessages.map((e=>this.getConfigValue("includeStackTrace")?e:e.split(/\n\s+at/)[0].trim().replace(/\n+$/,""))).forEach((e=>{s.ele("pre",{class:"failureMsg"},l(e))}))}})),this.consoleLogList&&this.consoleLogList.length>0&&this.getConfigValue("includeConsoleLog")&&this.renderSuiteConsoleLogs(e,i),e.snapshot&&e.snapshot.unchecked>0&&this.getConfigValue("includeObsoleteSnapshots")&&this.renderSuiteObsoleteSnapshots(i,e)})),t}catch(e){r(e)}}renderSuiteConsoleLogs(e,t){const s=this.consoleLogList.find((t=>t.filePath===e.testFilePath));if(s&&s.logs.length>0){const e=t.ele("div",{class:"suite-consolelog"});e.ele("div",{class:"suite-consolelog-header"},"Console Log"),s.logs.forEach((t=>{const s=e.ele("div",{class:"suite-consolelog-item"});this.getConfigValue("hideConsoleLogOrigin")||s.ele("pre",{class:"suite-consolelog-item-origin"},l(t.origin)),s.ele("pre",{class:"suite-consolelog-item-message"},l(t.message))}))}}renderSuiteObsoleteSnapshots(e,t){const s=e.ele("div",{class:"suite-obsolete-snapshots"});s.ele("div",{class:"suite-obsolete-snapshots-header"},"Obsolete snapshots");s.ele("div",{class:"suite-obsolete-snapshots-item"}).ele("pre",{class:"suite-obsolete-snapshots-item-message"},t.snapshot.uncheckedKeys.join("\n"))}renderAdditionalInformation(e){const t=this.getConfigValue("additionalInformation");if(t&&Array.isArray(t)&&t.length>0){const s=e.ele("div",{class:"additional-information-container"});for(const e of t)s.ele("div",{class:"additional-information"},`${e.label}: ${e.value}`);return s}}getConfigValue(e){return this.config[e]}}const j=e=>new b(e).generate();module.exports=function(e,t){const s=[];if(Object.prototype.hasOwnProperty.call(e,"testResults")){const s=e;return j({testData:s,options:t}),s}this.onTestResult=(e,t)=>{t.console&&s.push({filePath:t.testFilePath,logs:t.console})},this.onRunComplete=(i,n)=>j({testData:n,options:t,jestConfig:e,consoleLogs:s})};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-html-reporter",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "Jest test results processor for generating a summary in HTML",
5
5
  "main": "dist/index.js",
6
6
  "unpkg": "dist/index.js",
@@ -15,7 +15,8 @@
15
15
  "test": "npm run lint && npm run jest",
16
16
  "test:watch": "npm run jest -- --watch --no-coverage",
17
17
  "bundle": "rollup -c",
18
- "build": "npm run test && npm run bundle"
18
+ "build": "npm run test && npm run bundle",
19
+ "prepublishOnly": "npm run build"
19
20
  },
20
21
  "repository": {
21
22
  "type": "git",
@@ -0,0 +1,277 @@
1
+ :root {
2
+ --text-primary: #eee;
3
+ --text-secondary: #aaa;
4
+ --success: #2ecc71;
5
+ --success-bright: #1e3d2a;
6
+ --danger: #e74c3c;
7
+ --danger-bright: #3d1e1e;
8
+ --warning: #f39c12;
9
+ --warning-bright: #3d2c1e;
10
+ --panel: #1f1f1f;
11
+ --border: #444;
12
+ --disabled: #666;
13
+ background-color: #121212;
14
+ }
15
+
16
+ html,
17
+ body {
18
+ font-family: Arial, Helvetica, sans-serif;
19
+ font-size: 16px;
20
+ margin: 0;
21
+ padding: 0;
22
+ color: var(--text-primary);
23
+ }
24
+ body {
25
+ padding: 2rem 1rem;
26
+ }
27
+ .jesthtml-content {
28
+ margin: 0 auto;
29
+ max-width: 70rem;
30
+ }
31
+ header {
32
+ display: flex;
33
+ align-items: center;
34
+ }
35
+ #title {
36
+ margin: 0;
37
+ flex-grow: 1;
38
+ }
39
+ #logo {
40
+ height: 4rem;
41
+ }
42
+ #timestamp {
43
+ color: var(--text-secondary);
44
+ margin-top: 0.5rem;
45
+ }
46
+
47
+ #metadata-container {
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 2rem;
51
+ margin-bottom: 2rem;
52
+ }
53
+
54
+ .additional-information-container {
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: 0.5rem;
58
+ color: var(--text-secondary);
59
+ }
60
+
61
+ /** SUMMARY */
62
+ #summary {
63
+ color: var(--text-primary);
64
+ display: flex;
65
+ font-family: monospace;
66
+ font-size: 1rem;
67
+ }
68
+ #summary > div {
69
+ margin-right: 0.5rem;
70
+ background: var(--panel);
71
+ padding: 1rem;
72
+ min-width: 15rem;
73
+ }
74
+ #summary > div:last-child {
75
+ margin-right: 0;
76
+ }
77
+ @media only screen and (max-width: 720px) {
78
+ #summary {
79
+ flex-direction: column;
80
+ }
81
+ #summary > div {
82
+ margin-right: 0;
83
+ margin-top: 1rem;
84
+ }
85
+ #summary > div:first-child {
86
+ margin-top: 0;
87
+ }
88
+ }
89
+
90
+ .summary-total {
91
+ font-weight: bold;
92
+ margin-bottom: 0.5rem;
93
+ }
94
+ .summary-passed {
95
+ color: var(--success);
96
+ border-left: 0.4rem solid var(--success);
97
+ padding-left: 0.5rem;
98
+ margin-bottom: 0.15rem;
99
+ }
100
+ .summary-failed,
101
+ .summary-obsolete-snapshots {
102
+ color: var(--danger);
103
+ border-left: 0.4rem solid var(--danger);
104
+ padding-left: 0.5rem;
105
+ margin-bottom: 0.15rem;
106
+ }
107
+ .summary-pending {
108
+ color: var(--warning);
109
+ border-left: 0.4rem solid var(--warning);
110
+ padding-left: 0.5rem;
111
+ margin-bottom: 0.15rem;
112
+ }
113
+ .summary-empty {
114
+ color: var(--disabled);
115
+ border-left: 0.4rem solid var(--disabled);
116
+ margin-bottom: 0.15rem;
117
+ }
118
+
119
+ .test-result {
120
+ padding: 1rem;
121
+ margin-bottom: 0.25rem;
122
+ }
123
+ .test-result:last-child {
124
+ border: 0;
125
+ }
126
+ .test-result.passed {
127
+ background-color: var(--success-bright);
128
+ color: var(--success);
129
+ }
130
+ .test-result.failed {
131
+ background-color: var(--danger-bright);
132
+ color: var(--danger);
133
+ }
134
+ .test-result.pending {
135
+ background-color: var(--warning-bright);
136
+ color: var(--warning);
137
+ }
138
+
139
+ .test-info {
140
+ display: flex;
141
+ justify-content: space-between;
142
+ }
143
+ .test-suitename {
144
+ width: 20%;
145
+ text-align: left;
146
+ font-weight: bold;
147
+ word-break: break-word;
148
+ }
149
+ .test-title {
150
+ width: 40%;
151
+ text-align: left;
152
+ font-style: italic;
153
+ }
154
+ .test-status {
155
+ width: 20%;
156
+ text-align: right;
157
+ }
158
+ .test-duration {
159
+ width: 10%;
160
+ text-align: right;
161
+ font-size: 0.85rem;
162
+ }
163
+
164
+ .failureMessages {
165
+ padding: 0 1rem;
166
+ margin-top: 1rem;
167
+ border-top: 1px dashed var(--danger);
168
+ }
169
+ .failureMessages.suiteFailure {
170
+ border-top: none;
171
+ }
172
+ .failureMsg {
173
+ white-space: pre-wrap;
174
+ white-space: -moz-pre-wrap;
175
+ white-space: -pre-wrap;
176
+ white-space: -o-pre-wrap;
177
+ word-wrap: break-word;
178
+ }
179
+
180
+ .suite-container {
181
+ margin-bottom: 1rem;
182
+ }
183
+ .suite-info {
184
+ padding: 1rem;
185
+ background-color: var(--panel);
186
+ color: var(--text-secondary);
187
+ border: 0.15rem solid;
188
+ border-color: var(--panel);
189
+ display: flex;
190
+ align-items: center;
191
+ margin-bottom: 0.25rem;
192
+ }
193
+ .suite-info:hover {
194
+ border-color: var(--border);
195
+ cursor: pointer;
196
+ }
197
+ .suite-info .suite-path {
198
+ word-break: break-all;
199
+ flex-grow: 1;
200
+ font-family: monospace;
201
+ font-size: 1rem;
202
+ }
203
+ .suite-info .suite-time {
204
+ margin-left: 1rem;
205
+ padding: 0.2rem 0.3rem;
206
+ font-size: 0.85rem;
207
+ }
208
+ .suite-info .suite-time.warn {
209
+ background-color: var(--danger);
210
+ color: #fff;
211
+ }
212
+ .suite-info:before {
213
+ content: "\2303";
214
+ display: inline-block;
215
+ margin-right: 1rem;
216
+ transform: rotate(180deg) translateY(0.15rem);
217
+ }
218
+ .suite-container[open] .suite-info:before {
219
+ transform: rotate(0deg) translateY(0.15rem);
220
+ }
221
+
222
+ /* CONSOLE LOGS */
223
+ .suite-consolelog {
224
+ margin-bottom: 0.25rem;
225
+ padding: 1rem;
226
+ background-color: var(--panel);
227
+ }
228
+ .suite-consolelog-header {
229
+ font-weight: bold;
230
+ }
231
+ .suite-consolelog-item {
232
+ padding: 0.5rem;
233
+ }
234
+ .suite-consolelog-item pre {
235
+ margin: 0.5rem 0;
236
+ white-space: pre-wrap;
237
+ white-space: -moz-pre-wrap;
238
+ white-space: -pre-wrap;
239
+ white-space: -o-pre-wrap;
240
+ word-wrap: break-word;
241
+ }
242
+ .suite-consolelog-item-origin {
243
+ color: var(--text-secondary);
244
+ font-weight: bold;
245
+ }
246
+ .suite-consolelog-item-message {
247
+ color: var(--text-primary);
248
+ font-size: 1rem;
249
+ padding: 0 0.5rem;
250
+ }
251
+
252
+ /* OBSOLETE SNAPSHOTS */
253
+ .suite-obsolete-snapshots {
254
+ margin-bottom: 0.25rem;
255
+ padding: 1rem;
256
+ background-color: var(--danger-bright);
257
+ color: var(--danger);
258
+ }
259
+ .suite-obsolete-snapshots-header {
260
+ font-weight: bold;
261
+ }
262
+ .suite-obsolete-snapshots-item {
263
+ padding: 0.5rem;
264
+ }
265
+ .suite-obsolete-snapshots-item pre {
266
+ margin: 0.5rem 0;
267
+ white-space: pre-wrap;
268
+ white-space: -moz-pre-wrap;
269
+ white-space: -pre-wrap;
270
+ white-space: -o-pre-wrap;
271
+ word-wrap: break-word;
272
+ }
273
+ .suite-obsolete-snapshots-item-message {
274
+ color: var(--text-primary);
275
+ font-size: 1rem;
276
+ padding: 0 0.5rem;
277
+ }