jest-html-reporter 2.6.2 → 2.8.2

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/dist/main.js CHANGED
@@ -53,6 +53,55 @@ const writeFile = ({ filePath, content }) => new Promise((resolve, reject) => {
53
53
  });
54
54
  });
55
55
 
56
+ /**
57
+ * Appends a file at the given destination
58
+ * @param {String} filePath
59
+ * @param {Any} content
60
+ */
61
+ const appendFile = ({ filePath, content }) => new Promise((resolve, reject) => {
62
+ mkdirp(path.dirname(filePath), (mkdirpError) => {
63
+ if (mkdirpError) {
64
+ return reject(new Error(`Something went wrong when creating the folder: ${mkdirpError}`));
65
+ }
66
+
67
+ // Check if the file exists or not
68
+ return fs.readFile(filePath, 'utf8', (err, existingContent) => {
69
+ let parsedContent = content;
70
+ // The file exists - we need to strip all unecessary html
71
+ if (!err) {
72
+ const contentSearch = /<body>(.*?)<\/body>/gm.exec(content);
73
+ if (contentSearch) {
74
+ const [strippedContent] = contentSearch;
75
+ parsedContent = strippedContent;
76
+ }
77
+ // Then we need to add the stripped content just before the </body> tag
78
+ if (existingContent) {
79
+ let newContent = existingContent;
80
+ const closingBodyTag = /<\/body>/gm.exec(existingContent);
81
+ const indexOfClosingBodyTag = closingBodyTag ? closingBodyTag.index : 0;
82
+
83
+ newContent = [existingContent.slice(0, indexOfClosingBodyTag), parsedContent, existingContent.slice(indexOfClosingBodyTag)]
84
+ .join('');
85
+
86
+ return fs.writeFile(filePath, newContent, (writeFileError) => {
87
+ if (writeFileError) {
88
+ return reject(new Error(`Something went wrong when creating the file: ${writeFileError}`));
89
+ }
90
+ return resolve(filePath);
91
+ });
92
+ }
93
+ }
94
+
95
+ return fs.appendFile(filePath, parsedContent, (writeFileError) => {
96
+ if (writeFileError) {
97
+ return reject(new Error(`Something went wrong when appending the file: ${writeFileError}`));
98
+ }
99
+ return resolve(filePath);
100
+ });
101
+ });
102
+ });
103
+ });
104
+
56
105
  /**
57
106
  * Reads and returns the content of a given file
58
107
  * @param {String} filePath
@@ -101,6 +150,7 @@ const sortAlphabetically = ({ a, b, reversed }) => {
101
150
  module.exports = {
102
151
  logMessage,
103
152
  writeFile,
153
+ appendFile,
104
154
  getFileContent,
105
155
  createHtmlBase,
106
156
  sortAlphabetically,
@@ -109,9 +159,10 @@ module.exports = {
109
159
 
110
160
  var utils_1 = utils.logMessage;
111
161
  var utils_2 = utils.writeFile;
112
- var utils_3 = utils.getFileContent;
113
- var utils_4 = utils.createHtmlBase;
114
- var utils_5 = utils.sortAlphabetically;
162
+ var utils_3 = utils.appendFile;
163
+ var utils_4 = utils.getFileContent;
164
+ var utils_5 = utils.createHtmlBase;
165
+ var utils_6 = utils.sortAlphabetically;
115
166
 
116
167
  var sorting = createCommonjsModule(function (module) {
117
168
  /**
@@ -259,6 +310,7 @@ var sorting_1 = sorting.sortSuiteResults;
259
310
  class ReportGenerator {
260
311
  constructor(config) {
261
312
  this.config = config;
313
+ this.consoleLogs = null;
262
314
  }
263
315
 
264
316
  /**
@@ -270,6 +322,7 @@ class ReportGenerator {
270
322
  const fileDestination = this.config.getOutputFilepath();
271
323
  const useCssFile = this.config.shouldUseCssFile();
272
324
  const shouldGetStylesheetContent = this.config.shouldGetStylesheetContent();
325
+ const append = this.config.getAppend();
273
326
  let stylesheetPath = null;
274
327
  let stylesheetContent = null;
275
328
 
@@ -289,10 +342,13 @@ class ReportGenerator {
289
342
  stylesheet,
290
343
  stylesheetPath,
291
344
  }))
292
- .then(xmlBuilderOutput => utils.writeFile({
345
+ .then(xmlBuilderOutput => (append ? utils.appendFile({
293
346
  filePath: fileDestination,
294
347
  content: xmlBuilderOutput,
295
- }))
348
+ }) : utils.writeFile({
349
+ filePath: fileDestination,
350
+ content: xmlBuilderOutput,
351
+ })))
296
352
  .then(() => utils.logMessage({
297
353
  type: 'success',
298
354
  msg: `Report generated (${fileDestination})`,
@@ -335,7 +391,11 @@ class ReportGenerator {
335
391
  * @param {String} stylesheetPath Optional path to an external stylesheet
336
392
  * @return {xmlbuilder}
337
393
  */
