monocart-reporter 1.6.27 → 1.6.29

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
@@ -493,6 +493,7 @@ module.exports = {
493
493
  ]
494
494
  };
495
495
  ```
496
+ see example [remove-secrets](https://github.com/cenfun/monocart-reporter-test/tree/main/tests/remove-secrets)
496
497
 
497
498
  ## Style Tags
498
499
  * Add tag to test/describe title ( starts with `@` )
@@ -742,13 +743,14 @@ const report = await attachCoverageReport(coverageList, test.info(), {
742
743
  | Input data format | Istanbul (Object) | V8 (Array) | V8 (Array) |
743
744
  | Options | `watermarks: {}` | `watermarks: [50, 80]` | `toIstanbul: true, watermarks: {}` |
744
745
  | Output report | [Istanbul HTML report](https://cenfun.github.io/monocart-reporter/coverage-4ffdff9b89e7b58476cf/index.html) | [V8 HTML report](https://cenfun.github.io/monocart-reporter/coverage-f8ad4b6741d60f9e7b81/index.html) | [Istanbul HTML report](https://cenfun.github.io/monocart-reporter/coverage-391e7054ca1e6d944895/index.html) |
745
- | Indicators | Covered Lines, Branches, Statements and Functions, Execution Counts | Covered Bytes, Execution Counts | Covered Lines, Branches, Statements and Functions, Execution Counts |
746
+ | Indicators | Covered Lines, Branches, Statements and Functions, Execution Counts | Covered Bytes, Lines (after formatted) Execution Counts | Covered Lines, Branches, Statements and Functions, Execution Counts |
747
+ | Source code without [instrumentation](https://github.com/istanbuljs/babel-plugin-istanbul) | ❌ | ✅ | ✅ |
746
748
  | CSS coverage | ❌ | ✅ | ❌ |
747
749
  | Minified code | N/A | ✅ | ❌ |
748
750
  | Code formatting | N/A | ✅ | ❌ |
749
751
 
750
752
  ### Global Coverage Report
751
- If you want to generate a global coverage report, you can use the API `addCoverageReport(v8list, testInfo)`. When all the tests are finished, all added reports will be automatically merged into a global report. Currently supported `V8` only. Here is an example for Playwright Component Testing [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue).
753
+ The global coverage report will not be attached to any test case, but will merge all coverages into one global report after all the tests are finished. The API is `addCoverageReport(v8list, testInfo)`, currently supported `V8` only. Here is an example for Playwright Component Testing [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue).
752
754
  ```js
753
755
  // playwright.config.js
754
756
  module.exports = {
@@ -906,91 +908,54 @@ module.exports = {
906
908
  // async hook after report data generated
907
909
  onEnd: async (reportData, capability) => {
908
910
  // console.log(reportData.summary);
909
-
910
- // send email
911
- // const sendEmail = require('./common/send-email.js');
912
- // await sendEmail(reportData, capability);
913
-
914
- // testrail integration
915
- // const testrail = require('./common/testrail.js');
916
- // await testrail(reportData, capability);
917
-
918
- // jira + zephyr scale integration
919
- // const zephyrScale = require('./common/zephyr-scale.js');
920
- // await zephyrScale(reportData, capability);
921
-
922
- // jira + xray integration
923
- // const xray = require('./common/xray.js');
924
- // await xray(reportData, capability);
925
-
926
- // slack integration with webhook
927
- // const slackWebhook = require('./common/slack-webhook.js');
928
- // await slackWebhook(reportData, capability);
929
-
930
- // slack integration with web api
931
- // const slackWebApi = require('./common/slack-web-api.js');
932
- // await slackWebApi(reportData, capability);
933
-
934
- // discord integration with webhook
935
- // const discordWebhook = require('./common/discord-webhook.js');
936
- // await discordWebhook(reportData, capability);
937
-
938
- // teams integration with webhook
939
- // const teamsWebhook = require('./common/teams-webhook.js');
940
- // await teamsWebhook(reportData, capability);
941
-
942
- // html to pdf
943
- // const toPdf = require('./common/to-pdf.js');
944
- // await toPdf(reportData, capability);
945
911
  }
946
912
  }]
947
913
  ]
948
914
  };
