@testomatio/reporter 1.6.0-beta-2-artifacts → 2.0.0-beta-esm

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.
Files changed (97) hide show
  1. package/lib/adapter/codecept.js +288 -330
  2. package/lib/adapter/cucumber/current.js +195 -203
  3. package/lib/adapter/cucumber/legacy.js +130 -155
  4. package/lib/adapter/cucumber.js +5 -16
  5. package/lib/adapter/cypress-plugin/index.js +91 -105
  6. package/lib/adapter/jasmine/jasmine.js +63 -0
  7. package/lib/adapter/jasmine.js +54 -53
  8. package/lib/adapter/jest.js +97 -99
  9. package/lib/adapter/mocha/mocha.js +125 -0
  10. package/lib/adapter/mocha.js +111 -140
  11. package/lib/adapter/playwright.js +168 -200
  12. package/lib/adapter/vitest.js +144 -143
  13. package/lib/adapter/webdriver.js +113 -97
  14. package/lib/bin/reportXml.js +49 -49
  15. package/lib/bin/startTest.js +80 -97
  16. package/lib/client.js +344 -385
  17. package/lib/config.js +16 -21
  18. package/lib/constants.js +49 -43
  19. package/lib/data-storage.js +206 -188
  20. package/lib/fileUploader.js +245 -0
  21. package/lib/junit-adapter/adapter.js +17 -20
  22. package/lib/junit-adapter/csharp.js +18 -14
  23. package/lib/junit-adapter/index.js +27 -25
  24. package/lib/junit-adapter/java.js +41 -53
  25. package/lib/junit-adapter/javascript.js +30 -27
  26. package/lib/junit-adapter/python.js +38 -37
  27. package/lib/junit-adapter/ruby.js +11 -8
  28. package/lib/output.js +44 -52
  29. package/lib/package.json +1 -0
  30. package/lib/pipe/bitbucket.js +208 -227
  31. package/lib/pipe/csv.js +111 -124
  32. package/lib/pipe/github.js +184 -211
  33. package/lib/pipe/gitlab.js +164 -205
  34. package/lib/pipe/html.js +253 -312
  35. package/lib/pipe/index.js +83 -63
  36. package/lib/pipe/testomatio.js +391 -454
  37. package/lib/reporter-functions.js +16 -20
  38. package/lib/reporter.js +47 -17
  39. package/lib/services/artifacts.js +55 -51
  40. package/lib/services/index.js +14 -12
  41. package/lib/services/key-values.js +56 -53
  42. package/lib/services/logger.js +227 -245
  43. package/lib/utils/chalk.js +10 -0
  44. package/lib/utils/pipe_utils.js +91 -84
  45. package/lib/utils/utils.js +289 -273
  46. package/lib/xmlReader.js +480 -519
  47. package/package.json +57 -19
  48. package/src/adapter/codecept.js +369 -0
  49. package/src/adapter/cucumber/current.js +228 -0
  50. package/src/adapter/cucumber/legacy.js +158 -0
  51. package/src/adapter/cucumber.js +4 -0
  52. package/src/adapter/cypress-plugin/index.js +110 -0
  53. package/src/adapter/jasmine.js +60 -0
  54. package/src/adapter/jest.js +107 -0
  55. package/src/adapter/mocha.cjs +2 -0
  56. package/src/adapter/mocha.js +156 -0
  57. package/src/adapter/playwright.js +222 -0
  58. package/src/adapter/vitest.js +183 -0
  59. package/src/adapter/webdriver.js +111 -0
  60. package/src/bin/reportXml.js +67 -0
  61. package/src/bin/startTest.js +119 -0
  62. package/src/client.js +423 -0
  63. package/src/config.js +30 -0
  64. package/src/constants.js +49 -0
  65. package/src/data-storage.js +204 -0
  66. package/src/fileUploader.js +307 -0
  67. package/src/junit-adapter/adapter.js +23 -0
  68. package/src/junit-adapter/csharp.js +16 -0
  69. package/src/junit-adapter/index.js +28 -0
  70. package/src/junit-adapter/java.js +58 -0
  71. package/src/junit-adapter/javascript.js +31 -0
  72. package/src/junit-adapter/python.js +42 -0
  73. package/src/junit-adapter/ruby.js +10 -0
  74. package/src/output.js +57 -0
  75. package/src/pipe/bitbucket.js +254 -0
  76. package/src/pipe/csv.js +140 -0
  77. package/src/pipe/github.js +234 -0
  78. package/src/pipe/gitlab.js +229 -0
  79. package/src/pipe/html.js +366 -0
  80. package/src/pipe/index.js +73 -0
  81. package/src/pipe/testomatio.js +498 -0
  82. package/src/reporter-functions.js +44 -0
  83. package/src/reporter.cjs +22 -0
  84. package/src/reporter.js +24 -0
  85. package/src/services/artifacts.js +59 -0
  86. package/src/services/index.js +13 -0
  87. package/src/services/key-values.js +59 -0
  88. package/src/services/logger.js +314 -0
  89. package/src/template/emptyData.svg +23 -0
  90. package/src/template/testomatio.hbs +1421 -0
  91. package/src/utils/chalk.js +13 -0
  92. package/src/utils/pipe_utils.js +127 -0
  93. package/src/utils/utils.js +341 -0
  94. package/src/xmlReader.js +551 -0
  95. package/lib/bin/cli.js +0 -216
  96. package/lib/bin/uploadArtifacts.js +0 -86
  97. package/lib/uploader.js +0 -312