338
- renderHtmlReport({ data, stylesheet, stylesheetPath }) {
394
+ renderHtmlReport({
395
+ data,
396
+ stylesheet,
397
+ stylesheetPath,
398
+ }) {
339
399
  return new Promise((resolve, reject) => {
340
400
  // Make sure that test data was provided
341
401
  if (!data) { return reject(new Error('Test data missing or malformed')); }
@@ -462,18 +522,22 @@ class ReportGenerator {
462
522
  testTr.ele('td', { class: 'result' }, (test.status === 'passed') ? `${test.status} in ${test.duration / 1000}s` : test.status);
463
523
  });
464
524
 
465
- // Test Suite console.logs
466
- if (suite.console && suite.console.length > 0 && (this.config.shouldIncludeConsoleLog())) {
467
- // Console Log Container
468
- const consoleLogContainer = reportBody.ele('div', { class: 'suite-consolelog' });
469
- // Console Log Header
470
- consoleLogContainer.ele('div', { class: 'suite-consolelog-header' }, 'Console Log');
471
- // Logs
472
- suite.console.forEach((log) => {
473
- const logElement = consoleLogContainer.ele('div', { class: 'suite-consolelog-item' });
474
- logElement.ele('pre', { class: 'suite-consolelog-item-origin' }, stripAnsi(log.origin));
475
- logElement.ele('pre', { class: 'suite-consolelog-item-message' }, stripAnsi(log.message));
476
- });
525
+ // All console.logs caught during the test run
526
+ if (this.consoleLogs && this.consoleLogs.length > 0 && (this.config.shouldIncludeConsoleLog())) {
527
+ // Filter out the logs for this test file path
528
+ const filteredConsoleLogs = this.consoleLogs.find(logs => logs.testFilePath === suite.testFilePath);
529
+ if (filteredConsoleLogs && filteredConsoleLogs.logs.length > 0) {
530
+ // Console Log Container
531
+ const consoleLogContainer = reportBody.ele('div', { class: 'suite-consolelog' });
532
+ // Console Log Header
533
+ consoleLogContainer.ele('div', { class: 'suite-consolelog-header' }, 'Console Log');
534
+ // Apply the logs to the body
535
+ filteredConsoleLogs.logs.forEach((log) => {
536
+ const logElement = consoleLogContainer.ele('div', { class: 'suite-consolelog-item' });
537
+ logElement.ele('pre', { class: 'suite-consolelog-item-origin' }, stripAnsi(log.origin));
538
+ logElement.ele('pre', { class: 'suite-consolelog-item-message' }, stripAnsi(log.message));
539
+ });
540
+ }
477
541
  }
478
542
  });
479
543
 
@@ -624,6 +688,13 @@ const getSort = () =>
624
688
  const getStatusIgnoreFilter = () =>
625
689
  process.env.JEST_HTML_REPORTER_STATUS_FILTER || config.statusIgnoreFilter || null;
626
690
 
691
+ /**
692
+ * Returns whether or not new reports should be Appended to existing report
693
+ * @return {Boolean}
694
+ */
695
+ const getAppend = () =>
696
+ process.env.JEST_HTML_REPORTER_APPEND || config.append || false;
697
+
627
698
  module.exports = {
628
699
  config,
629
700
  setup,
@@ -644,6 +715,7 @@ module.exports = {
644
715
  getDateFormat,
645
716
  getSort,
646
717
  getStatusIgnoreFilter,
718
+ getAppend,
647
719
  };
648
720
  });
649
721
 
@@ -666,6 +738,7 @@ var config_17 = config_1.getTheme;
666
738
  var config_18 = config_1.getDateFormat;
667
739
  var config_19 = config_1.getSort;
668
740
  var config_20 = config_1.getStatusIgnoreFilter;
741
+ var config_21 = config_1.getAppend;
669
742
 
670
743
  function JestHtmlReporter(globalConfig, options) {
671
744
  // Initiate the config and setup the Generator class
@@ -692,12 +765,25 @@ function JestHtmlReporter(globalConfig, options) {
692
765
  */
693
766
  this.jestConfig = globalConfig;
694
767
  this.jestOptions = options;
768
+ this.consoleLogs = [];
769
+
770
+ this.onTestResult = (data, result) => {
771
+ // Catch console logs per test
772
+ if (result.console) {
773
+ this.consoleLogs.push({
774
+ testFilePath: result.testFilePath,
775
+ logs: result.console,
776
+ });
777
+ }
778
+ };
695
779
 
696
780
  this.onRunComplete = (contexts, testResult) => {
697
781
  // Apply the configuration within jest.config.json to the current config
698
782
  config_1.setConfigData(this.jestOptions);
699
783
  // Apply the updated config
700
784
  reportGenerator$$1.config = config_1;
785
+ // Add the console logs that we've caught
786
+ reportGenerator$$1.consoleLogs = this.consoleLogs;
701
787
  // Generate Report
702
788
  return reportGenerator$$1.generate({ data: testResult });
703
789
  };
package/dist/main.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var fs=_interopDefault(require("fs")),path=_interopDefault(require("path")),mkdirp=_interopDefault(require("mkdirp")),xmlbuilder=_interopDefault(require("xmlbuilder")),dateformat=_interopDefault(require("dateformat")),stripAnsi=_interopDefault(require("strip-ansi"));function createCommonjsModule(e,t){return e(t={exports:{}},t.exports),t.exports}var utils=createCommonjsModule(function(e){e.exports={logMessage:({type:e,msg:t,ignoreConsole:s})=>{const o={default:"%s",success:"%s",error:"%s"},r=o[e]?o[e]:o.default,i=`jest-html-reporter >> ${t}`;return s||console.log(r,i),{logColor:r,logMsg:i}},writeFile:({filePath:e,content:t})=>new Promise((s,o)=>{mkdirp(path.dirname(e),r=>r?o(new Error(`Something went wrong when creating the folder: ${r}`)):fs.writeFile(e,t,t=>t?o(new Error(`Something went wrong when creating the file: ${t}`)):s(e)))}),getFileContent:({filePath:e})=>new Promise((t,s)=>{fs.readFile(e,"utf8",(o,r)=>o?s(new Error(`Could not locate file: '${e}': ${o}`)):t(r))}),createHtmlBase:({pageTitle:e,stylesheet:t,stylesheetPath:s})=>{const o={html:{head:{meta:{"@charset":"utf-8"},title:{"#text":e}}}};return s?o.html.head.link={"@rel":"stylesheet","@type":"text/css","@href":s}:o.html.head.style={"@type":"text/css","#text":t},xmlbuilder.create(o)},sortAlphabetically:({a:e,b:t,reversed:s})=>!s&&e<t||s&&e>t?-1:!s&&e>t||s&&e<t?1:0}}),utils_1=utils.logMessage,utils_2=utils.writeFile,utils_3=utils.getFileContent,utils_4=utils.createHtmlBase,utils_5=utils.sortAlphabetically,sorting=createCommonjsModule(function(e){e.exports={sortSuiteResults:({testData:e,sortMethod:t})=>{if(t)switch(t.toLowerCase()){case"status":return(e=>{const t=[],s=[],o=[];return e.forEach(e=>{const r=[],i=[],n=[];e.testResults.forEach(e=>{"pending"===e.status?r.push(e):"failed"===e.status?i.push(e):n.push(e)}),r.length&&t.push(Object.assign({},e,{testResults:r})),i.length&&s.push(Object.assign({},e,{testResults:i})),n.length&&o.push(Object.assign({},e,{testResults:n}))}),[].concat(t,s,o)})(e);case"executiondesc":return(e=>(e&&e.sort((e,t)=>t.perfStats.end-t.perfStats.start-(e.perfStats.end-e.perfStats.start)),e))(e);case"executionasc":return(e=>(e&&e.sort((e,t)=>e.perfStats.end-e.perfStats.start-(t.perfStats.end-t.perfStats.start)),e))(e);case"titledesc":return(e=>{if(e){const t=e.sort((e,t)=>utils.sortAlphabetically({a:e.testFilePath,b:t.testFilePath,reversed:!0}));return t.forEach(e=>{e.testResults.sort((e,t)=>utils.sortAlphabetically({a:e.ancestorTitles.join(" "),b:t.ancestorTitles.join(" "),reversed:!0}))}),t}return e})(e);case"titleasc":return(e=>{if(e){const t=e.sort((e,t)=>utils.sortAlphabetically({a:e.testFilePath,b:t.testFilePath}));return t.forEach(e=>{e.testResults.sort((e,t)=>utils.sortAlphabetically({a:e.ancestorTitles.join(" "),b:t.ancestorTitles.join(" ")}))}),t}return e})(e);default:return e}return e}}}),sorting_1=sorting.sortSuiteResults;class ReportGenerator{constructor(e){this.config=e}generate({data:e,ignoreConsole:t}){const s=this.config.getOutputFilepath(),o=this.config.shouldUseCssFile(),r=this.config.shouldGetStylesheetContent();let i=null,n=null;return o&&(i=this.config.getStylesheetFilepath()),(n=r?()=>this.getStylesheetContent():()=>Promise.resolve())().then(t=>this.renderHtmlReport({data:e,stylesheet:t,stylesheetPath:i})).then(e=>utils.writeFile({filePath:s,content:e})).then(()=>utils.logMessage({type:"success",msg:`Report generated (${s})`,ignoreConsole:t})).catch(e=>utils.logMessage({type:"error",msg:e,ignoreConsole:t}))}integrateContentIntoBoilerplate({content:e}){const t=this.config.getBoilerplatePath();return new Promise((s,o)=>utils.getFileContent({filePath:t}).then(t=>s(t.replace("{jesthtmlreporter-content}",e))).catch(e=>o(e)))}getStylesheetContent(){const e=this.config.getStylesheetFilepath();return utils.getFileContent({filePath:e})}renderHtmlReport({data:e,stylesheet:t,stylesheetPath:s}){return new Promise((o,r)=>{if(!e)return r(new Error("Test data missing or malformed"));const i=this.config.getPageTitle(),n=this.getReportBody({data:e,pageTitle:i});if(this.config.getBoilerplatePath())return this.integrateContentIntoBoilerplate({content:n}).then(e=>o(e));const l=utils.createHtmlBase({pageTitle:i,stylesheet:t,stylesheetPath:s}),a=l.ele("body");a.raw(n);const c=this.config.getCustomScriptFilepath();return c&&a.raw(`<script src="${c}"><\/script>`),o(l)})}getReportBody({data:e,pageTitle:t}){const s=xmlbuilder.begin().element("div",{id:"jesthtml-content"}),o=s.ele("header");o.ele("h1",{id:"title"},t);const r=this.config.getLogo();r&&o.ele("img",{id:"logo",src:r});const i=s.ele("div",{id:"metadata-container"}),n=new Date(e.startTime);i.ele("div",{id:"timestamp"},`Start: ${dateformat(n,this.config.getDateFormat())}`),i.ele("div",{id:"summary"},`${e.numTotalTests} tests -- ${e.numPassedTests} passed / ${e.numFailedTests} failed / ${e.numPendingTests} pending`);const l=sorting.sortSuiteResults({testData:e.testResults,sortMethod:this.config.getSort()}),a=this.config.getStatusIgnoreFilter();let c=[];return a&&(c=a.replace(/\s/g,"").toLowerCase().split(",")),l.forEach(e=>{for(let t=e.testResults.length-1;t>=0;t-=1)c.includes(e.testResults[t].status)&&e.testResults.splice(t,1);if(!e.testResults||e.testResults.length<=0)return;const t=s.ele("div",{class:"suite-info"});t.ele("div",{class:"suite-path"},e.testFilePath);const o=(e.perfStats.end-e.perfStats.start)/1e3;t.ele("div",{class:`suite-time${o>5?" warn":""}`},`${o}s`);const r=s.ele("table",{class:"suite-table",cellspacing:"0",cellpadding:"0"});if(e.testResults.forEach(e=>{const t=r.ele("tr",{class:e.status});t.ele("td",{class:"suite"},e.ancestorTitles.join(" > "));const s=t.ele("td",{class:"test"},e.title);if(e.failureMessages&&this.config.shouldIncludeFailureMessages()){const t=s.ele("div",{class:"failureMessages"});e.failureMessages.forEach(e=>{t.ele("pre",{class:"failureMsg"},stripAnsi(e))})}t.ele("td",{class:"result"},"passed"===e.status?`${e.status} in ${e.duration/1e3}s`:e.status)}),e.console&&e.console.length>0&&this.config.shouldIncludeConsoleLog()){const t=s.ele("div",{class:"suite-consolelog"});t.ele("div",{class:"suite-consolelog-header"},"Console Log"),e.console.forEach(e=>{const s=t.ele("div",{class:"suite-consolelog-item"});s.ele("pre",{class:"suite-consolelog-item-origin"},stripAnsi(e.origin)),s.ele("pre",{class:"suite-consolelog-item-message"},stripAnsi(e.message))})}}),s}}var reportGenerator=ReportGenerator,config_1=createCommonjsModule(function(e){const t={},s=e=>Object.assign(t,e),o=()=>process.env.JEST_HTML_REPORTER_THEME||t.theme||"defaultTheme",r=()=>Boolean(process.env.JEST_HTML_REPORTER_STYLE_OVERRIDE_PATH)||Boolean(t.styleOverridePath),i=()=>process.env.JEST_HTML_REPORTER_USE_CSS_FILE||t.useCssFile||!1;e.exports={config:t,setup:()=>{try{const e=fs.readFileSync(path.join(process.cwd(),"jesthtmlreporter.config.json"),"utf8");if(e)return s(JSON.parse(e))}catch(e){}try{const e=fs.readFileSync(path.join(process.cwd(),"package.json"),"utf8");if(e)return s(JSON.parse(e)["jest-html-reporter"])}catch(e){}return t},setConfigData:s,getOutputFilepath:()=>{return(process.env.JEST_HTML_REPORTER_OUTPUT_PATH||t.outputPath||path.join(process.cwd(),"test-report.html")).replace(/<rootdir>/gi,".")},getStylesheetFilepath:()=>process.env.JEST_HTML_REPORTER_STYLE_OVERRIDE_PATH||t.styleOverridePath||path.join(__dirname,`../style/${o()}.css`),getHasStyleOverridePath:r,getCustomScriptFilepath:()=>process.env.JEST_HTML_REPORTER_CUSTOM_SCRIPT_PATH||t.customScriptPath||null,getPageTitle:()=>process.env.JEST_HTML_REPORTER_PAGE_TITLE||t.pageTitle||"Test report",getLogo:()=>process.env.JEST_HTML_REPORTER_LOGO||t.logo||null,shouldIncludeFailureMessages:()=>process.env.JEST_HTML_REPORTER_INCLUDE_FAILURE_MSG||t.includeFailureMsg||!1,shouldIncludeConsoleLog:()=>process.env.JEST_HTML_REPORTER_INCLUDE_CONSOLE_LOG||t.includeConsoleLog||!1,shouldUseCssFile:i,shouldGetStylesheetContent:()=>!(r()&&i()),getExecutionTimeWarningThreshold:()=>process.env.JEST_HTML_REPORTER_EXECUTION_TIME_WARNING_THRESHOLD||t.executionTimeWarningThreshold||5,getBoilerplatePath:()=>process.env.JEST_HTML_REPORTER_BOILERPLATE||t.boilerplate||null,getTheme:o,getDateFormat:()=>process.env.JEST_HTML_REPORTER_DATE_FORMAT||t.dateFormat||"yyyy-mm-dd HH:MM:ss",getSort:()=>process.env.JEST_HTML_REPORTER_SORT||t.sort||"default",getStatusIgnoreFilter:()=>process.env.JEST_HTML_REPORTER_STATUS_FILTER||t.statusIgnoreFilter||null}}),config_2=config_1.config,config_3=config_1.setup,config_4=config_1.setConfigData,config_5=config_1.getOutputFilepath,config_6=config_1.getStylesheetFilepath,config_7=config_1.getHasStyleOverridePath,config_8=config_1.getCustomScriptFilepath,config_9=config_1.getPageTitle,config_10=config_1.getLogo,config_11=config_1.shouldIncludeFailureMessages,config_12=config_1.shouldIncludeConsoleLog,config_13=config_1.shouldUseCssFile,config_14=config_1.shouldGetStylesheetContent,config_15=config_1.getExecutionTimeWarningThreshold,config_16=config_1.getBoilerplatePath,config_17=config_1.getTheme,config_18=config_1.getDateFormat,config_19=config_1.getSort,config_20=config_1.getStatusIgnoreFilter;function JestHtmlReporter(e,t){config_1.setup();const s=new reportGenerator(config_1);if(Object.prototype.hasOwnProperty.call(e,"testResults"))return s.generate({data:e}),e;this.jestConfig=e,this.jestOptions=t,this.onRunComplete=((e,t)=>(config_1.setConfigData(this.jestOptions),s.config=config_1,s.generate({data:t})))}var src=JestHtmlReporter;module.exports=src;
1
+ "use strict";function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var fs=_interopDefault(require("fs")),path=_interopDefault(require("path")),mkdirp=_interopDefault(require("mkdirp")),xmlbuilder=_interopDefault(require("xmlbuilder")),dateformat=_interopDefault(require("dateformat")),stripAnsi=_interopDefault(require("strip-ansi"));function createCommonjsModule(e,t){return e(t={exports:{}},t.exports),t.exports}var utils=createCommonjsModule(function(e){e.exports={logMessage:({type:e,msg:t,ignoreConsole:s})=>{const o={default:"%s",success:"%s",error:"%s"},n=o[e]?o[e]:o.default,i=`jest-html-reporter >> ${t}`;return s||console.log(n,i),{logColor:n,logMsg:i}},writeFile:({filePath:e,content:t})=>new Promise((s,o)=>{mkdirp(path.dirname(e),n=>n?o(new Error(`Something went wrong when creating the folder: ${n}`)):fs.writeFile(e,t,t=>t?o(new Error(`Something went wrong when creating the file: ${t}`)):s(e)))}),appendFile:({filePath:e,content:t})=>new Promise((s,o)=>{mkdirp(path.dirname(e),n=>n?o(new Error(`Something went wrong when creating the folder: ${n}`)):fs.readFile(e,"utf8",(n,i)=>{let r=t;if(!n){const n=/<body>(.*?)<\/body>/gm.exec(t);if(n){const[e]=n;r=e}if(i){let t=i;const n=/<\/body>/gm.exec(i),l=n?n.index:0;return t=[i.slice(0,l),r,i.slice(l)].join(""),fs.writeFile(e,t,t=>t?o(new Error(`Something went wrong when creating the file: ${t}`)):s(e))}}return fs.appendFile(e,r,t=>t?o(new Error(`Something went wrong when appending the file: ${t}`)):s(e))}))}),getFileContent:({filePath:e})=>new Promise((t,s)=>{fs.readFile(e,"utf8",(o,n)=>o?s(new Error(`Could not locate file: '${e}': ${o}`)):t(n))}),createHtmlBase:({pageTitle:e,stylesheet:t,stylesheetPath:s})=>{const o={html:{head:{meta:{"@charset":"utf-8"},title:{"#text":e}}}};return s?o.html.head.link={"@rel":"stylesheet","@type":"text/css","@href":s}:o.html.head.style={"@type":"text/css","#text":t},xmlbuilder.create(o)},sortAlphabetically:({a:e,b:t,reversed:s})=>!s&&e<t||s&&e>t?-1:!s&&e>t||s&&e<t?1:0}}),utils_1=utils.logMessage,utils_2=utils.writeFile,utils_3=utils.appendFile,utils_4=utils.getFileContent,utils_5=utils.createHtmlBase,utils_6=utils.sortAlphabetically,sorting=createCommonjsModule(function(e){e.exports={sortSuiteResults:({testData:e,sortMethod:t})=>{if(t)switch(t.toLowerCase()){case"status":return(e=>{const t=[],s=[],o=[];return e.forEach(e=>{const n=[],i=[],r=[];e.testResults.forEach(e=>{"pending"===e.status?n.push(e):"failed"===e.status?i.push(e):r.push(e)}),n.length&&t.push(Object.assign({},e,{testResults:n})),i.length&&s.push(Object.assign({},e,{testResults:i})),r.length&&o.push(Object.assign({},e,{testResults:r}))}),[].concat(t,s,o)})(e);case"executiondesc":return(e=>(e&&e.sort((e,t)=>t.perfStats.end-t.perfStats.start-(e.perfStats.end-e.perfStats.start)),e))(e);case"executionasc":return(e=>(e&&e.sort((e,t)=>e.perfStats.end-e.perfStats.start-(t.perfStats.end-t.perfStats.start)),e))(e);case"titledesc":return(e=>{if(e){const t=e.sort((e,t)=>utils.sortAlphabetically({a:e.testFilePath,b:t.testFilePath,reversed:!0}));return t.forEach(e=>{e.testResults.sort((e,t)=>utils.sortAlphabetically({a:e.ancestorTitles.join(" "),b:t.ancestorTitles.join(" "),reversed:!0}))}),t}return e})(e);case"titleasc":return(e=>{if(e){const t=e.sort((e,t)=>utils.sortAlphabetically({a:e.testFilePath,b:t.testFilePath}));return t.forEach(e=>{e.testResults.sort((e,t)=>utils.sortAlphabetically({a:e.ancestorTitles.join(" "),b:t.ancestorTitles.join(" ")}))}),t}return e})(e);default:return e}return e}}}),sorting_1=sorting.sortSuiteResults;class ReportGenerator{constructor(e){this.config=e,this.consoleLogs=null}generate({data:e,ignoreConsole:t}){const s=this.config.getOutputFilepath(),o=this.config.shouldUseCssFile(),n=this.config.shouldGetStylesheetContent(),i=this.config.getAppend();let r=null,l=null;return o&&(r=this.config.getStylesheetFilepath()),(l=n?()=>this.getStylesheetContent():()=>Promise.resolve())().then(t=>this.renderHtmlReport({data:e,stylesheet:t,stylesheetPath:r})).then(e=>i?utils.appendFile({filePath:s,content:e}):utils.writeFile({filePath:s,content:e})).then(()=>utils.logMessage({type:"success",msg:`Report generated (${s})`,ignoreConsole:t})).catch(e=>utils.logMessage({type:"error",msg:e,ignoreConsole:t}))}integrateContentIntoBoilerplate({content:e}){const t=this.config.getBoilerplatePath();return new Promise((s,o)=>utils.getFileContent({filePath:t}).then(t=>s(t.replace("{jesthtmlreporter-content}",e))).catch(e=>o(e)))}getStylesheetContent(){const e=this.config.getStylesheetFilepath();return utils.getFileContent({filePath:e})}renderHtmlReport({data:e,stylesheet:t,stylesheetPath:s}){return new Promise((o,n)=>{if(!e)return n(new Error("Test data missing or malformed"));const i=this.config.getPageTitle(),r=this.getReportBody({data:e,pageTitle:i});if(this.config.getBoilerplatePath())return this.integrateContentIntoBoilerplate({content:r}).then(e=>o(e));const l=utils.createHtmlBase({pageTitle:i,stylesheet:t,stylesheetPath:s}),a=l.ele("body");a.raw(r);const c=this.config.getCustomScriptFilepath();return c&&a.raw(`<script src="${c}"><\/script>`),o(l)})}getReportBody({data:e,pageTitle:t}){const s=xmlbuilder.begin().element("div",{id:"jesthtml-content"}),o=s.ele("header");o.ele("h1",{id:"title"},t);const n=this.config.getLogo();n&&o.ele("img",{id:"logo",src:n});const i=s.ele("div",{id:"metadata-container"}),r=new Date(e.startTime);i.ele("div",{id:"timestamp"},`Start: ${dateformat(r,this.config.getDateFormat())}`),i.ele("div",{id:"summary"},`${e.numTotalTests} tests -- ${e.numPassedTests} passed / ${e.numFailedTests} failed / ${e.numPendingTests} pending`);const l=sorting.sortSuiteResults({testData:e.testResults,sortMethod:this.config.getSort()}),a=this.config.getStatusIgnoreFilter();let c=[];return a&&(c=a.replace(/\s/g,"").toLowerCase().split(",")),l.forEach(e=>{for(let t=e.testResults.length-1;t>=0;t-=1)c.includes(e.testResults[t].status)&&e.testResults.splice(t,1);if(!e.testResults||e.testResults.length<=0)return;const t=s.ele("div",{class:"suite-info"});t.ele("div",{class:"suite-path"},e.testFilePath);const o=(e.perfStats.end-e.perfStats.start)/1e3;t.ele("div",{class:`suite-time${o>5?" warn":""}`},`${o}s`);const n=s.ele("table",{class:"suite-table",cellspacing:"0",cellpadding:"0"});if(e.testResults.forEach(e=>{const t=n.ele("tr",{class:e.status});t.ele("td",{class:"suite"},e.ancestorTitles.join(" > "));const s=t.ele("td",{class:"test"},e.title);if(e.failureMessages&&this.config.shouldIncludeFailureMessages()){const t=s.ele("div",{class:"failureMessages"});e.failureMessages.forEach(e=>{t.ele("pre",{class:"failureMsg"},stripAnsi(e))})}t.ele("td",{class:"result"},"passed"===e.status?`${e.status} in ${e.duration/1e3}s`:e.status)}),this.consoleLogs&&this.consoleLogs.length>0&&this.config.shouldIncludeConsoleLog()){const t=this.consoleLogs.find(t=>t.testFilePath===e.testFilePath);if(t&&t.logs.length>0){const e=s.ele("div",{class:"suite-consolelog"});e.ele("div",{class:"suite-consolelog-header"},"Console Log"),t.logs.forEach(t=>{const s=e.ele("div",{class:"suite-consolelog-item"});s.ele("pre",{class:"suite-consolelog-item-origin"},stripAnsi(t.origin)),s.ele("pre",{class:"suite-consolelog-item-message"},stripAnsi(t.message))})}}}),s}}var reportGenerator=ReportGenerator,config_1=createCommonjsModule(function(e){const t={},s=e=>Object.assign(t,e),o=()=>process.env.JEST_HTML_REPORTER_THEME||t.theme||"defaultTheme",n=()=>Boolean(process.env.JEST_HTML_REPORTER_STYLE_OVERRIDE_PATH)||Boolean(t.styleOverridePath),i=()=>process.env.JEST_HTML_REPORTER_USE_CSS_FILE||t.useCssFile||!1;e.exports={config:t,setup:()=>{try{const e=fs.readFileSync(path.join(process.cwd(),"jesthtmlreporter.config.json"),"utf8");if(e)return s(JSON.parse(e))}catch(e){}try{const e=fs.readFileSync(path.join(process.cwd(),"package.json"),"utf8");if(e)return s(JSON.parse(e)["jest-html-reporter"])}catch(e){}return t},setConfigData:s,getOutputFilepath:()=>{return(process.env.JEST_HTML_REPORTER_OUTPUT_PATH||t.outputPath||path.join(process.cwd(),"test-report.html")).replace(/<rootdir>/gi,".")},getStylesheetFilepath:()=>process.env.JEST_HTML_REPORTER_STYLE_OVERRIDE_PATH||t.styleOverridePath||path.join(__dirname,`../style/${o()}.css`),getHasStyleOverridePath:n,getCustomScriptFilepath:()=>process.env.JEST_HTML_REPORTER_CUSTOM_SCRIPT_PATH||t.customScriptPath||null,getPageTitle:()=>process.env.JEST_HTML_REPORTER_PAGE_TITLE||t.pageTitle||"Test report",getLogo:()=>process.env.JEST_HTML_REPORTER_LOGO||t.logo||null,shouldIncludeFailureMessages:()=>process.env.JEST_HTML_REPORTER_INCLUDE_FAILURE_MSG||t.includeFailureMsg||!1,shouldIncludeConsoleLog:()=>process.env.JEST_HTML_REPORTER_INCLUDE_CONSOLE_LOG||t.includeConsoleLog||!1,shouldUseCssFile:i,shouldGetStylesheetContent:()=>!(n()&&i()),getExecutionTimeWarningThreshold:()=>process.env.JEST_HTML_REPORTER_EXECUTION_TIME_WARNING_THRESHOLD||t.executionTimeWarningThreshold||5,getBoilerplatePath:()=>process.env.JEST_HTML_REPORTER_BOILERPLATE||t.boilerplate||null,getTheme:o,getDateFormat:()=>process.env.JEST_HTML_REPORTER_DATE_FORMAT||t.dateFormat||"yyyy-mm-dd HH:MM:ss",getSort:()=>process.env.JEST_HTML_REPORTER_SORT||t.sort||"default",getStatusIgnoreFilter:()=>process.env.JEST_HTML_REPORTER_STATUS_FILTER||t.statusIgnoreFilter||null,getAppend:()=>process.env.JEST_HTML_REPORTER_APPEND||t.append||!1}}),config_2=config_1.config,config_3=config_1.setup,config_4=config_1.setConfigData,config_5=config_1.getOutputFilepath,config_6=config_1.getStylesheetFilepath,config_7=config_1.getHasStyleOverridePath,config_8=config_1.getCustomScriptFilepath,config_9=config_1.getPageTitle,config_10=config_1.getLogo,config_11=config_1.shouldIncludeFailureMessages,config_12=config_1.shouldIncludeConsoleLog,config_13=config_1.shouldUseCssFile,config_14=config_1.shouldGetStylesheetContent,config_15=config_1.getExecutionTimeWarningThreshold,config_16=config_1.getBoilerplatePath,config_17=config_1.getTheme,config_18=config_1.getDateFormat,config_19=config_1.getSort,config_20=config_1.getStatusIgnoreFilter,config_21=config_1.getAppend;function JestHtmlReporter(e,t){config_1.setup();const s=new reportGenerator(config_1);if(Object.prototype.hasOwnProperty.call(e,"testResults"))return s.generate({data:e}),e;this.jestConfig=e,this.jestOptions=t,this.consoleLogs=[],this.onTestResult=((e,t)=>{t.console&&this.consoleLogs.push({testFilePath:t.testFilePath,logs:t.console})}),this.onRunComplete=((e,t)=>(config_1.setConfigData(this.jestOptions),s.config=config_1,s.consoleLogs=this.consoleLogs,s.generate({data:t})))}var src=JestHtmlReporter;module.exports=src;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortTestResults = (testResults, sortType) => {
4
+ switch (sortType) {
5
+ case "status":
6
+ return sortTestResultsByStatus(testResults);
7
+ default:
8
+ return testResults;
9
+ }
10
+ };
11
+ /**
12
+ * Splits test suites apart based on individual test status and sorts by that status:
13
+ * 1. Pending
14
+ * 2. Failed
15
+ * 3. Passed
16
+ */
17
+ const sortTestResultsByStatus = (testResults) => {
18
+ const pendingSuites = [];
19
+ const failingSuites = [];
20
+ const passingSuites = [];
21
+ testResults.forEach(result => {
22
+ const pending = [];
23
+ const failed = [];
24
+ const passed = [];
25
+ result.testResults.forEach(x => {
26
+ if (x.status === "pending") {
27
+ pending.push(x);
28
+ }
29
+ else if (x.status === "failed") {
30
+ failed.push(x);
31
+ }
32
+ else {
33
+ passed.push(x);
34
+ }
35
+ });
36
+ if (pending.length) {
37
+ pendingSuites.push({
38
+ ...result,
39
+ testResults: pending
40
+ });
41
+ }
42
+ if (failed.length) {
43
+ failingSuites.push({
44
+ ...result,
45
+ testResults: failed
46
+ });
47
+ }
48
+ if (passed.length) {
49
+ pendingSuites.push({
50
+ ...result,
51
+ testResults: failed
52
+ });
53
+ }
54
+ });
55
+ return [].concat(pendingSuites, failingSuites, passingSuites);
56
+ };
57
+ //# sourceMappingURL=sortingMethods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sortingMethods.js","sourceRoot":"","sources":["../src/sortingMethods.ts"],"names":[],"mappings":";;AAGa,QAAA,eAAe,GAAG,CAC7B,WAA4C,EAC5C,QAAkC,EACD,EAAE;IACnC,QAAQ,QAAQ,EAAE;QAChB,KAAK,QAAQ;YACX,OAAO,uBAAuB,CAAC,WAAW,CAAC,CAAC;QAC9C;YACE,OAAO,WAAW,CAAC;KACtB;AACH,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,uBAAuB,GAAG,CAC9B,WAA4C,EAC5C,EAAE;IACF,MAAM,aAAa,GAAoC,EAAE,CAAC;IAC1D,MAAM,aAAa,GAAoC,EAAE,CAAC;IAC1D,MAAM,aAAa,GAAoC,EAAE,CAAC;IAE1D,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QAC3B,MAAM,OAAO,GAAsB,EAAE,CAAC;QACtC,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,MAAM,MAAM,GAAsB,EAAE,CAAC;QAErC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YAC7B,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE;gBAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACjB;iBAAM,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE;gBAChC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aAChB;iBAAM;gBACL,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aAChB;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,EAAE;YAClB,aAAa,CAAC,IAAI,CAAC;gBACjB,GAAG,MAAM;gBACT,WAAW,EAAE,OAAO;aACrB,CAAC,CAAC;SACJ;QACD,IAAI,MAAM,CAAC,MAAM,EAAE;YACjB,aAAa,CAAC,IAAI,CAAC;gBACjB,GAAG,MAAM;gBACT,WAAW,EAAE,MAAM;aACpB,CAAC,CAAC;SACJ;QACD,IAAI,MAAM,CAAC,MAAM,EAAE;YACjB,aAAa,CAAC,IAAI,CAAC;gBACjB,GAAG,MAAM;gBACT,WAAW,EAAE,MAAM;aACpB,CAAC,CAAC;SACJ;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAChE,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-html-reporter",
3
- "version": "2.6.2",
3
+ "version": "2.8.2",
4
4
  "description": "Jest test results processor for generating a summary in HTML",
5
5
  "main": "dist/main",
6
6
  "unpkg": "dist/main.min.js",
@@ -39,20 +39,20 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "dateformat": "3.0.2",
42
- "mkdirp": "0.5.1",
42
+ "mkdirp": "0.5.3",
43
43
  "strip-ansi": "3.0.1",
44
44
  "xmlbuilder": "13.0.2"
45
45
  },
46
46
  "peerDependencies": {
47
- "jest": "19.x - 24.x"
47
+ "jest": "19.x - 25.x"
48
48
  },
49
49
  "devDependencies": {
50
50
  "eslint": "^4.19.1",
51
51
  "eslint-config-airbnb-base": "^12.1.0",
52
- "eslint-plugin-import": "^2.18.2",
52
+ "eslint-plugin-import": "^2.20.1",
53
53
  "istanbul-api": "1.2.2",
54
54
  "istanbul-reports": "1.1.4",
55
- "jest": "^24.9.0",
55
+ "jest": "^25.1.0",
56
56
  "rollup": "^0.55.5",
57
57
  "rollup-plugin-commonjs": "^8.4.1",
58
58
  "rollup-plugin-node-resolve": "^3.4.0",
@@ -10,6 +10,9 @@ body {
10
10
  padding: 3rem;
11
11
  font-size: 0.85rem;
12
12
  }
13
+ #jesthtml-content {
14
+ margin-bottom: 2rem;
15
+ }
13
16
  header {
14
17
  display: flex;
15
18
  align-items: center;
@@ -9,6 +9,9 @@ body {
9
9
  padding: 1rem;
10
10
  font-size: 0.85rem;
11
11
  }
12
+ #jesthtml-content {
13
+ margin-bottom: 2rem;
14
+ }
12
15
  header {
13
16
  display: flex;
14
17
  align-items: center;
@@ -9,6 +9,9 @@ body {
9
9
  padding: 3rem;
10
10
  font-size: 0.85rem;
11
11
  }
12
+ #jesthtml-content {
13
+ margin-bottom: 2rem;
14
+ }
12
15
  header {
13
16
  display: flex;
14
17
  align-items: center;