949
915
  ```
950
916
  ## Send Email
951
- Simply send email with [nodemailer](https://nodemailer.com), check example: [send-email.js](/tests/common/send-email.js)
917
+ Simply send email with [nodemailer](https://nodemailer.com), check example: [send-email](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/send-email)
952
918
 
953
919
  ![](/docs/email.png)
954
920
 
955
921
 
956
922
  ## Testrail Integration
957
- Send results to your Testrail with [testrail-api](https://github.com/rundef/node-testrail-api), check example: [testrail.js](/tests/common/testrail.js)
923
+ Send test results to your Testrail, check example: [testrail](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/testrail)
958
924
 
959
925
  ![](/docs/testrail.png)
960
926
 
961
927
  ## Jira + Zephyr Scale Integration
962
- Create test cycle and executions with [zephyr-scale-api](https://support.smartbear.com/zephyr-scale-cloud/api-docs/), check example: [zephyr-scale.js](/tests/common/zephyr-scale.js)
928
+ Create test cycle and executions with [zephyr-scale-api](https://support.smartbear.com/zephyr-scale-cloud/api-docs/), check example: [zephyr-scale](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/zephyr-scale)
963
929
 
964
930
  ![](/docs/zephyr.png)
965
931
 
966
932
  ## Jira + Xray Integration
967
- check example: [xray.js](/tests/common/xray.js)
968
933
  - Import test execution results with [Xray REST API](https://docs.getxray.app/display/XRAYCLOUD/REST+API)
969
934
  - Update Jira issue status with [Jira Transition API](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-transitions-post)
935
+ check example: [xray](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/xray)
970
936
 
971
937
  ![](/docs/xray.png)
972
938
 
973
-
974
939
  ## Slack Integration
975
- 1. Simply send message with [@slack/webhook](https://github.com/slackapi/node-slack-sdk), example: [slack-webhook.js](/tests/common/slack-webhook.js)
976
- 2. Recommended: Post chat message and upload image with [@slack/web-api](https://github.com/slackapi/node-slack-sdk), example: [slack-web-api.js](/tests/common/slack-web-api.js)
940
+ 1. Simply send message with [@slack/webhook](https://github.com/slackapi/node-slack-sdk), example: [slack-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/slack-webhook)
941
+ 2. Recommended: Post chat message and upload image with [@slack/web-api](https://github.com/slackapi/node-slack-sdk), example: [slack-web-api](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/slack-web-api)
977
942
 
978
943
  ![](/docs/slack.png)
979
944
 
980
945
  ## Discord Integration
981
- Using [Discord webhooks](https://discord.com/developers/docs/resources/webhook) to post messages to channels. example: [discord-webhook.js](/tests/common/discord-webhook.js)
946
+ Using [Discord webhooks](https://discord.com/developers/docs/resources/webhook) to post messages to channels. example: [discord-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/discord-webhook)
982
947
 
983
948
  ![](/docs/discord.png)
984
949
 
985
950
  ## Teams Integration
986
- Please create an [Incoming Webhooks](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) for the channel first. example: [teams-webhook.js](/tests/common/teams-webhook.js)
951
+ Please create an [Incoming Webhooks](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) for the channel first. example: [teams-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/teams-webhook)
987
952
 
988
953
  ![](/docs/teams.png)
989
954
 
990
955
  ## Dingtalk/Weixin/Feishu Integration
991
- - [dingtalk-webhook.js](/tests/common/dingtalk-webhook.js)
992
- - [weixin-webhook.js](/tests/common/weixin-webhook.js)
993
- - [feishu-webhook.js](/tests/common/feishu-webhook.js)
956
+ - [dingtalk-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/dingtalk-webhook)
957
+ - [weixin-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/weixin-webhook)
958
+ - [feishu-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/feishu-webhook)
994
959
 
995
960
  ## Dependencies
996
961
  - UI Framework [Vue 3](https://github.com/vuejs/core)
@@ -16,9 +16,9 @@ const getReportName = (options, config, metadata) => {
16
16
  };
17
17
 
18
18
  const artifactsHandler = async (visitor, options) => {
19
- const artifacts = [];
20
- const { coverage, network } = visitor.artifacts;
21
- visitor.artifacts = null;
19
+ const artifacts = [].concat(visitor.artifacts);
20
+ // global artifacts
21
+ const { coverage, network } = visitor.artifactDataMap;
22
22
  if (coverage) {
23
23
  const report = await generateCoverageReport(coverage, options);
24
24
  artifacts.push(report);
@@ -55,22 +55,26 @@ const showTestResults = (reportData) => {
55
55
 
56
56
  const summary = reportData.summary;
57
57
 
58
- const colorHandler = (item, v) => {
59
- if (item.id === 'failed') {
60
- if (item.value > 0) {
61
- v = EC.red(v);
62
- }
58
+ const colorHandler = (item, row) => {
63
59
 
64
- } else if (item.id === 'flaky') {
65
- if (item.value > 0) {
66
- v = EC.yellow(v);
67
- }
68
- } else if (item.id === 'passed') {
60
+ if (['failed', 'errors'].includes(item.id) && item.value > 0) {
61
+ row.name = EC.red(row.name);
62
+ row.value = EC.red(row.value);
63
+ return;
64
+ }
65
+
66
+ if (['flaky', 'retries'].includes(item.id) && item.value > 0) {
67
+ row.name = EC.yellow(row.name);
68
+ row.value = EC.yellow(row.value);
69
+ return;
70
+ }
71
+
72
+ if (item.id === 'passed') {
69
73
  if (summary.failed.value === 0 && summary.passed.value > 0) {
70
- v = EC.green(v);
74
+ row.name = EC.green(row.name);
75
+ row.value = EC.green(row.value);
71
76
  }
72
77
  }
73
- return v;
74
78
  };
75
79
 
76
80
  let rows = [];
@@ -82,9 +86,12 @@ const showTestResults = (reportData) => {
82
86
  if (caseTypes.includes(item.id) || suiteSubs.includes(item.id)) {
83
87
  return;
84
88
  }
85
- rows.push({
89
+
90
+ const row = {
86
91
  ... item
87
- });
92
+ };
93
+ colorHandler(item, row);
94
+ rows.push(row);
88
95
  });
89
96
 
90
97
  const tests = rows.find((it) => it.id === 'tests');
@@ -94,10 +101,12 @@ const showTestResults = (reportData) => {
94
101
  };
95
102
  const value = `${item.value}`.padEnd(`${tests.value}`.length, ' ');
96
103
  const percent = `(${item.percent})`;
97
- return {
98
- name: colorHandler(item, item.name),
99
- value: colorHandler(item, `${value} ${percent}`)
104
+ const row = {
105
+ name: item.name,
106
+ value: `${value} ${percent}`
100
107
  };
108
+ colorHandler(item, row);
109
+ return row;
101
110
  });
102
111
 
103
112
  const suites = rows.find((it) => it.id === 'suites');
@@ -143,11 +152,10 @@ const generateReport = async (reportData, options) => {
143
152
 
144
153
  if (artifacts) {
145
154
  artifacts.forEach((report) => {
146
- console.log(`[MCR] ${report.type} report: ${EC.cyan(report.htmlPath)}`);
147
-
148
- // convert htmlPath to relative reporter
149
- report.htmlPath = Util.relativePath(report.htmlPath, outputDir);
150
-
155
+ const g = report.global ? `${EC.magenta('(global)')}` : '';
156
+ console.log(`[MCR] ${report.name}: ${EC.cyan(report.path)} ${report.title} ${g}`);
157
+ // convert path to relative reporter
158
+ report.path = Util.relativePath(report.path, outputDir);
151
159
  });
152
160
  }
153
161
 
package/lib/index.js CHANGED
@@ -43,6 +43,10 @@ class Reporter {
43
43
  this.tickStart();
44
44
  }
45
45
 
46
+ printsToStdio() {
47
+ return false;
48
+ }
49
+
46
50
  tickStart() {
47
51
  this.tick_time_id = setTimeout(async () => {
48
52
  const tickInfo = await getTickInfo();
@@ -70,7 +70,10 @@ const attachAuditReport = async (runnerResult, testInfo, options = {}) => {
70
70
  return;
71
71
  }
72
72
 
73
+ const title = options.title || `Lighthouse Report - ${testInfo.title}`;
74
+
73
75
  options = {
76
+ title,
74
77
  outputDir: Util.resolveOutputDir(testInfo),
75
78
  outputName: `audit-${Util.shortTestId(testInfo.testId)}`,
76
79
 
@@ -86,7 +89,10 @@ const attachAuditReport = async (runnerResult, testInfo, options = {}) => {
86
89
  options.htmlDir = htmlDir;
87
90
 
88
91
  // `.lhr` is the Lighthouse Result as a JS object
89
- const report = getSummaryReport(runnerResult.lhr);
92
+ const report = {
93
+ title,
94
+ ... getSummaryReport(runnerResult.lhr)
95
+ };
90
96
 
91
97
  const htmlPath = path.resolve(htmlDir, 'index.html');
92
98
  // `.report` is the HTML report as a string
@@ -67,6 +67,13 @@ const getSourcePath = (url, index = '', type = '') => {
67
67
  return filterPath(relPath);
68
68
  };
69
69
 
70
+ const mergeSourceRoot = (sourceRoot, sourceName) => {
71
+ if (sourceName.startsWith(sourceRoot)) {
72
+ return sourceName;
73
+ }
74
+ return sourceRoot + sourceName;
75
+ };
76
+
70
77
  // ================================================================================================
71
78
 
72
79
  const request = async (options) => {
@@ -150,5 +157,6 @@ const collectSourceMaps = async (v8list) => {
150
157
  module.exports = {
151
158
  sortRanges,
152
159
  getSourcePath,
160
+ mergeSourceRoot,
153
161
  collectSourceMaps
154
162
  };
@@ -15,6 +15,10 @@ const {
15
15
  // ========================================================================================================
16
16
 
17
17
  const defaultV8Options = {
18
+
19
+ // Defaults to test title
20
+ // title: '',
21
+
18
22
  // (Boolean) Whether to convert to Istanbul report
19
23
  toIstanbul: false,
20
24
 
@@ -36,6 +40,9 @@ const defaultV8Options = {
36
40
 
37
41
  const defaultIstanbulOptions = {
38
42
 
43
+ // Defaults to test title
44
+ // title: '',
45
+
39
46
  // when toIstanbul = true
40
47
  entryFilter: null,
41
48
  unpackSourceMap: true,
@@ -129,8 +136,10 @@ const attachCoverageReport = (coverageInput, testInfo, options = {}) => {
129
136
  return;
130
137
  }
131
138
 
139
+ const title = options.title || `Coverage Report - ${testInfo.title}`;
140
+
132
141
  options = {
133
- title: `Coverage Report - ${testInfo.title}`,
142
+ title,
134
143
  outputDir: Util.resolveOutputDir(testInfo),
135
144
  outputName: `coverage-${Util.shortTestId(testInfo.testId)}`,
136
145
  ... options
@@ -276,10 +285,11 @@ const generateCoverageReport = async (dataList, reporterOptions) => {
276
285
  const report = await generateGlobalCoverageReport(dataList, options);
277
286
 
278
287
  return {
279
- type: 'coverage',
280
- name: 'Coverage',
281
- htmlPath: report.htmlPath,
282
- summary: report.summary
288
+ global: true,
289
+ name: 'coverage',
290
+ path: report.htmlPath,
291
+ summary: report.summary,
292
+ title: options.title
283
293
  };
284
294
  };
285
295
 
@@ -4,6 +4,7 @@ const EC = require('eight-colors');
4
4
 
5
5
  const istanbulReports = require('istanbul-reports');
6
6
 
7
+ const Util = require('../../../utils/util.js');
7
8
  const IstanbulSummary = require('./istanbul-summary.js');
8
9
 
9
10
  const {
@@ -17,7 +18,9 @@ const {
17
18
  // const istanbulLibCoverage = require('istanbul-lib-coverage');
18
19
  // const istanbulLibReport = require('istanbul-lib-report');
19
20
 
20
- const { getSourcePath, collectSourceMaps } = require('../coverage-utils.js');
21
+ const {
22
+ getSourcePath, mergeSourceRoot, collectSourceMaps
23
+ } = require('../coverage-utils.js');
21
24
 
22
25
 
23
26
  const saveIstanbulReport = (coverageData, fileSources, options) => {
@@ -74,6 +77,8 @@ const saveIstanbulReport = (coverageData, fileSources, options) => {
74
77
  const htmlReport = istanbulReports.create('html', {});
75
78
  htmlReport.execute(context);
76
79
 
80
+ const htmlPath = Util.relativePath(path.resolve(options.htmlDir, 'index.html'));
81
+
77
82
  if (options.lcov) {
78
83
  const lcovReport = istanbulReports.create('lcovonly', {});
79
84
  lcovReport.execute(context);
@@ -82,7 +87,12 @@ const saveIstanbulReport = (coverageData, fileSources, options) => {
82
87
  // add watermarks and color
83
88
  const coverageReport = new IstanbulSummary();
84
89
  coverageReport.execute(context);
85
- const report = coverageReport.getReport();
90
+ const report = {
91
+ title: options.title,
92
+ htmlPath,
93
+ watermarks: contextOptions.watermarks,
94
+ ... coverageReport.getReport()
95
+ };
86
96
 
87
97
  return report;
88
98
  };
@@ -141,9 +151,14 @@ const getConversionSources = (item, fileSources) => {
141
151
  // 'webpack://monocart-v8/external umd "monocart-code-viewer"'
142
152
  // format the url to sourcePath
143
153
 
154
+ // reset sourceRoot
155
+ const sourceRoot = sourceMap.sourceRoot || '';
156
+ sourceMap.sourceRoot = '';
157
+
144
158
  // resolve source path and add to file sources cache for html report sourceFinder
145
159
  sourceMap.sources = sourceMap.sources.map((sourceName, i) => {
146
- const newSourceName = getSourcePath(sourceName, i + 1);
160
+ const sourceUrl = mergeSourceRoot(sourceRoot, sourceName);
161
+ const newSourceName = getSourcePath(sourceUrl, i + 1);
147
162
  fileSources[newSourceName] = sourceMap.sourcesContent[i];
148
163
  return newSourceName;
149
164
  });
@@ -29,10 +29,6 @@ class PositionMapping {
29
29
  this.sourceName = sourceName;
30
30
  this.lines = this.getLines(source);
31
31
  this.ranges = [];
32
- this.range = {
33
- start: 0,
34
- end: 0
35
- };
36
32
  }
37
33
 
38
34
  // =============================================================================