@@ -1,13 +1,18 @@
1
- const debug = require('debug')('@testomatio/reporter:pipe:github');
2
- const path = require('path');
3
- const chalk = require('chalk');
4
- const humanizeDuration = require('humanize-duration');
5
- const merge = require('lodash.merge');
6
- const { Octokit } = require('@octokit/rest');
7
- const { APP_PREFIX, testomatLogoURL } = require('../constants');
8
- const { ansiRegExp, isSameTest } = require('../utils/utils');
9
- const { statusEmoji, fullName } = require('../utils/pipe_utils');
10
-
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const debug_1 = __importDefault(require("debug"));
7
+ const path_1 = __importDefault(require("path"));
8
+ const picocolors_1 = __importDefault(require("picocolors"));
9
+ const humanize_duration_1 = __importDefault(require("humanize-duration"));
10
+ const lodash_merge_1 = __importDefault(require("lodash.merge"));
11
+ const rest_1 = require("@octokit/rest");
12
+ const constants_js_1 = require("../constants.js");
13
+ const utils_js_1 = require("../utils/utils.js");
14
+ const pipe_utils_js_1 = require("../utils/pipe_utils.js");
15
+ const debug = (0, debug_1.default)('@testomatio/reporter:pipe:github');
11
16
  /**
12
17
  * @typedef {import('../../types').Pipe} Pipe
13
18
  * @typedef {import('../../types').TestData} TestData
@@ -15,217 +20,185 @@ const { statusEmoji, fullName } = require('../utils/pipe_utils');
15
20
  * @implements {Pipe}
16
21
  */
