@testomatio/reporter 2.0.0-beta-esm → 2.0.1-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.
- package/lib/adapter/codecept.d.ts +2 -0
- package/lib/adapter/codecept.js +31 -24
- package/lib/adapter/cucumber/current.d.ts +14 -0
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.js +11 -9
- package/lib/adapter/jasmine.d.ts +11 -0
- package/lib/adapter/jest.d.ts +13 -0
- package/lib/adapter/mocha.d.ts +2 -0
- package/lib/adapter/mocha.js +4 -3
- package/lib/adapter/playwright.d.ts +14 -0
- package/lib/adapter/playwright.js +58 -33
- package/lib/adapter/vitest.d.ts +35 -0
- package/lib/adapter/vitest.js +6 -6
- package/lib/adapter/webdriver.d.ts +24 -0
- package/lib/adapter/webdriver.js +34 -6
- package/lib/bin/cli.d.ts +2 -0
- package/lib/bin/cli.js +228 -0
- package/lib/bin/reportXml.d.ts +2 -0
- package/lib/bin/reportXml.js +11 -9
- package/lib/bin/startTest.d.ts +2 -0
- package/lib/bin/startTest.js +9 -5
- package/lib/bin/uploadArtifacts.d.ts +2 -0
- package/lib/bin/uploadArtifacts.js +81 -0
- package/lib/client.d.ts +76 -0
- package/lib/client.js +111 -45
- package/lib/config.d.ts +1 -0
- package/lib/constants.d.ts +25 -0
- package/lib/constants.js +5 -1
- package/lib/data-storage.d.ts +34 -0
- package/lib/data-storage.js +2 -2
- package/lib/junit-adapter/adapter.d.ts +9 -0
- package/lib/junit-adapter/csharp.d.ts +4 -0
- package/lib/junit-adapter/index.d.ts +3 -0
- package/lib/junit-adapter/java.d.ts +5 -0
- package/lib/junit-adapter/javascript.d.ts +4 -0
- package/lib/junit-adapter/python.d.ts +5 -0
- package/lib/junit-adapter/ruby.d.ts +4 -0
- package/lib/output.d.ts +11 -0
- package/lib/package.json +3 -1
- package/lib/pipe/bitbucket.d.ts +23 -0
- package/lib/pipe/bitbucket.js +2 -2
- package/lib/pipe/csv.d.ts +47 -0
- package/lib/pipe/csv.js +2 -2
- package/lib/pipe/debug.d.ts +29 -0
- package/lib/pipe/debug.js +108 -0
- package/lib/pipe/github.d.ts +30 -0
- package/lib/pipe/github.js +2 -2
- package/lib/pipe/gitlab.d.ts +23 -0
- package/lib/pipe/gitlab.js +2 -2
- package/lib/pipe/html.d.ts +34 -0
- package/lib/pipe/html.js +8 -1
- package/lib/pipe/index.d.ts +1 -0
- package/lib/pipe/index.js +3 -3
- package/lib/pipe/testomatio.d.ts +70 -0
- package/lib/pipe/testomatio.js +50 -30
- package/lib/reporter-functions.d.ts +34 -0
- package/lib/reporter-functions.js +17 -7
- package/lib/reporter.d.ts +232 -0
- package/lib/reporter.js +19 -33
- package/lib/services/artifacts.d.ts +33 -0
- package/lib/services/index.d.ts +9 -0
- package/lib/services/key-values.d.ts +27 -0
- package/lib/services/key-values.js +1 -1
- package/lib/services/logger.d.ts +64 -0
- package/lib/template/testomatio.hbs +651 -1366
- package/lib/uploader.d.ts +60 -0
- package/lib/uploader.js +312 -0
- package/lib/utils/pipe_utils.d.ts +41 -0
- package/lib/utils/pipe_utils.js +3 -5
- package/lib/utils/utils.d.ts +45 -0
- package/lib/utils/utils.js +69 -2
- package/lib/xmlReader.d.ts +92 -0
- package/lib/xmlReader.js +22 -12
- package/package.json +15 -9
- package/src/adapter/codecept.js +30 -24
- package/src/adapter/cypress-plugin/index.js +5 -3
- package/src/adapter/mocha.cjs +1 -1
- package/src/adapter/mocha.js +4 -3
- package/src/adapter/playwright.js +59 -31
- package/src/adapter/vitest.js +6 -6
- package/src/adapter/webdriver.js +41 -10
- package/src/bin/cli.js +280 -0
- package/src/bin/reportXml.js +15 -8
- package/src/bin/startTest.js +7 -3
- package/src/bin/uploadArtifacts.js +90 -0
- package/src/client.js +137 -56
- package/src/constants.js +5 -1
- package/src/data-storage.js +2 -2
- package/src/pipe/bitbucket.js +2 -2
- package/src/pipe/csv.js +3 -3
- package/src/pipe/debug.js +104 -0
- package/src/pipe/github.js +2 -3
- package/src/pipe/gitlab.js +6 -6
- package/src/pipe/html.js +11 -3
- package/src/pipe/index.js +5 -7
- package/src/pipe/testomatio.js +72 -67
- package/src/reporter-functions.js +18 -7
- package/src/reporter.cjs_decprecated +21 -0
- package/src/reporter.js +20 -11
- package/src/services/key-values.js +1 -1
- package/src/services/logger.js +4 -2
- package/src/template/testomatio.hbs +651 -1366
- package/src/uploader.js +371 -0
- package/src/utils/pipe_utils.js +4 -12
- package/src/utils/utils.js +48 -6
- package/src/xmlReader.js +26 -15
- package/lib/adapter/jasmine/jasmine.js +0 -63
- package/lib/adapter/mocha/mocha.js +0 -125
- package/lib/fileUploader.js +0 -245
- package/lib/utils/chalk.js +0 -10
- package/src/fileUploader.js +0 -307
- package/src/reporter.cjs +0 -22
- package/src/utils/chalk.js +0 -13
package/lib/xmlReader.js
CHANGED
|
@@ -15,12 +15,12 @@ const utils_js_1 = require("./utils/utils.js");
|
|
|
15
15
|
const index_js_1 = require("./pipe/index.js");
|
|
16
16
|
const index_js_2 = __importDefault(require("./junit-adapter/index.js"));
|
|
17
17
|
const config_js_1 = require("./config.js");
|
|
18
|
-
const
|
|
18
|
+
const uploader_js_1 = require("./uploader.js");
|
|
19
19
|
// @ts-ignore this line will be removed in compiled code, because __dirname is defined in commonjs
|
|
20
20
|
const debug = (0, debug_1.default)('@testomatio/reporter:xml');
|
|
21
21
|
const ridRunId = (0, crypto_1.randomUUID)();
|
|
22
22
|
const TESTOMATIO_URL = process.env.TESTOMATIO_URL || 'https://app.testomat.io';
|
|
23
|
-
const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } = process.env;
|
|
23
|
+
const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN, TESTOMATIO_MARK_DETACHED } = process.env;
|
|
24
24
|
const options = {
|
|
25
25
|
ignoreDeclaration: true,
|
|
26
26
|
ignoreAttributes: false,
|
|
@@ -37,6 +37,7 @@ class XmlReader {
|
|
|
37
37
|
title: TESTOMATIO_TITLE,
|
|
38
38
|
env: TESTOMATIO_ENV,
|
|
39
39
|
group_title: TESTOMATIO_RUNGROUP_TITLE,
|
|
40
|
+
detach: TESTOMATIO_MARK_DETACHED,
|
|
40
41
|
// batch uploading is implemented for xml already
|
|
41
42
|
isBatchEnabled: false,
|
|
42
43
|
};
|
|
@@ -51,7 +52,7 @@ class XmlReader {
|
|
|
51
52
|
this.tests = [];
|
|
52
53
|
this.stats = {};
|
|
53
54
|
this.stats.language = opts.lang?.toLowerCase();
|
|
54
|
-
this.
|
|
55
|
+
this.uploader = new uploader_js_1.S3Uploader();
|
|
55
56
|
// @ts-ignore
|
|
56
57
|
const packageJsonPath = path_1.default.resolve(__dirname, '..', 'package.json');
|
|
57
58
|
this.version = JSON.parse(fs_1.default.readFileSync(packageJsonPath).toString()).version;
|
|
@@ -105,16 +106,24 @@ class XmlReader {
|
|
|
105
106
|
const resultTests = processTestSuite(testsuite);
|
|
106
107
|
const hasFailures = resultTests.filter(t => t.status === 'failed').length > 0;
|
|
107
108
|
const status = failures > 0 || errors > 0 || hasFailures ? 'failed' : 'passed';
|
|
109
|
+
const time = testsuite.time || 0;
|
|
110
|
+
// debug('time', jsonSuite, time)
|
|
111
|
+
if (time) {
|
|
112
|
+
if (!this.stats.duration)
|
|
113
|
+
this.stats.duration = 0;
|
|
114
|
+
this.stats.duration += parseFloat(time);
|
|
115
|
+
}
|
|
108
116
|
this.tests = this.tests.concat(resultTests);
|
|
109
117
|
return {
|
|
110
|
-
status,
|
|
111
118
|
create_tests: true,
|
|
119
|
+
duration: parseFloat(time),
|
|
120
|
+
failed_count: parseInt(failures, 10),
|
|
112
121
|
name,
|
|
113
|
-
tests_count: parseInt(tests, 10),
|
|
114
122
|
passed_count: parseInt(tests, 10) - parseInt(failures, 10),
|
|
115
|
-
failed_count: parseInt(failures, 10),
|
|
116
123
|
skipped_count: 0,
|
|
124
|
+
status,
|
|
117
125
|
tests: resultTests,
|
|
126
|
+
tests_count: parseInt(tests, 10),
|
|
118
127
|
};
|
|
119
128
|
}
|
|
120
129
|
processNUnit(jsonSuite) {
|
|
@@ -266,6 +275,7 @@ class XmlReader {
|
|
|
266
275
|
calculateStats() {
|
|
267
276
|
this.stats = {
|
|
268
277
|
...this.stats,
|
|
278
|
+
detach: this.requestParams.detach,
|
|
269
279
|
status: 'passed',
|
|
270
280
|
create_tests: true,
|
|
271
281
|
tests_count: 0,
|
|
@@ -355,7 +365,7 @@ class XmlReader {
|
|
|
355
365
|
if (!files.length)
|
|
356
366
|
continue;
|
|
357
367
|
const runId = this.runId || this.store.runId || Date.now().toString();
|
|
358
|
-
test.artifacts = await Promise.all(files.map(f =>
|
|
368
|
+
test.artifacts = await Promise.all(files.map(f => this.uploader.uploadFileByPath(f, [runId])));
|
|
359
369
|
console.log(constants_js_1.APP_PREFIX, `🗄️ Uploaded ${picocolors_1.default.bold(`${files.length} artifacts`)} for test ${test.title}`);
|
|
360
370
|
}
|
|
361
371
|
}
|
|
@@ -369,7 +379,9 @@ class XmlReader {
|
|
|
369
379
|
};
|
|
370
380
|
debug('Run', runParams);
|
|
371
381
|
this.pipes = this.pipes || (await this.pipesPromise);
|
|
372
|
-
|
|
382
|
+
const run = await Promise.all(this.pipes.map(p => p.createRun(runParams)));
|
|
383
|
+
this.uploader.checkEnabled();
|
|
384
|
+
return run;
|
|
373
385
|
}
|
|
374
386
|
async uploadData() {
|
|
375
387
|
await this.uploadArtifacts();
|
|
@@ -378,16 +390,14 @@ class XmlReader {
|
|
|
378
390
|
this.fetchSourceCode();
|
|
379
391
|
this.formatErrors();
|
|
380
392
|
this.formatTests();
|
|
381
|
-
debug('Uploading data', {
|
|
382
|
-
...this.stats,
|
|
383
|
-
tests: this.tests,
|
|
384
|
-
});
|
|
385
393
|
const dataString = {
|
|
386
394
|
...this.stats,
|
|
387
395
|
api_key: this.requestParams.apiKey,
|
|
388
396
|
status: 'finished',
|
|
397
|
+
duration: this.stats.duration,
|
|
389
398
|
tests: this.tests,
|
|
390
399
|
};
|
|
400
|
+
debug('Uploading data', dataString);
|
|
391
401
|
this.pipes = this.pipes || (await this.pipesPromise);
|
|
392
402
|
return Promise.all(this.pipes.map(p => p.finishRun(dataString)));
|
|
393
403
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testomatio/reporter",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1-beta-esm",
|
|
4
4
|
"description": "Testomatio Reporter Client",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18"
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
"axios": "^1.6.2",
|
|
20
20
|
"axios-retry": "^3.9.1",
|
|
21
21
|
"callsite-record": "^4.1.4",
|
|
22
|
-
"
|
|
23
|
-
"commander": "^4.1.1",
|
|
22
|
+
"commander": "^12",
|
|
24
23
|
"cross-spawn": "^7.0.3",
|
|
25
24
|
"csv-writer": "^1.6.0",
|
|
26
25
|
"debug": "^4.3.4",
|
|
27
26
|
"dotenv": "^16.0.1",
|
|
28
27
|
"fast-xml-parser": "^4.4.1",
|
|
29
28
|
"file-url": "3.0.0",
|
|
29
|
+
"filesize": "^10.1.6",
|
|
30
30
|
"glob": "^10.3",
|
|
31
31
|
"handlebars": "^4.7.8",
|
|
32
32
|
"has-flag": "^5.0.1",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"lodash.merge": "^4.6.2",
|
|
38
38
|
"minimatch": "^9.0.3",
|
|
39
39
|
"picocolors": "^1.0.1",
|
|
40
|
+
"pretty-ms": "^7.0.1",
|
|
40
41
|
"promise-retry": "^2.0.1",
|
|
41
42
|
"strip-ansi": "^7.1.0",
|
|
42
43
|
"uuid": "^9.0.0"
|
|
@@ -67,10 +68,11 @@
|
|
|
67
68
|
"test:adapter:playwright:example": "npx playwright test --config='./tests/adapter/examples/playwright/playwright.config.ts'",
|
|
68
69
|
"test:adapter:vitest:example": "npx vitest --config='./tests/adapter/examples/vitest/vitest.config.ts'",
|
|
69
70
|
"test:storage": "npx mocha tests-storage/artifact-storage.test.js && npx mocha tests-storage/data-storage.test.js && TESTOMATIO_INTERCEPT_CONSOLE_LOGS=true npx mocha tests-storage/logger.test.js && npx mocha tests-storage/logger-2.test.js && npx mocha tests-storage/reporter-functions.test.js",
|
|
70
|
-
"
|
|
71
|
+
"//": "builds code from /src (esm) into /lib (commonjs)",
|
|
72
|
+
"build": "rm -rf ./cjs && tsc --module commonjs && npx tsx build/scripts/edit-js-files.js && npx tsx build/scripts/edit-package-json.js && chmod +x ./build/scripts/copy-tesmplate.sh && ./build/scripts/copy-tesmplate.sh"
|
|
71
73
|
},
|
|
72
74
|
"devDependencies": {
|
|
73
|
-
"@playwright/test": "^1.
|
|
75
|
+
"@playwright/test": "^1.49.1",
|
|
74
76
|
"@redocly/cli": "^1.0.0-beta.125",
|
|
75
77
|
"@types/cross-spawn": "^6.0.6",
|
|
76
78
|
"@types/cucumber": "^7.0.0",
|
|
@@ -95,14 +97,16 @@
|
|
|
95
97
|
"vitest": "^1.6.0"
|
|
96
98
|
},
|
|
97
99
|
"bin": {
|
|
100
|
+
"@testomatio/reporter": "./lib/bin/cli.js",
|
|
98
101
|
"report-xml": "./lib/bin/reportXml.js",
|
|
99
|
-
"start-test-run": "./lib/bin/startTest.js"
|
|
102
|
+
"start-test-run": "./lib/bin/startTest.js",
|
|
103
|
+
"upload-artifacts": "./lib/bin/uploadArtifacts.js"
|
|
100
104
|
},
|
|
101
105
|
"exports": {
|
|
102
106
|
".": {
|
|
103
107
|
"import": "./src/reporter.js",
|
|
104
108
|
"require": "./lib/reporter.js",
|
|
105
|
-
"types": "./
|
|
109
|
+
"types": "./types/types.d.ts"
|
|
106
110
|
},
|
|
107
111
|
"./lib/adapter/codecept/codecept.js": "./lib/adapter/codecept.js",
|
|
108
112
|
"./lib/adapter/codecept": "./lib/adapter/codecept.js",
|
|
@@ -111,6 +115,7 @@
|
|
|
111
115
|
"./cucumber": "./lib/adapter/cucumber/current.js",
|
|
112
116
|
"./lib/adapter/cypress-plugin": "./lib/adapter/cypress-plugin/index.js",
|
|
113
117
|
"./cypress-plugin": "./lib/adapter/cypress-plugin/index.js",
|
|
118
|
+
"./cypress": "./lib/adapter/cypress-plugin/index.js",
|
|
114
119
|
"./lib/adapter/jasmine.js": "./lib/adapter/jasmine.js",
|
|
115
120
|
"./jasmine": "./lib/adapter/jasmine.js",
|
|
116
121
|
"./lib/adapter/jest.js": "./lib/adapter/jest.js",
|
|
@@ -119,9 +124,10 @@
|
|
|
119
124
|
"./mocha": "./lib/adapter/mocha.js",
|
|
120
125
|
"./lib/adapter/playwright.js": "./lib/adapter/playwright.js",
|
|
121
126
|
"./playwright": "./lib/adapter/playwright.js",
|
|
122
|
-
"./vitest": "./
|
|
127
|
+
"./vitest": "./lib/adapter/vitest.js",
|
|
123
128
|
"./lib/adapter/webdriver.js": "./lib/adapter/webdriver.js",
|
|
124
129
|
"./lib/adapter/webdriver": "./lib/adapter/webdriver.js",
|
|
125
|
-
"./webdriver": "./lib/adapter/webdriver.js"
|
|
130
|
+
"./webdriver": "./lib/adapter/webdriver.js",
|
|
131
|
+
"./wdio": "./lib/adapter/webdriver.js"
|
|
126
132
|
}
|
|
127
133
|
}
|
package/src/adapter/codecept.js
CHANGED
|
@@ -4,7 +4,6 @@ import TestomatClient from '../client.js';
|
|
|
4
4
|
import { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
|
|
5
5
|
import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
|
|
6
6
|
import { services } from '../services/index.js';
|
|
7
|
-
import { upload } from '../fileUploader.js';
|
|
8
7
|
// eslint-disable-next-line
|
|
9
8
|
import codeceptjs from 'codeceptjs';
|
|
10
9
|
|
|
@@ -46,8 +45,9 @@ function CodeceptReporter(config) {
|
|
|
46
45
|
const { apiKey } = config;
|
|
47
46
|
|
|
48
47
|
const getDuration = test => {
|
|
49
|
-
if (
|
|
50
|
-
|
|
48
|
+
if (!test.uid) return 0;
|
|
49
|
+
if (testTimeMap[test.uid]) {
|
|
50
|
+
return Date.now() - testTimeMap[test.uid];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
return 0;
|
|
@@ -125,7 +125,8 @@ function CodeceptReporter(config) {
|
|
|
125
125
|
services.setContext(test.fullTitle());
|
|
126
126
|
|
|
127
127
|
testTimeMap[test.id] = Date.now();
|
|
128
|
-
|
|
128
|
+
if (!test.uid) return;
|
|
129
|
+
testTimeMap[test.uid] = Date.now();
|
|
129
130
|
});
|
|
130
131
|
|
|
131
132
|
event.dispatcher.on(event.all.result, async () => {
|
|
@@ -133,10 +134,8 @@ function CodeceptReporter(config) {
|
|
|
133
134
|
// all tests were reported and we can upload videos
|
|
134
135
|
await Promise.all(reportTestPromises);
|
|
135
136
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
await uploadAttachments(client, traces, '📁 Uploading', 'trace');
|
|
139
|
-
}
|
|
137
|
+
await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
|
|
138
|
+
await uploadAttachments(client, traces, '📁 Uploading', 'trace');
|
|
140
139
|
|
|
141
140
|
const status = failedTests.length === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
142
141
|
// @ts-ignore
|
|
@@ -144,9 +143,9 @@ function CodeceptReporter(config) {
|
|
|
144
143
|
});
|
|
145
144
|
|
|
146
145
|
event.dispatcher.on(event.test.passed, test => {
|
|
147
|
-
const {
|
|
148
|
-
if (
|
|
149
|
-
failedTests = failedTests.filter(failed =>
|
|
146
|
+
const { uid, tags, title } = test;
|
|
147
|
+
if (uid && failedTests.includes(uid)) {
|
|
148
|
+
failedTests = failedTests.filter(failed => uid !== failed);
|
|
150
149
|
}
|
|
151
150
|
const testObj = getTestAndMessage(title);
|
|
152
151
|
|
|
@@ -157,7 +156,7 @@ function CodeceptReporter(config) {
|
|
|
157
156
|
|
|
158
157
|
client.addTestRun(STATUS.PASSED, {
|
|
159
158
|
...stripExampleFromTitle(title),
|
|
160
|
-
rid:
|
|
159
|
+
rid: uid,
|
|
161
160
|
suite_title: test.parent && test.parent.title,
|
|
162
161
|
message: testObj.message,
|
|
163
162
|
time: getDuration(test),
|
|
@@ -180,12 +179,12 @@ function CodeceptReporter(config) {
|
|
|
180
179
|
if (!suite) return;
|
|
181
180
|
if (!suite.tests) return;
|
|
182
181
|
for (const test of suite.tests) {
|
|
183
|
-
const {
|
|
184
|
-
failedTests.push(
|
|
182
|
+
const { uid, tags, title } = test;
|
|
183
|
+
failedTests.push(uid || title);
|
|
185
184
|
const testId = getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`);
|
|
186
185
|
|
|
187
186
|
client.addTestRun(STATUS.FAILED, {
|
|
188
|
-
rid:
|
|
187
|
+
rid: uid,
|
|
189
188
|
...stripExampleFromTitle(title),
|
|
190
189
|
suite_title: suite.title,
|
|
191
190
|
test_id: testId,
|
|
@@ -199,8 +198,8 @@ function CodeceptReporter(config) {
|
|
|
199
198
|
event.dispatcher.on(event.test.after, test => {
|
|
200
199
|
if (test.state && test.state !== STATUS.FAILED) return;
|
|
201
200
|
if (test.err) error = test.err;
|
|
202
|
-
const {
|
|
203
|
-
failedTests.push(
|
|
201
|
+
const { uid, tags, title, artifacts } = test;
|
|
202
|
+
failedTests.push(uid || title);
|
|
204
203
|
const testObj = getTestAndMessage(title);
|
|
205
204
|
|
|
206
205
|
const files = [];
|
|
@@ -214,7 +213,7 @@ function CodeceptReporter(config) {
|
|
|
214
213
|
|
|
215
214
|
client.addTestRun(STATUS.FAILED, {
|
|
216
215
|
...stripExampleFromTitle(title),
|
|
217
|
-
rid:
|
|
216
|
+
rid: uid,
|
|
218
217
|
test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
|
|
219
218
|
suite_title: test.parent && test.parent.title,
|
|
220
219
|
error,
|
|
@@ -230,20 +229,20 @@ function CodeceptReporter(config) {
|
|
|
230
229
|
debug('artifacts', artifacts);
|
|
231
230
|
|
|
232
231
|
for (const aid in artifacts) {
|
|
233
|
-
if (aid.startsWith('video')) videos.push({ rid:
|
|
234
|
-
if (aid.startsWith('trace')) traces.push({ rid:
|
|
232
|
+
if (aid.startsWith('video')) videos.push({ rid: uid, title, path: artifacts[aid], type: 'video/webm' });
|
|
233
|
+
if (aid.startsWith('trace')) traces.push({ rid: uid, title, path: artifacts[aid], type: 'application/zip' });
|
|
235
234
|
}
|
|
236
235
|
|
|
237
236
|
// output.stop();
|
|
238
237
|
});
|
|
239
238
|
|
|
240
239
|
event.dispatcher.on(event.test.skipped, test => {
|
|
241
|
-
const {
|
|
242
|
-
if (failedTests.includes(
|
|
240
|
+
const { uid, tags, title } = test;
|
|
241
|
+
if (failedTests.includes(uid || title)) return;
|
|
243
242
|
|
|
244
243
|
const testObj = getTestAndMessage(title);
|
|
245
244
|
client.addTestRun(STATUS.SKIPPED, {
|
|
246
|
-
rid:
|
|
245
|
+
rid: uid,
|
|
247
246
|
...stripExampleFromTitle(title),
|
|
248
247
|
test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
|
|
249
248
|
suite_title: test.parent && test.parent.title,
|
|
@@ -312,11 +311,17 @@ function CodeceptReporter(config) {
|
|
|
312
311
|
async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
|
|
313
312
|
if (!attachments?.length) return;
|
|
314
313
|
|
|
315
|
-
|
|
314
|
+
if (client.uploader.isEnabled) {
|
|
315
|
+
console.log(APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
|
|
316
|
+
}
|
|
316
317
|
|
|
317
318
|
const promises = attachments.map(async attachment => {
|
|
318
319
|
const { rid, title, path, type } = attachment;
|
|
319
320
|
const file = { path, type, title };
|
|
321
|
+
|
|
322
|
+
// we are storing file if upload is disabled
|
|
323
|
+
if (!client.uploader.isEnabled) return client.uploader.storeUploadedFile(path, client.runId, rid, false);
|
|
324
|
+
|
|
320
325
|
return client.addTestRun(undefined, {
|
|
321
326
|
...stripExampleFromTitle(title),
|
|
322
327
|
rid,
|
|
@@ -367,3 +372,4 @@ function getTestLogs(test) {
|
|
|
367
372
|
}
|
|
368
373
|
|
|
369
374
|
export { CodeceptReporter };
|
|
375
|
+
export default CodeceptReporter;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { STATUS } from '../../constants.js';
|
|
2
2
|
import { getTestomatIdFromTestTitle, parseSuite } from '../../utils/utils.js';
|
|
3
3
|
import TestomatClient from '../../client.js';
|
|
4
|
-
import {config} from '../../config.js';
|
|
4
|
+
import { config } from '../../config.js';
|
|
5
5
|
|
|
6
6
|
const testomatioReporter = on => {
|
|
7
7
|
if (!config.TESTOMATIO) {
|
|
@@ -50,7 +50,8 @@ const testomatioReporter = on => {
|
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const formattedError = error
|
|
53
|
+
const formattedError = error
|
|
54
|
+
? {
|
|
54
55
|
message: error.message,
|
|
55
56
|
name: error.name,
|
|
56
57
|
inspect:
|
|
@@ -59,7 +60,8 @@ const testomatioReporter = on => {
|
|
|
59
60
|
function () {
|
|
60
61
|
return this.message;
|
|
61
62
|
},
|
|
62
|
-
}
|
|
63
|
+
}
|
|
64
|
+
: undefined;
|
|
63
65
|
|
|
64
66
|
const screenshots = Array.isArray(results.screenshots)
|
|
65
67
|
? results.screenshots
|
package/src/adapter/mocha.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const MochaReporter = require('../../../lib/adapter/mocha
|
|
1
|
+
const MochaReporter = require('../../../lib/adapter/mocha.js');
|
|
2
2
|
module.exports = MochaReporter;
|
package/src/adapter/mocha.js
CHANGED
|
@@ -33,6 +33,7 @@ function MochaReporter(runner, opts) {
|
|
|
33
33
|
runner.on(EVENT_RUN_BEGIN, () => {
|
|
34
34
|
client.createRun();
|
|
35
35
|
|
|
36
|
+
// clear dir with artifacts/logs
|
|
36
37
|
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
37
38
|
});
|
|
38
39
|
|
|
@@ -66,7 +67,7 @@ function MochaReporter(runner, opts) {
|
|
|
66
67
|
test_id: testId,
|
|
67
68
|
suite_title: getSuiteTitle(test),
|
|
68
69
|
title: getTestName(test),
|
|
69
|
-
code: test.body.toString(),
|
|
70
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
70
71
|
file: getFile(test),
|
|
71
72
|
time: test.duration,
|
|
72
73
|
logs,
|
|
@@ -82,7 +83,7 @@ function MochaReporter(runner, opts) {
|
|
|
82
83
|
client.addTestRun(STATUS.SKIPPED, {
|
|
83
84
|
title: getTestName(test),
|
|
84
85
|
suite_title: getSuiteTitle(test),
|
|
85
|
-
code: test.body.toString(),
|
|
86
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
86
87
|
file: getFile(test),
|
|
87
88
|
test_id: testId,
|
|
88
89
|
time: test.duration,
|
|
@@ -102,7 +103,7 @@ function MochaReporter(runner, opts) {
|
|
|
102
103
|
file: getFile(test),
|
|
103
104
|
test_id: testId,
|
|
104
105
|
title: getTestName(test),
|
|
105
|
-
code: test.body.toString(),
|
|
106
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
106
107
|
time: test.duration,
|
|
107
108
|
logs,
|
|
108
109
|
});
|
|
@@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import { APP_PREFIX, STATUS as Status, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
|
|
8
8
|
import TestomatioClient from '../client.js';
|
|
9
|
-
import { upload } from '../fileUploader.js';
|
|
10
9
|
import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
|
|
11
10
|
import { services } from '../services/index.js';
|
|
12
11
|
import { dataStorage } from '../data-storage.js';
|
|
@@ -57,11 +56,37 @@ class PlaywrightReporter {
|
|
|
57
56
|
logs = `\n\n${pc.bold('Logs:')}\n${pc.red(result.stderr.join(''))}\n${result.stdout.join('')}`;
|
|
58
57
|
}
|
|
59
58
|
const manuallyAttachedArtifacts = services.artifacts.get(fullTestTitle);
|
|
60
|
-
const
|
|
59
|
+
const testMeta = services.keyValues.get(fullTestTitle);
|
|
61
60
|
const rid = test.id || test.testId || uuidv4();
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
/**
|
|
63
|
+
* @type {{
|
|
64
|
+
* browser?: string,
|
|
65
|
+
* dependencies: string[],
|
|
66
|
+
* isMobile?: boolean
|
|
67
|
+
* metadata: Record<string, any>,
|
|
68
|
+
* name: string,
|
|
69
|
+
* }}
|
|
70
|
+
*/
|
|
71
|
+
const project = {
|
|
72
|
+
browser: test.parent.project().use.defaultBrowserType,
|
|
73
|
+
dependencies: test.parent.project().dependencies,
|
|
74
|
+
isMobile: test.parent.project().use.isMobile,
|
|
75
|
+
metadata: test.parent.project().metadata,
|
|
76
|
+
name: test.parent.project().name,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
let status = result.status;
|
|
80
|
+
// process test.fail() annotation
|
|
81
|
+
if (test.expectedStatus === 'failed') {
|
|
82
|
+
// actual status = expected
|
|
83
|
+
if (result.status === 'failed') status = 'passed';
|
|
84
|
+
// actual status != expected
|
|
85
|
+
if (result.status === 'passed') status = 'failed';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const reportTestPromise = this.client.addTestRun(checkStatus(status), {
|
|
89
|
+
rid: `${rid}-${project.name}`,
|
|
65
90
|
error,
|
|
66
91
|
test_id: getTestomatIdFromTestTitle(`${title} ${test.tags?.join(' ')}`),
|
|
67
92
|
suite_title,
|
|
@@ -70,12 +95,19 @@ class PlaywrightReporter {
|
|
|
70
95
|
time: duration,
|
|
71
96
|
logs,
|
|
72
97
|
manuallyAttachedArtifacts,
|
|
73
|
-
meta:
|
|
98
|
+
meta: {
|
|
99
|
+
browser: project.browser,
|
|
100
|
+
isMobile: project.isMobile,
|
|
101
|
+
project: project.name,
|
|
102
|
+
projectDependencies: project.dependencies?.length ? project.dependencies : null,
|
|
103
|
+
...testMeta,
|
|
104
|
+
...project.metadata, // metadata has any type (in playwright), but we will stringify it in client.js
|
|
105
|
+
},
|
|
74
106
|
file: test.location?.file,
|
|
75
107
|
});
|
|
76
108
|
|
|
77
109
|
this.uploads.push({
|
|
78
|
-
rid
|
|
110
|
+
rid: `${rid}-${project.name}`,
|
|
79
111
|
title: test.title,
|
|
80
112
|
files: result.attachments.filter(a => a.body || a.path),
|
|
81
113
|
file: test.location?.file,
|
|
@@ -94,9 +126,13 @@ class PlaywrightReporter {
|
|
|
94
126
|
}
|
|
95
127
|
|
|
96
128
|
if (artifact.body) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
129
|
+
let filePath = generateTmpFilepath(artifact.name);
|
|
130
|
+
|
|
131
|
+
const extension = artifact.contentType?.split('/')[1]?.replace('jpeg', 'jpg');
|
|
132
|
+
if (extension) filePath += `.${extension}`;
|
|
133
|
+
|
|
134
|
+
fs.writeFileSync(filePath, artifact.body);
|
|
135
|
+
return filePath;
|
|
100
136
|
}
|
|
101
137
|
|
|
102
138
|
return null;
|
|
@@ -107,20 +143,26 @@ class PlaywrightReporter {
|
|
|
107
143
|
|
|
108
144
|
await Promise.all(reportTestPromises);
|
|
109
145
|
|
|
110
|
-
if (this.uploads.length
|
|
111
|
-
console.log(APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
|
|
146
|
+
if (this.uploads.length) {
|
|
147
|
+
if (this.client.uploader.isEnabled) console.log(APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
|
|
112
148
|
|
|
113
149
|
const promises = [];
|
|
114
150
|
|
|
115
|
-
|
|
116
|
-
|
|
151
|
+
// ? possible move to addTestRun (needs investigation if files are ready)
|
|
152
|
+
for (const upload of this.uploads) {
|
|
153
|
+
const { rid, file, title } = upload;
|
|
117
154
|
|
|
118
|
-
const files =
|
|
155
|
+
const files = upload.files.map(attachment => ({
|
|
119
156
|
path: this.#getArtifactPath(attachment),
|
|
120
157
|
title,
|
|
121
158
|
type: attachment.contentType,
|
|
122
159
|
}));
|
|
123
160
|
|
|
161
|
+
if (!this.client.uploader.isEnabled) {
|
|
162
|
+
files.forEach(f => this.client.uploader.storeUploadedFile(f, this.client.runId, rid, false));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
124
166
|
promises.push(
|
|
125
167
|
this.client.addTestRun(undefined, {
|
|
126
168
|
rid,
|
|
@@ -190,9 +232,10 @@ function appendStep(step, shift = 0) {
|
|
|
190
232
|
return resultStep;
|
|
191
233
|
}
|
|
192
234
|
|
|
193
|
-
function
|
|
235
|
+
function generateTmpFilepath(filename = '') {
|
|
236
|
+
filename = filename || `tmp.${crypto.randomBytes(16).toString('hex')}`;
|
|
194
237
|
const tmpdir = os.tmpdir();
|
|
195
|
-
return path.join(tmpdir,
|
|
238
|
+
return path.join(tmpdir, filename);
|
|
196
239
|
}
|
|
197
240
|
|
|
198
241
|
/**
|
|
@@ -204,19 +247,4 @@ function getTestContextName(test) {
|
|
|
204
247
|
return `${test._requireFile || ''}_${test.title}`;
|
|
205
248
|
}
|
|
206
249
|
|
|
207
|
-
function initPlaywrightForStorage() {
|
|
208
|
-
try {
|
|
209
|
-
// @ts-ignore-next-line
|
|
210
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
211
|
-
const { test } = require('@playwright/test');
|
|
212
|
-
// eslint-disable-next-line no-empty-pattern
|
|
213
|
-
test.beforeEach(async ({}, testInfo) => {
|
|
214
|
-
global.testomatioTestTitle = `${testInfo.file || ''}_${testInfo.title}`;
|
|
215
|
-
});
|
|
216
|
-
} catch (e) {
|
|
217
|
-
// ignore
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
250
|
export default PlaywrightReporter;
|
|
222
|
-
export { initPlaywrightForStorage };
|
package/src/adapter/vitest.js
CHANGED
|
@@ -7,13 +7,13 @@ import createDebugMessages from 'debug';
|
|
|
7
7
|
const debug = createDebugMessages('@testomatio/reporter:adapter-jest');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types').VitestTest} VitestTest
|
|
11
|
-
* @typedef {import('../../types').VitestTestFile} VitestTestFile
|
|
12
|
-
* @typedef {import('../../types').VitestSuite} VitestSuite
|
|
13
|
-
* @typedef {import('../../types').VitestTestLogs} VitestTestLogs
|
|
14
|
-
* @typedef {import('../../vitest.types').ErrorWithDiff} ErrorWithDiff
|
|
10
|
+
* @typedef {import('../../types/types.js').VitestTest} VitestTest
|
|
11
|
+
* @typedef {import('../../types/types.js').VitestTestFile} VitestTestFile
|
|
12
|
+
* @typedef {import('../../types/types.js').VitestSuite} VitestSuite
|
|
13
|
+
* @typedef {import('../../types/types.js').VitestTestLogs} VitestTestLogs
|
|
14
|
+
* @typedef {import('../../types/vitest.types.js').ErrorWithDiff} ErrorWithDiff
|
|
15
15
|
* @typedef {typeof import('../constants.js').STATUS} STATUS
|
|
16
|
-
* @typedef {import('../../types').TestData} TestData
|
|
16
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
class VitestReporter {
|