@testomatio/reporter 2.0.1-beta.3 → 2.0.1-beta.5-timestamp
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/lib/adapter/codecept.js +335 -293
- package/lib/adapter/cucumber/current.js +203 -195
- package/lib/adapter/cucumber/legacy.js +155 -130
- package/lib/adapter/cucumber.js +16 -5
- package/lib/adapter/cypress-plugin/index.js +105 -91
- package/lib/adapter/jasmine.js +53 -54
- package/lib/adapter/jest.js +99 -97
- package/lib/adapter/mocha.js +141 -112
- package/lib/adapter/playwright.js +231 -199
- package/lib/adapter/vitest.js +149 -150
- package/lib/adapter/webdriver.js +121 -144
- package/lib/bin/cli.js +211 -229
- package/lib/bin/reportXml.js +52 -51
- package/lib/bin/startTest.js +95 -83
- package/lib/bin/uploadArtifacts.js +61 -56
- package/lib/client.js +465 -424
- package/lib/config.js +23 -18
- package/lib/constants.js +44 -50
- package/lib/data-storage.js +188 -216
- package/lib/junit-adapter/adapter.js +20 -17
- package/lib/junit-adapter/csharp.js +14 -28
- package/lib/junit-adapter/index.js +25 -27
- package/lib/junit-adapter/java.js +53 -41
- package/lib/junit-adapter/javascript.js +27 -30
- package/lib/junit-adapter/python.js +37 -38
- package/lib/junit-adapter/ruby.js +8 -11
- package/lib/output.js +52 -44
- package/lib/pipe/bitbucket.js +230 -223
- package/lib/pipe/csv.js +126 -113
- package/lib/pipe/debug.js +99 -118
- package/lib/pipe/github.js +213 -218
- package/lib/pipe/gitlab.js +206 -183
- package/lib/pipe/html.js +321 -258
- package/lib/pipe/index.js +66 -94
- package/lib/pipe/testomatio.js +474 -429
- package/lib/reporter-functions.js +26 -28
- package/lib/reporter.js +29 -34
- package/lib/services/artifacts.js +51 -55
- package/lib/services/index.js +12 -14
- package/lib/services/key-values.js +53 -56
- package/lib/services/logger.js +245 -226
- package/lib/template/testomatio.hbs +1366 -1026
- package/lib/uploader.js +364 -295
- package/lib/utils/pipe_utils.js +85 -89
- package/lib/utils/utils.js +307 -398
- package/lib/xmlReader.js +532 -525
- package/package.json +21 -64
- package/lib/adapter/codecept.d.ts +0 -2
- package/lib/adapter/cucumber/current.d.ts +0 -14
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber.d.ts +0 -2
- package/lib/adapter/cypress-plugin/index.d.ts +0 -2
- package/lib/adapter/jasmine.d.ts +0 -11
- package/lib/adapter/jest.d.ts +0 -13
- package/lib/adapter/mocha.d.ts +0 -2
- package/lib/adapter/nightwatch.d.ts +0 -4
- package/lib/adapter/nightwatch.js +0 -80
- package/lib/adapter/playwright.d.ts +0 -14
- package/lib/adapter/vitest.d.ts +0 -35
- package/lib/adapter/webdriver.d.ts +0 -24
- package/lib/bin/cli.d.ts +0 -2
- package/lib/bin/reportXml.d.ts +0 -2
- package/lib/bin/startTest.d.ts +0 -2
- package/lib/bin/uploadArtifacts.d.ts +0 -2
- package/lib/client.d.ts +0 -76
- package/lib/config.d.ts +0 -1
- package/lib/constants.d.ts +0 -25
- package/lib/data-storage.d.ts +0 -34
- package/lib/junit-adapter/adapter.d.ts +0 -9
- package/lib/junit-adapter/csharp.d.ts +0 -5
- package/lib/junit-adapter/index.d.ts +0 -3
- package/lib/junit-adapter/java.d.ts +0 -5
- package/lib/junit-adapter/javascript.d.ts +0 -4
- package/lib/junit-adapter/python.d.ts +0 -5
- package/lib/junit-adapter/ruby.d.ts +0 -4
- package/lib/output.d.ts +0 -11
- package/lib/package.json +0 -3
- package/lib/pipe/bitbucket.d.ts +0 -25
- package/lib/pipe/csv.d.ts +0 -47
- package/lib/pipe/debug.d.ts +0 -29
- package/lib/pipe/github.d.ts +0 -30
- package/lib/pipe/gitlab.d.ts +0 -25
- package/lib/pipe/html.d.ts +0 -35
- package/lib/pipe/index.d.ts +0 -1
- package/lib/pipe/testomatio.d.ts +0 -71
- package/lib/replay.d.ts +0 -31
- package/lib/replay.js +0 -237
- package/lib/reporter-functions.d.ts +0 -34
- package/lib/reporter.d.ts +0 -232
- package/lib/services/artifacts.d.ts +0 -33
- package/lib/services/index.d.ts +0 -9
- package/lib/services/key-values.d.ts +0 -27
- package/lib/services/logger.d.ts +0 -64
- package/lib/uploader.d.ts +0 -60
- package/lib/utils/pipe_utils.d.ts +0 -41
- package/lib/utils/utils.d.ts +0 -54
- package/lib/xmlReader.d.ts +0 -92
- package/src/adapter/codecept.js +0 -373
- package/src/adapter/cucumber/current.js +0 -228
- package/src/adapter/cucumber/legacy.js +0 -158
- package/src/adapter/cucumber.js +0 -4
- package/src/adapter/cypress-plugin/index.js +0 -110
- package/src/adapter/jasmine.js +0 -60
- package/src/adapter/jest.js +0 -107
- package/src/adapter/mocha.cjs +0 -2
- package/src/adapter/mocha.js +0 -156
- package/src/adapter/nightwatch.js +0 -88
- package/src/adapter/playwright.js +0 -254
- package/src/adapter/vitest.js +0 -183
- package/src/adapter/webdriver.js +0 -142
- package/src/bin/cli.js +0 -348
- package/src/bin/reportXml.js +0 -77
- package/src/bin/startTest.js +0 -124
- package/src/bin/uploadArtifacts.js +0 -91
- package/src/client.js +0 -508
- package/src/config.js +0 -30
- package/src/constants.js +0 -53
- package/src/data-storage.js +0 -204
- package/src/junit-adapter/adapter.js +0 -23
- package/src/junit-adapter/csharp.js +0 -28
- package/src/junit-adapter/index.js +0 -28
- package/src/junit-adapter/java.js +0 -58
- package/src/junit-adapter/javascript.js +0 -31
- package/src/junit-adapter/python.js +0 -42
- package/src/junit-adapter/ruby.js +0 -10
- package/src/output.js +0 -57
- package/src/pipe/bitbucket.js +0 -252
- package/src/pipe/csv.js +0 -140
- package/src/pipe/debug.js +0 -119
- package/src/pipe/github.js +0 -232
- package/src/pipe/gitlab.js +0 -247
- package/src/pipe/html.js +0 -373
- package/src/pipe/index.js +0 -71
- package/src/pipe/testomatio.js +0 -504
- package/src/replay.js +0 -245
- package/src/reporter-functions.js +0 -55
- package/src/reporter.cjs_decprecated +0 -21
- package/src/reporter.js +0 -33
- package/src/services/artifacts.js +0 -59
- package/src/services/index.js +0 -13
- package/src/services/key-values.js +0 -59
- package/src/services/logger.js +0 -315
- package/src/template/emptyData.svg +0 -23
- package/src/template/testomatio.hbs +0 -1081
- package/src/uploader.js +0 -376
- package/src/utils/pipe_utils.js +0 -119
- package/src/utils/utils.js +0 -416
- package/src/xmlReader.js +0 -614
package/src/pipe/bitbucket.js
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import { APP_PREFIX, testomatLogoURL } from '../constants.js';
|
|
2
|
-
import { ansiRegExp, isSameTest } from '../utils/utils.js';
|
|
3
|
-
import { statusEmoji, fullName } from '../utils/pipe_utils.js';
|
|
4
|
-
import { Gaxios } from 'gaxios';
|
|
5
|
-
import pc from 'picocolors';
|
|
6
|
-
import humanizeDuration from 'humanize-duration';
|
|
7
|
-
import merge from 'lodash.merge';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import createDebugMessages from 'debug';
|
|
10
|
-
|
|
11
|
-
const debug = createDebugMessages('@testomatio/reporter:pipe:bitbucket');
|
|
12
|
-
|
|
13
|
-
//! BITBUCKET_ACCESS_TOKEN environment variable is required for this functionality to work
|
|
14
|
-
//! and your pipeline trigger should be a pull request
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @class BitbucketPipe
|
|
18
|
-
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
19
|
-
* @typedef {import('../../types/types.js').TestData} TestData
|
|
20
|
-
*/
|
|
21
|
-
export class BitbucketPipe {
|
|
22
|
-
constructor(params, store = {}) {
|
|
23
|
-
this.isEnabled = false;
|
|
24
|
-
this.ENV = process.env;
|
|
25
|
-
this.store = store;
|
|
26
|
-
this.tests = [];
|
|
27
|
-
// Bitbucket PAT looks like bbpat-*****
|
|
28
|
-
this.token = params.BITBUCKET_ACCESS_TOKEN || process.env.BITBUCKET_ACCESS_TOKEN || this.ENV.BITBUCKET_ACCESS_TOKEN;
|
|
29
|
-
this.hiddenCommentData = `Testomat.io report: ${process.env.BITBUCKET_BRANCH || ''}`;
|
|
30
|
-
|
|
31
|
-
debug(
|
|
32
|
-
pc.yellow('Bitbucket Pipe:'),
|
|
33
|
-
this.token ? 'TOKEN passed' : '*no token*',
|
|
34
|
-
`Project key: ${this.ENV.BITBUCKET_PROJECT_KEY}, Pull request ID: ${this.ENV.BITBUCKET_PR_ID}`,
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
if (!this.token) {
|
|
38
|
-
debug(`Hint: Bitbucket CI variables are unavailable for unprotected branches by default.`);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
this.isEnabled = true;
|
|
43
|
-
this.client = new Gaxios({
|
|
44
|
-
baseURL: 'https://api.bitbucket.org/2.0',
|
|
45
|
-
headers: {
|
|
46
|
-
'Content-Type': 'application/json',
|
|
47
|
-
'Authorization': `Bearer ${this.token}`
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
debug('Bitbucket Pipe: Enabled');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async cleanLog(log) {
|
|
55
|
-
const stripAnsi = (await import('strip-ansi')).default;
|
|
56
|
-
return stripAnsi(log);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Prepare the run (if needed)
|
|
60
|
-
async prepareRun() {}
|
|
61
|
-
|
|
62
|
-
// Create a new run (if needed)
|
|
63
|
-
async createRun() {}
|
|
64
|
-
|
|
65
|
-
addTest(test) {
|
|
66
|
-
if (!this.isEnabled) return;
|
|
67
|
-
|
|
68
|
-
const index = this.tests.findIndex(t => isSameTest(t, test));
|
|
69
|
-
// Update if they were already added
|
|
70
|
-
if (index >= 0) {
|
|
71
|
-
this.tests[index] = merge(this.tests[index], test);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
this.tests.push(test);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async finishRun(runParams) {
|
|
79
|
-
if (!this.isEnabled) return;
|
|
80
|
-
|
|
81
|
-
if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
|
|
82
|
-
|
|
83
|
-
// Clean up the logs from ANSI codes
|
|
84
|
-
for (let i = 0; i < this.tests.length; i++) {
|
|
85
|
-
this.tests[i].message = await this.cleanLog(this.tests[i].message || '');
|
|
86
|
-
this.tests[i].stack = await this.cleanLog(this.tests[i].stack || '');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Create a comment on Bitbucket
|
|
90
|
-
const passedCount = this.tests.filter(t => t.status === 'passed').length;
|
|
91
|
-
const failedCount = this.tests.filter(t => t.status === 'failed').length;
|
|
92
|
-
const skippedCount = this.tests.filter(t => t.status === 'skipped').length;
|
|
93
|
-
|
|
94
|
-
// Constructing the table
|
|
95
|
-
let summary = `${this.hiddenCommentData}
|
|
96
|
-
|
|
97
|
-
|  | ${statusEmoji(
|
|
98
|
-
runParams.status,
|
|
99
|
-
)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
|
|
100
|
-
| --- | --- |
|
|
101
|
-
| **Tests** | ✔️ **${this.tests.length}** tests run |
|
|
102
|
-
| **Summary** | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji(
|
|
103
|
-
'passed',
|
|
104
|
-
)} **${passedCount}** passed; **${statusEmoji('skipped')}** ${skippedCount} skipped |
|
|
105
|
-
| **Duration** | 🕐 **${humanizeDuration(
|
|
106
|
-
parseInt(
|
|
107
|
-
this.tests.reduce((a, t) => a + (t.run_time || 0), 0),
|
|
108
|
-
10,
|
|
109
|
-
),
|
|
110
|
-
{
|
|
111
|
-
maxDecimalPoints: 0,
|
|
112
|
-
},
|
|
113
|
-
)}** |
|
|
114
|
-
`;
|
|
115
|
-
|
|
116
|
-
if (this.ENV.BITBUCKET_BRANCH && this.ENV.BITBUCKET_COMMIT) {
|
|
117
|
-
// eslint-disable-next-line max-len
|
|
118
|
-
summary += `| **Job** | 👷 [#${this.ENV.BITBUCKET_BUILD_NUMBER}](https://bitbucket.org/${this.ENV.BITBUCKET_REPO_FULL_NAME}/pipelines/results/${this.ENV.BITBUCKET_BUILD_NUMBER}") by commit: **${this.ENV.BITBUCKET_COMMIT}** |`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const failures = this.tests
|
|
122
|
-
.filter(t => t.status === 'failed')
|
|
123
|
-
.slice(0, 20)
|
|
124
|
-
.map(t => {
|
|
125
|
-
let text = `${statusEmoji('failed')} ${fullName(t)}\n`;
|
|
126
|
-
if (t.message) {
|
|
127
|
-
text += `> ${t.message
|
|
128
|
-
.replace(/[^\x20-\x7E]/g, '')
|
|
129
|
-
.replace(ansiRegExp(), '')
|
|
130
|
-
.trim()}\n`;
|
|
131
|
-
}
|
|
132
|
-
if (t.stack) {
|
|
133
|
-
text += `\n\`\`\`diff\n${t.stack
|
|
134
|
-
.replace(ansiRegExp(), '')
|
|
135
|
-
.replace(
|
|
136
|
-
/^[\s\S]*################\[ Failure \]################/g,
|
|
137
|
-
'################[ Failure ]################',
|
|
138
|
-
)
|
|
139
|
-
.trim()}\n\`\`\`\n`;
|
|
140
|
-
}
|
|
141
|
-
if (t.artifacts && t.artifacts.length && !this.ENV.TESTOMATIO_PRIVATE_ARTIFACTS) {
|
|
142
|
-
t.artifacts
|
|
143
|
-
.filter(f => !!f)
|
|
144
|
-
.forEach(f => {
|
|
145
|
-
if (f.endsWith('.png')) {
|
|
146
|
-
text += `\n`;
|
|
147
|
-
} else {
|
|
148
|
-
text += `[📄 ${path.basename(f)}](${f})\n`;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
text += `\n---\n`;
|
|
153
|
-
return text;
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
let body = summary;
|
|
157
|
-
|
|
158
|
-
if (failures.length) {
|
|
159
|
-
body += `\n🟥 **Failures (${failures.length})**\n\n* ${failures.join('\n* ')}\n`;
|
|
160
|
-
if (failures.length > 10) {
|
|
161
|
-
body += `\n> Notice: Only the first 10 failures are shown.`;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (this.tests.length > 0) {
|
|
166
|
-
body += `\n\n**🐢 Slowest Tests**\n\n`;
|
|
167
|
-
body += this.tests
|
|
168
|
-
.sort((a, b) => b.run_time - a.run_time)
|
|
169
|
-
.slice(0, 5)
|
|
170
|
-
.map(t => `* **${fullName(t)}** (${humanizeDuration(parseFloat(t.run_time))})`)
|
|
171
|
-
.join('\n');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Construct Bitbucket API URL for comments
|
|
175
|
-
// eslint-disable-next-line max-len
|
|
176
|
-
const commentsRequestURL = `/repositories/${this.ENV.BITBUCKET_WORKSPACE}/${this.ENV.BITBUCKET_REPO_SLUG}/pullrequests/${this.ENV.BITBUCKET_PR_ID}/comments`;
|
|
177
|
-
|
|
178
|
-
// Delete previous report
|
|
179
|
-
await deletePreviousReport(this.client, commentsRequestURL, this.hiddenCommentData);
|
|
180
|
-
|
|
181
|
-
// Add current report
|
|
182
|
-
debug(`Adding comment via URL: ${commentsRequestURL}`);
|
|
183
|
-
debug(`Final Bitbucket API call body: ${body}`);
|
|
184
|
-
|
|
185
|
-
try {
|
|
186
|
-
const addCommentResponse = await this.client.request({
|
|
187
|
-
method: 'POST',
|
|
188
|
-
url: commentsRequestURL,
|
|
189
|
-
data: { content: { raw: body } }
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
const commentID = addCommentResponse.data.id;
|
|
193
|
-
// eslint-disable-next-line max-len
|
|
194
|
-
const commentURL = `https://bitbucket.org/${this.ENV.BITBUCKET_WORKSPACE}/${this.ENV.BITBUCKET_REPO_SLUG}/pull-requests/${this.ENV.BITBUCKET_PR_ID}#comment-${commentID}`;
|
|
195
|
-
|
|
196
|
-
console.log(APP_PREFIX, pc.yellow('Bitbucket'), `Report created: ${pc.magenta(commentURL)}`);
|
|
197
|
-
} catch (err) {
|
|
198
|
-
console.error(
|
|
199
|
-
APP_PREFIX,
|
|
200
|
-
pc.yellow('Bitbucket'),
|
|
201
|
-
`Couldn't create Bitbucket report\n${err}.
|
|
202
|
-
Request URL: ${commentsRequestURL}
|
|
203
|
-
Request data: ${body}`,
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
toString() {
|
|
209
|
-
return 'Bitbucket Reporter';
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
updateRun() {}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
async function deletePreviousReport(client, commentsRequestURL, hiddenCommentData) {
|
|
216
|
-
if (process.env.BITBUCKET_KEEP_OUTDATED_REPORTS) return;
|
|
217
|
-
|
|
218
|
-
// Get comments
|
|
219
|
-
let comments = [];
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
const response = await client.request({
|
|
223
|
-
method: 'GET',
|
|
224
|
-
url: commentsRequestURL
|
|
225
|
-
});
|
|
226
|
-
comments = response.data.values;
|
|
227
|
-
} catch (e) {
|
|
228
|
-
console.error('Error while attempting to retrieve comments on Bitbucket Pull Request:\n', e);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (!comments.length) return;
|
|
232
|
-
|
|
233
|
-
for (const comment of comments) {
|
|
234
|
-
// If comment was left by the same workflow
|
|
235
|
-
if (comment.content.raw.includes(hiddenCommentData)) {
|
|
236
|
-
try {
|
|
237
|
-
// Delete previous comment
|
|
238
|
-
const deleteCommentURL = `${commentsRequestURL}/${comment.id}`;
|
|
239
|
-
await client.request({
|
|
240
|
-
method: 'DELETE',
|
|
241
|
-
url: deleteCommentURL
|
|
242
|
-
});
|
|
243
|
-
} catch (e) {
|
|
244
|
-
console.warn(`Can't delete previously added comment with testomat.io report. Ignored.`);
|
|
245
|
-
}
|
|
246
|
-
// Pass next env var if need to clear all previous reports;
|
|
247
|
-
// only the last one is removed by default
|
|
248
|
-
if (!process.env.BITBUCKET_REMOVE_ALL_OUTDATED_REPORTS) break;
|
|
249
|
-
// TODO: in case of many reports should implement pagination
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
package/src/pipe/csv.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import createDebugMessages from 'debug';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import { createObjectCsvWriter } from 'csv-writer';
|
|
5
|
-
import pc from 'picocolors';
|
|
6
|
-
import merge from 'lodash.merge';
|
|
7
|
-
import { isSameTest, getCurrentDateTime, ansiRegExp } from '../utils/utils.js';
|
|
8
|
-
import { CSV_HEADERS } from '../constants.js';
|
|
9
|
-
|
|
10
|
-
const debug = createDebugMessages('@testomatio/reporter:pipe:csv');
|
|
11
|
-
/**
|
|
12
|
-
* @typedef {import('../../types/types.js').Pipe} Pipe
|
|
13
|
-
* @typedef {import('../../types/types.js').TestData} TestData
|
|
14
|
-
* @class CsvPipe
|
|
15
|
-
* @implements {Pipe}
|
|
16
|
-
*/
|
|
17
|
-
class CsvPipe {
|
|
18
|
-
constructor(params, store) {
|
|
19
|
-
this.store = store || {};
|
|
20
|
-
this.title = params.title || process.env.TESTOMATIO_TITLE;
|
|
21
|
-
this.results = [];
|
|
22
|
-
|
|
23
|
-
this.outputDir = 'export';
|
|
24
|
-
this.defaultReportName = 'report.csv';
|
|
25
|
-
this.csvFilename = process.env.TESTOMATIO_CSV_FILENAME;
|
|
26
|
-
this.isEnabled = false;
|
|
27
|
-
|
|
28
|
-
if (this.csvFilename) {
|
|
29
|
-
const filenameParts = this.csvFilename.split('.');
|
|
30
|
-
|
|
31
|
-
if (filenameParts.length > 0) {
|
|
32
|
-
this.isEnabled = true;
|
|
33
|
-
const baseFilename = filenameParts[0];
|
|
34
|
-
const defaultOutputFile = path.resolve(process.cwd(), this.outputDir, this.defaultReportName);
|
|
35
|
-
|
|
36
|
-
const outputFile =
|
|
37
|
-
baseFilename === this.defaultReportName.split('.')[0] // = 'report'
|
|
38
|
-
? defaultOutputFile
|
|
39
|
-
: path.resolve(process.cwd(), this.outputDir, `${getCurrentDateTime()}_${baseFilename}.csv`);
|
|
40
|
-
|
|
41
|
-
this.outputFile = outputFile;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// TODO: to using SET opts as argument => prepareRun(opts)
|
|
47
|
-
async prepareRun() {}
|
|
48
|
-
|
|
49
|
-
async createRun() {
|
|
50
|
-
// empty
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
updateRun() {}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Create a folder that will contain the exported files
|
|
57
|
-
*/
|
|
58
|
-
checkExportDir() {
|
|
59
|
-
if (!fs.existsSync(this.outputDir)) {
|
|
60
|
-
return fs.mkdirSync(this.outputDir);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Save data to the csv file.
|
|
66
|
-
* @param {Object} data - data that will be added to the CSV file.
|
|
67
|
-
* Example: [{suite_title: "Suite #1", test: "Test-case-1", message: "Test msg"}]
|
|
68
|
-
* @param {Object} headers - csv file headers. Example: [{ id: 'suite_title', title: 'Suite_title' }]
|
|
69
|
-
*/
|
|
70
|
-
async saveToCsv(data, headers) {
|
|
71
|
-
debug('Data', data);
|
|
72
|
-
// First, we check whether the export directory exists: if yes - OK, no - create it.
|
|
73
|
-
this.checkExportDir();
|
|
74
|
-
|
|
75
|
-
if (!this.outputFile) {
|
|
76
|
-
console.log(pc.yellow(`⚠️ CSV file is not set, ignoring`));
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
console.log(pc.yellow(`⏳ The test results will be added to the csv. It will take some time...`));
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
// Create csv writer object
|
|
84
|
-
const writer = createObjectCsvWriter({
|
|
85
|
-
path: this.outputFile,
|
|
86
|
-
header: headers,
|
|
87
|
-
});
|
|
88
|
-
// Save csv file based on the current data
|
|
89
|
-
return await writer.writeRecords(data);
|
|
90
|
-
} catch (e) {
|
|
91
|
-
console.log('Unknown csv error: ', e);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Add test data to the result array for saving. As a result of this function, we get a result object to save.
|
|
97
|
-
* @param {Object} test - object which includes each test entry.
|
|
98
|
-
*/
|
|
99
|
-
addTest(test) {
|
|
100
|
-
if (!this.isEnabled) return;
|
|
101
|
-
|
|
102
|
-
const index = this.results.findIndex(t => isSameTest(t, test));
|
|
103
|
-
// update if they were already added
|
|
104
|
-
if (index >= 0) {
|
|
105
|
-
this.results[index] = merge(this.results[index], test);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const { suite_title, title, status, message, stack } = test;
|
|
110
|
-
|
|
111
|
-
this.results.push({
|
|
112
|
-
suite_title,
|
|
113
|
-
title,
|
|
114
|
-
status,
|
|
115
|
-
message: message.replace(ansiRegExp(), ''),
|
|
116
|
-
stack: stack.replace(ansiRegExp(), ''),
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @param {{ tests?: TestData[] }} runParams
|
|
122
|
-
* @returns {Promise<void>}
|
|
123
|
-
*/
|
|
124
|
-
async finishRun(runParams) {
|
|
125
|
-
if (!this.isEnabled) return;
|
|
126
|
-
|
|
127
|
-
if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
|
|
128
|
-
// Save results based on the default headers
|
|
129
|
-
if (this.isEnabled) {
|
|
130
|
-
await this.saveToCsv(this.results, CSV_HEADERS);
|
|
131
|
-
console.log(pc.green(`🗃️ Recording completed! You can check the result in file = ${this.outputFile}`));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
toString() {
|
|
136
|
-
return 'csv exporter';
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export default CsvPipe;
|
package/src/pipe/debug.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
import createDebugMessages from 'debug';
|
|
5
|
-
import { APP_PREFIX } from '../constants.js';
|
|
6
|
-
import prettyMs from 'pretty-ms';
|
|
7
|
-
|
|
8
|
-
const debug = createDebugMessages('@testomatio/reporter:pipe:debug');
|
|
9
|
-
|
|
10
|
-
export class DebugPipe {
|
|
11
|
-
constructor(params, store) {
|
|
12
|
-
this.params = params || {};
|
|
13
|
-
this.store = store || {};
|
|
14
|
-
|
|
15
|
-
this.isEnabled = !!process.env.TESTOMATIO_DEBUG || !!process.env.DEBUG;
|
|
16
|
-
if (this.isEnabled) {
|
|
17
|
-
this.batch = {
|
|
18
|
-
isEnabled: this.params.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
|
|
19
|
-
intervalFunction: null,
|
|
20
|
-
intervalTime: 5000,
|
|
21
|
-
tests: [],
|
|
22
|
-
batchIndex: 0,
|
|
23
|
-
};
|
|
24
|
-
this.logFilePath = path.join(os.tmpdir(), `testomatio.debug.${Date.now()}.json`);
|
|
25
|
-
|
|
26
|
-
debug('Creating debug file:', this.logFilePath);
|
|
27
|
-
fs.writeFileSync(this.logFilePath, '');
|
|
28
|
-
|
|
29
|
-
// Create symlink to ensure consistent path to latest debug file
|
|
30
|
-
const symlinkPath = path.join(os.tmpdir(), 'testomatio.debug.latest.json');
|
|
31
|
-
try {
|
|
32
|
-
// Remove existing symlink if it exists
|
|
33
|
-
if (fs.existsSync(symlinkPath)) {
|
|
34
|
-
fs.unlinkSync(symlinkPath);
|
|
35
|
-
}
|
|
36
|
-
// Create new symlink pointing to the timestamped debug file
|
|
37
|
-
fs.symlinkSync(this.logFilePath, symlinkPath);
|
|
38
|
-
debug('Created symlink:', symlinkPath, '->', this.logFilePath);
|
|
39
|
-
} catch (err) {
|
|
40
|
-
debug('Failed to create symlink:', err.message);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log(APP_PREFIX, '🪲 Debug file created');
|
|
44
|
-
this.testomatioEnvVars = Object.keys(process.env)
|
|
45
|
-
.filter(key => key.startsWith('TESTOMATIO_'))
|
|
46
|
-
.reduce((acc, key) => {
|
|
47
|
-
acc[key] = process.env[key];
|
|
48
|
-
return acc;
|
|
49
|
-
}, {});
|
|
50
|
-
this.logToFile({ datetime: new Date().toISOString(), timestamp: Date.now() });
|
|
51
|
-
this.logToFile({ data: 'variables', testomatioEnvVars: this.testomatioEnvVars });
|
|
52
|
-
this.logToFile({ data: 'store', store: this.store || {} });
|
|
53
|
-
// Bind batchUpload to the instance
|
|
54
|
-
this.batchUpload = this.batchUpload.bind(this);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Logs data to a file if logging is enabled.
|
|
60
|
-
*
|
|
61
|
-
* @param {Object} logData - The data to be logged.
|
|
62
|
-
* @returns {Promise<void>} A promise that resolves when the log data has been appended to the file.
|
|
63
|
-
*/
|
|
64
|
-
logToFile(logData) {
|
|
65
|
-
if (!this.isEnabled) return;
|
|
66
|
-
const timePassedFromLastAction = Date.now() - (this.lastActionTimestamp || Date.now());
|
|
67
|
-
this.lastActionTimestamp = Date.now();
|
|
68
|
-
|
|
69
|
-
const logLine = JSON.stringify({ t: `+${prettyMs(timePassedFromLastAction)}`, ...logData });
|
|
70
|
-
fs.appendFileSync(this.logFilePath, `${logLine}\n`);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async prepareRun(opts) {
|
|
74
|
-
if (!this.isEnabled) return [];
|
|
75
|
-
|
|
76
|
-
this.logToFile({ action: 'prepareRun', data: opts });
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async createRun(params = {}) {
|
|
80
|
-
if (!this.isEnabled) return;
|
|
81
|
-
if (params.isBatchEnabled === true || params.isBatchEnabled === false) this.batch.isEnabled = params.isBatchEnabled;
|
|
82
|
-
|
|
83
|
-
if (!this.isEnabled) return {};
|
|
84
|
-
if (this.batch.isEnabled) this.batch.intervalFunction = setInterval(this.batchUpload, this.batch.intervalTime);
|
|
85
|
-
|
|
86
|
-
this.logToFile({ action: 'createRun', params });
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async addTest(data) {
|
|
90
|
-
if (!this.isEnabled) return;
|
|
91
|
-
|
|
92
|
-
if (!this.batch.isEnabled) this.logToFile({ action: 'addTest', testId: data });
|
|
93
|
-
else this.batch.tests.push(data);
|
|
94
|
-
|
|
95
|
-
if (!this.batch.intervalFunction) await this.batchUpload();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async batchUpload() {
|
|
99
|
-
this.batch.batchIndex++;
|
|
100
|
-
if (!this.batch.isEnabled) return;
|
|
101
|
-
if (!this.batch.tests.length) return;
|
|
102
|
-
|
|
103
|
-
const testsToSend = this.batch.tests.splice(0);
|
|
104
|
-
|
|
105
|
-
this.logToFile({ action: 'addTestsBatch', tests: testsToSend });
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async finishRun(params) {
|
|
109
|
-
if (!this.isEnabled) return;
|
|
110
|
-
await this.batchUpload();
|
|
111
|
-
if (this.batch.intervalFunction) clearInterval(this.batch.intervalFunction);
|
|
112
|
-
this.logToFile({ action: 'finishRun', params });
|
|
113
|
-
console.log(APP_PREFIX, '🪲 Debug Saved to', this.logFilePath);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
toString() {
|
|
117
|
-
return 'Debug Reporter';
|
|
118
|
-
}
|
|
119
|
-
}
|