17
22
  class GitHubPipe {
18
- constructor(params, store = {}) {
19
- this.isEnabled = false;
20
- this.store = store;
21
- this.tests = [];
22
- this.token = params.GH_PAT || process.env.GH_PAT;
23
- this.ref = process.env.GITHUB_REF;
24
- this.repo = process.env.GITHUB_REPOSITORY;
25
- this.jobKey = `${process.env.GITHUB_WORKFLOW || ''} / ${process.env.GITHUB_JOB || ''}`;
26
- this.hiddenCommentData = `<!--- testomat.io report ${this.jobKey} -->`;
27
-
28
- debug('GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', 'Ref:', this.ref, 'Repo:', this.repo);
29
-
30
- if (!this.token || !this.ref || !this.repo) return;
31
- this.isEnabled = true;
32
- const matchedIssue = this.ref.match(/refs\/pull\/(\d+)\/merge/);
33
- if (!matchedIssue) return;
34
- this.issue = parseInt(matchedIssue[1], 10);
35
-
36
- this.start = new Date();
37
-
38
- debug('GitHub Pipe: Enabled');
39
- }
40
-
41
- // TODO: to using SET opts as argument => prepareRun(opts)
42
- async prepareRun() {}
43
-
44
- async createRun() {}
45
-
46
- addTest(test) {
47
- if (!this.isEnabled) return;
48
- debug('Adding test:', test);
49
-
50
- const index = this.tests.findIndex(t => isSameTest(t, test));
51
- // update if they were already added
52
- if (index >= 0) {
53
- this.tests[index] = merge(this.tests[index], test);
54
- return;
23
+ constructor(params, store = {}) {
24
+ this.isEnabled = false;
25
+ this.store = store;
26
+ this.tests = [];
27
+ this.token = params.GH_PAT || process.env.GH_PAT;
28
+ this.ref = process.env.GITHUB_REF;
29
+ this.repo = process.env.GITHUB_REPOSITORY;
30
+ this.jobKey = `${process.env.GITHUB_WORKFLOW || ''} / ${process.env.GITHUB_JOB || ''}`;
31
+ this.hiddenCommentData = `<!--- testomat.io report ${this.jobKey} -->`;
32
+ debug('GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', 'Ref:', this.ref, 'Repo:', this.repo);
33
+ if (!this.token || !this.ref || !this.repo)
34
+ return;
35
+ this.isEnabled = true;
36
+ const matchedIssue = this.ref.match(/refs\/pull\/(\d+)\/merge/);
37
+ if (!matchedIssue)
38
+ return;
39
+ this.issue = parseInt(matchedIssue[1], 10);
40
+ this.start = new Date();
41
+ debug('GitHub Pipe: Enabled');
55
42
  }
56
-
57
- this.tests.push(test);
58
- }
59
-
60
- async finishRun(runParams) {
61
- if (!this.isEnabled) return;
62
- if (!this.issue) return;
63
-
64
- if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
65
-
66
- this.octokit = new Octokit({
67
- auth: this.token,
68
- });
69
-
70
- const [owner, repo] = (this.repo || '').split('/');
71
- if (!(owner || repo)) return;
72
-
73
- // ... create a comment on GitHub
74
- const passedCount = this.tests.filter(t => t.status === 'passed').length;
75
- const failedCount = this.tests.filter(t => t.status === 'failed').length;
76
- const skippedCount = this.tests.filter(t => t.status === 'skipped').length;
77
-
78
- let summary = `${this.hiddenCommentData}
79
-
80
- | [![Testomat.io Report](${testomatLogoURL})](https://testomat.io) | ${statusEmoji(
81
- runParams.status,
82
- )} ${`${process.env.GITHUB_JOB} ${runParams.status}`.toUpperCase()} |
43
+ // TODO: to using SET opts as argument => prepareRun(opts)
44
+ async prepareRun() { }
45
+ async createRun() { }
46
+ addTest(test) {
47
+ if (!this.isEnabled)
48
+ return;
49
+ debug('Adding test:', test);
50
+ const index = this.tests.findIndex(t => (0, utils_js_1.isSameTest)(t, test));
51
+ // update if they were already added
52
+ if (index >= 0) {
53
+ this.tests[index] = (0, lodash_merge_1.default)(this.tests[index], test);
54
+ return;
55
+ }
56
+ this.tests.push(test);
57
+ }
58
+ async finishRun(runParams) {
59
+ if (!this.isEnabled)
60
+ return;
61
+ if (!this.issue)
62
+ return;
63
+ if (runParams.tests)
64
+ runParams.tests.forEach(t => this.addTest(t));
65
+ this.octokit = new rest_1.Octokit({
66
+ auth: this.token,
67
+ });
68
+ const [owner, repo] = (this.repo || '').split('/');
69
+ if (!(owner || repo))
70
+ return;
71
+ // ... create a comment on GitHub
72
+ const passedCount = this.tests.filter(t => t.status === 'passed').length;
73
+ const failedCount = this.tests.filter(t => t.status === 'failed').length;
74
+ const skippedCount = this.tests.filter(t => t.status === 'skipped').length;
75
+ let summary = `${this.hiddenCommentData}
76
+
77
+ | [![Testomat.io Report](${constants_js_1.testomatLogoURL})](https://testomat.io) | ${(0, pipe_utils_js_1.statusEmoji)(runParams.status)} ${`${process.env.GITHUB_JOB} ${runParams.status}`.toUpperCase()} |
83
78
  | --- | --- |
84
79
  | Tests | ✔️ **${this.tests.length}** tests run |
85
- | Summary | ${failedCount ? `${statusEmoji('failed')} **${failedCount}** failed; ` : ''} ${statusEmoji(
86
- 'passed',
87
- )} **${passedCount}** passed; **${statusEmoji('skipped')}** ${skippedCount} skipped |
88
- | Duration | 🕐 **${humanizeDuration(
89
- parseInt(
90
- this.tests.reduce((a, t) => a + (t.run_time || 0), 0),
91
- 10,
92
- ),
93
- {
94
- maxDecimalPoints: 0,
95
- },
96
- )}** |`;
97
-
98
- if (this.store.runUrl) {
99
- summary += `\n| Testomat.io Report | 📊 [Run #${this.store.runId}](${this.store.runUrl}) | `;
100
- }
101
- if (process.env.GITHUB_WORKFLOW) {
102
- summary += `\n| Job | 🗂️ [${this.jobKey}](${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${
103
- this.repo
104
- }/actions/runs/${process.env.GITHUB_RUN_ID}) | `;
105
- }
106
- if (process.env.RUNNER_OS) {
107
- summary += `\n| Operating System | 🖥️ \`${process.env.RUNNER_OS}\` ${process.env.RUNNER_ARCH || ''} | `;
108
- }
109
-
110
- const failures = this.tests
111
- .filter(t => t.status === 'failed')
112
- .slice(0, 20)
113
- .map(t => {
114
- let text = `#### ${statusEmoji('failed')} ${fullName(t)} `;
115
- text += '\n\n';
116
- if (t.message)
117
- text += `> ${t.message
118
- .replace(/[^\x20-\x7E]/g, '')
119
- .replace(ansiRegExp(), '')
120
- .trim()}\n`;
121
- if (t.stack) text += `\`\`\`diff\n${t.stack.replace(ansiRegExp(), '').trim()}\n\`\`\`\n`;
122
-
123
- if (t.artifacts && t.artifacts.length && !process.env.TESTOMATIO_PRIVATE_ARTIFACTS) {
124
- t.artifacts
125
- .filter(f => !!f)
126
- .filter(f => f.endsWith('.png'))
127
- .forEach(f => {
128
- if (f.endsWith('.png')) {
129
- text += `![](${f})\n`;
130
- return text;
131
- }
132
- text += `[📄 ${path.basename(f)}](${f})\n`;
133
- return text;
80
+ | Summary | ${failedCount ? `${(0, pipe_utils_js_1.statusEmoji)('failed')} **${failedCount}** failed; ` : ''} ${(0, pipe_utils_js_1.statusEmoji)('passed')} **${passedCount}** passed; **${(0, pipe_utils_js_1.statusEmoji)('skipped')}** ${skippedCount} skipped |
81
+ | Duration | 🕐 **${(0, humanize_duration_1.default)(parseInt(this.tests.reduce((a, t) => a + (t.run_time || 0), 0), 10), {
82
+ maxDecimalPoints: 0,
83
+ })}** |`;
84
+ if (this.store.runUrl) {
85
+ summary += `\n| Testomat.io Report | 📊 [Run #${this.store.runId}](${this.store.runUrl}) | `;
86
+ }
87
+ if (process.env.GITHUB_WORKFLOW) {
88
+ summary += `\n| Job | 🗂️ [${this.jobKey}](${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${this.repo}/actions/runs/${process.env.GITHUB_RUN_ID}) | `;
89
+ }
90
+ if (process.env.RUNNER_OS) {
91
+ summary += `\n| Operating System | 🖥️ \`${process.env.RUNNER_OS}\` ${process.env.RUNNER_ARCH || ''} | `;
92
+ }
93
+ const failures = this.tests
94
+ .filter(t => t.status === 'failed')
95
+ .slice(0, 20)
96
+ .map(t => {
97
+ let text = `#### ${(0, pipe_utils_js_1.statusEmoji)('failed')} ${(0, pipe_utils_js_1.fullName)(t)} `;
98
+ text += '\n\n';
99
+ if (t.message)
100
+ text += `> ${t.message
101
+ .replace(/[^\x20-\x7E]/g, '')
102
+ .replace((0, utils_js_1.ansiRegExp)(), '')
103
+ .trim()}\n`;
104
+ if (t.stack)
105
+ text += `\`\`\`diff\n${t.stack.replace((0, utils_js_1.ansiRegExp)(), '').trim()}\n\`\`\`\n`;
106
+ if (t.artifacts && t.artifacts.length && !process.env.TESTOMATIO_PRIVATE_ARTIFACTS) {
107
+ t.artifacts
108
+ .filter(f => !!f)
109
+ .filter(f => f.endsWith('.png'))
110
+ .forEach(f => {
111
+ if (f.endsWith('.png')) {
112
+ text += `![](${f})\n`;
113
+ return text;
114
+ }
115
+ text += `[📄 ${path_1.default.basename(f)}](${f})\n`;
116
+ return text;
117
+ });
118
+ }
119
+ text += '\n---\n';
120
+ return text;
121
+ });
122
+ let body = summary;
123
+ if (failures.length) {
124
+ body += `\n<details>\n<summary><h3>🟥 Failures (${failures.length})</h4></summary>\n\n${failures.join('\n')}\n`;
125
+ if (failures.length > 20) {
126
+ body += '\n> Notice\n> Only first 20 failures shown*';
127
+ }
128
+ body += '\n\n</details>';
129
+ }
130
+ if (this.tests.length > 0) {
131
+ body += '\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n';
132
+ body += this.tests
133
+ // eslint-disable-next-line no-unsafe-optional-chaining
134
+ .sort((a, b) => b?.run_time - a?.run_time)
135
+ .slice(0, 5)
136
+ .map(t => `* ${(0, pipe_utils_js_1.fullName)(t)} (${(0, humanize_duration_1.default)(parseFloat(t.run_time))})`)
137
+ .join('\n');
138
+ body += '\n</details>';
139
+ }
140
+ await deletePreviousReport(this.octokit, owner, repo, this.issue, this.hiddenCommentData);
141
+ // add report as comment
142
+ try {
143
+ debug('Adding comment\n', body);
144
+ const resp = await this.octokit.rest.issues.createComment({
145
+ owner,
146
+ repo,
147
+ issue_number: this.issue,
148
+ body,
134
149
  });
150
+ const url = resp.data?.html_url;
151
+ debug('Comment URL:', url);
152
+ this.store.githubUrl = url;
153
+ console.log(constants_js_1.APP_PREFIX, picocolors_1.default.yellow('GitHub'), `Report created: ${picocolors_1.default.magenta(url)}`);
154
+ }
155
+ catch (err) {
156
+ console.log(constants_js_1.APP_PREFIX, picocolors_1.default.yellow('GitHub'), `Couldn't create GitHub report ${err}`);
135
157
  }
136
-
137
- text += '\n---\n';
138
-
139
- return text;
140
- });
141
-
142
- let body = summary;
143
-
144
- if (failures.length) {
145
- body += `\n<details>\n<summary><h3>🟥 Failures (${failures.length})</h4></summary>\n\n${failures.join('\n')}\n`;
146
- if (failures.length > 20) {
147
- body += '\n> Notice\n> Only first 20 failures shown*';
148
- }
149
- body += '\n\n</details>';
150
158
  }
151
-
152
- if (this.tests.length > 0) {
153
- body += '\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n';
154
- body += this.tests
155
- // eslint-disable-next-line no-unsafe-optional-chaining
156
- .sort((a, b) => b?.run_time - a?.run_time)
157
- .slice(0, 5)
158
- .map(t => `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`)
159
- .join('\n');
160
- body += '\n</details>';
159
+ toString() {
160
+ return 'GitHub Reporter';
161
161
  }
162
-
163
- await deletePreviousReport(this.octokit, owner, repo, this.issue, this.hiddenCommentData);
164
-
165
- // add report as comment
166
- try {
167
- debug('Adding comment\n', body);
168
- const resp = await this.octokit.rest.issues.createComment({
169
- owner,
170
- repo,
171
- issue_number: this.issue,
172
- body,
173
- });
174
-
175
- const url = resp.data?.html_url;
176
- debug('Comment URL:', url);
177
- this.store.githubUrl = url;
178
-
179
- console.log(APP_PREFIX, chalk.yellow('GitHub'), `Report created: ${chalk.magenta(url)}`);
180
- } catch (err) {
181
- console.log(APP_PREFIX, chalk.yellow('GitHub'), `Couldn't create GitHub report ${err}`);
182
- }
183
- }
184
-
185
- toString() {
186
- return 'GitHub Reporter';
187
- }
188
162
  }
189
-
190
163
  async function deletePreviousReport(octokit, owner, repo, issue, hiddenCommentData) {
191
- if (process.env.GH_KEEP_OUTDATED_REPORTS) return;
192
-
193
- // get comments
194
- let comments = [];
195
- try {
196
- const response = await octokit.rest.issues.listComments({
197
- owner,
198
- repo,
199
- issue_number: issue,
200
- });
201
- comments = response.data;
202
- } catch (e) {
203
- console.error('Error while attempt to retrieve comments on GitHub Pull Request:\n', e);
204
- }
205
-
206
- if (!comments.length) return;
207
-
208
- for (const comment of comments) {
209
- // if comment was left by the same workflow
210
- if (comment.body.includes(hiddenCommentData)) {
211
- try {
212
- // delete previous comment
213
- await octokit.rest.issues.deleteComment({
214
- owner,
215
- repo,
216
- issue_number: issue,
217
- comment_id: comment.id,
164
+ if (process.env.GH_KEEP_OUTDATED_REPORTS)
165
+ return;
166
+ // get comments
167
+ let comments = [];
168
+ try {
169
+ const response = await octokit.rest.issues.listComments({
170
+ owner,
171
+ repo,
172
+ issue_number: issue,
218
173
  });
219
- } catch (e) {
220
- console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
221
- }
222
-
223
- // pass next env var if need to clear all previous reports;
224
- // only the last one is removed by default
225
- if (!process.env.GITHUB_REMOVE_ALL_OUTDATED_REPORTS) break;
226
- // TODO: in case of many reports should implement pagination
174
+ comments = response.data;
175
+ }
176
+ catch (e) {
177
+ console.error('Error while attempt to retrieve comments on GitHub Pull Request:\n', e);
178
+ }
179
+ if (!comments.length)
180
+ return;
181
+ for (const comment of comments) {
182
+ // if comment was left by the same workflow
183
+ if (comment.body.includes(hiddenCommentData)) {
184
+ try {
185
+ // delete previous comment
186
+ await octokit.rest.issues.deleteComment({
187
+ owner,
188
+ repo,
189
+ issue_number: issue,
190
+ comment_id: comment.id,
191
+ });
192
+ }
193
+ catch (e) {
194
+ console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
195
+ }
196
+ // pass next env var if need to clear all previous reports;
197
+ // only the last one is removed by default
198
+ if (!process.env.GITHUB_REMOVE_ALL_OUTDATED_REPORTS)
199
+ break;
200
+ // TODO: in case of many reports should implement pagination
201
+ }
227
202
  }
228
- }
229
203
  }
230
-
231
204
  module.exports = GitHubPipe;