@testomatio/reporter 2.0.0-beta-esm → 2.0.0-beta.1-gaxios
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 -26
- 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 +10 -10
- 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 -4
- package/lib/adapter/nightwatch.d.ts +4 -0
- package/lib/adapter/nightwatch.js +80 -0
- 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 +51 -14
- package/lib/bin/cli.d.ts +2 -0
- package/lib/bin/cli.js +249 -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 +128 -53
- package/lib/config.d.ts +1 -0
- package/lib/config.js +2 -2
- 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 +19 -9
- 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 +25 -0
- package/lib/pipe/bitbucket.js +40 -28
- 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 +37 -5
- package/lib/pipe/gitlab.d.ts +25 -0
- package/lib/pipe/gitlab.js +29 -11
- package/lib/pipe/html.d.ts +35 -0
- package/lib/pipe/html.js +9 -4
- package/lib/pipe/index.d.ts +1 -0
- package/lib/pipe/index.js +20 -10
- package/lib/pipe/testomatio.d.ts +71 -0
- package/lib/pipe/testomatio.js +117 -92
- 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/services/logger.js +1 -2
- 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 +81 -10
- package/lib/xmlReader.d.ts +92 -0
- package/lib/xmlReader.js +28 -16
- package/package.json +19 -14
- package/src/adapter/codecept.js +30 -26
- package/src/adapter/cypress-plugin/index.js +5 -5
- package/src/adapter/mocha.cjs +1 -1
- package/src/adapter/mocha.js +4 -4
- package/src/adapter/nightwatch.js +88 -0
- package/src/adapter/playwright.js +59 -31
- package/src/adapter/vitest.js +6 -6
- package/src/adapter/webdriver.js +41 -11
- package/src/bin/cli.js +302 -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 -57
- package/src/config.js +2 -2
- package/src/constants.js +5 -1
- package/src/data-storage.js +2 -2
- package/src/pipe/bitbucket.js +24 -26
- package/src/pipe/csv.js +3 -3
- package/src/pipe/debug.js +104 -0
- package/src/pipe/github.js +3 -5
- package/src/pipe/gitlab.js +33 -15
- package/src/pipe/html.js +14 -7
- package/src/pipe/index.js +5 -7
- package/src/pipe/testomatio.js +156 -158
- 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 +5 -4
- 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 +50 -14
- package/src/xmlReader.js +32 -18
- 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/adapter/codecept.js
CHANGED
|
@@ -10,8 +10,6 @@ const client_js_1 = __importDefault(require("../client.js"));
|
|
|
10
10
|
const constants_js_1 = require("../constants.js");
|
|
11
11
|
const utils_js_1 = require("../utils/utils.js");
|
|
12
12
|
const index_js_1 = require("../services/index.js");
|
|
13
|
-
const fileUploader_js_1 = require("../fileUploader.js");
|
|
14
|
-
// eslint-disable-next-line
|
|
15
13
|
const codeceptjs_1 = __importDefault(require("codeceptjs"));
|
|
16
14
|
const debug = (0, debug_1.default)('@testomatio/reporter:adapter:codeceptjs');
|
|
17
15
|
// @ts-ignore
|
|
@@ -41,8 +39,10 @@ function CodeceptReporter(config) {
|
|
|
41
39
|
const testTimeMap = {};
|
|
42
40
|
const { apiKey } = config;
|
|
43
41
|
const getDuration = test => {
|
|
44
|
-
if (
|
|
45
|
-
return
|
|
42
|
+
if (!test.uid)
|
|
43
|
+
return 0;
|
|
44
|
+
if (testTimeMap[test.uid]) {
|
|
45
|
+
return Date.now() - testTimeMap[test.uid];
|
|
46
46
|
}
|
|
47
47
|
return 0;
|
|
48
48
|
};
|
|
@@ -103,24 +103,24 @@ function CodeceptReporter(config) {
|
|
|
103
103
|
event.dispatcher.on(event.test.started, test => {
|
|
104
104
|
index_js_1.services.setContext(test.fullTitle());
|
|
105
105
|
testTimeMap[test.id] = Date.now();
|
|
106
|
-
|
|
106
|
+
if (!test.uid)
|
|
107
|
+
return;
|
|
108
|
+
testTimeMap[test.uid] = Date.now();
|
|
107
109
|
});
|
|
108
110
|
event.dispatcher.on(event.all.result, async () => {
|
|
109
111
|
debug('waiting for all tests to be reported');
|
|
110
112
|
// all tests were reported and we can upload videos
|
|
111
113
|
await Promise.all(reportTestPromises);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
await uploadAttachments(client, traces, '📁 Uploading', 'trace');
|
|
115
|
-
}
|
|
114
|
+
await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
|
|
115
|
+
await uploadAttachments(client, traces, '📁 Uploading', 'trace');
|
|
116
116
|
const status = failedTests.length === 0 ? constants_js_1.STATUS.PASSED : constants_js_1.STATUS.FAILED;
|
|
117
117
|
// @ts-ignore
|
|
118
118
|
client.updateRunStatus(status);
|
|
119
119
|
});
|
|
120
120
|
event.dispatcher.on(event.test.passed, test => {
|
|
121
|
-
const {
|
|
122
|
-
if (
|
|
123
|
-
failedTests = failedTests.filter(failed =>
|
|
121
|
+
const { uid, tags, title } = test;
|
|
122
|
+
if (uid && failedTests.includes(uid)) {
|
|
123
|
+
failedTests = failedTests.filter(failed => uid !== failed);
|
|
124
124
|
}
|
|
125
125
|
const testObj = getTestAndMessage(title);
|
|
126
126
|
const logs = getTestLogs(test);
|
|
@@ -129,7 +129,7 @@ function CodeceptReporter(config) {
|
|
|
129
129
|
index_js_1.services.setContext(null);
|
|
130
130
|
client.addTestRun(constants_js_1.STATUS.PASSED, {
|
|
131
131
|
...stripExampleFromTitle(title),
|
|
132
|
-
rid:
|
|
132
|
+
rid: uid,
|
|
133
133
|
suite_title: test.parent && test.parent.title,
|
|
134
134
|
message: testObj.message,
|
|
135
135
|
time: getDuration(test),
|
|
@@ -151,11 +151,11 @@ function CodeceptReporter(config) {
|
|
|
151
151
|
if (!suite.tests)
|
|
152
152
|
return;
|
|
153
153
|
for (const test of suite.tests) {
|
|
154
|
-
const {
|
|
155
|
-
failedTests.push(
|
|
154
|
+
const { uid, tags, title } = test;
|
|
155
|
+
failedTests.push(uid || title);
|
|
156
156
|
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`);
|
|
157
157
|
client.addTestRun(constants_js_1.STATUS.FAILED, {
|
|
158
|
-
rid:
|
|
158
|
+
rid: uid,
|
|
159
159
|
...stripExampleFromTitle(title),
|
|
160
160
|
suite_title: suite.title,
|
|
161
161
|
test_id: testId,
|
|
@@ -170,8 +170,8 @@ function CodeceptReporter(config) {
|
|
|
170
170
|
return;
|
|
171
171
|
if (test.err)
|
|
172
172
|
error = test.err;
|
|
173
|
-
const {
|
|
174
|
-
failedTests.push(
|
|
173
|
+
const { uid, tags, title, artifacts } = test;
|
|
174
|
+
failedTests.push(uid || title);
|
|
175
175
|
const testObj = getTestAndMessage(title);
|
|
176
176
|
const files = [];
|
|
177
177
|
if (artifacts.screenshot)
|
|
@@ -183,7 +183,7 @@ function CodeceptReporter(config) {
|
|
|
183
183
|
index_js_1.services.setContext(null);
|
|
184
184
|
client.addTestRun(constants_js_1.STATUS.FAILED, {
|
|
185
185
|
...stripExampleFromTitle(title),
|
|
186
|
-
rid:
|
|
186
|
+
rid: uid,
|
|
187
187
|
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
|
|
188
188
|
suite_title: test.parent && test.parent.title,
|
|
189
189
|
error,
|
|
@@ -198,19 +198,19 @@ function CodeceptReporter(config) {
|
|
|
198
198
|
debug('artifacts', artifacts);
|
|
199
199
|
for (const aid in artifacts) {
|
|
200
200
|
if (aid.startsWith('video'))
|
|
201
|
-
videos.push({ rid:
|
|
201
|
+
videos.push({ rid: uid, title, path: artifacts[aid], type: 'video/webm' });
|
|
202
202
|
if (aid.startsWith('trace'))
|
|
203
|
-
traces.push({ rid:
|
|
203
|
+
traces.push({ rid: uid, title, path: artifacts[aid], type: 'application/zip' });
|
|
204
204
|
}
|
|
205
205
|
// output.stop();
|
|
206
206
|
});
|
|
207
207
|
event.dispatcher.on(event.test.skipped, test => {
|
|
208
|
-
const {
|
|
209
|
-
if (failedTests.includes(
|
|
208
|
+
const { uid, tags, title } = test;
|
|
209
|
+
if (failedTests.includes(uid || title))
|
|
210
210
|
return;
|
|
211
211
|
const testObj = getTestAndMessage(title);
|
|
212
212
|
client.addTestRun(constants_js_1.STATUS.SKIPPED, {
|
|
213
|
-
rid:
|
|
213
|
+
rid: uid,
|
|
214
214
|
...stripExampleFromTitle(title),
|
|
215
215
|
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
|
|
216
216
|
suite_title: test.parent && test.parent.title,
|
|
@@ -237,7 +237,6 @@ function CodeceptReporter(config) {
|
|
|
237
237
|
for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
|
|
238
238
|
if (currentMetaStep[i] !== metaSteps[i]) {
|
|
239
239
|
stepShift = 2 * i;
|
|
240
|
-
// eslint-disable-next-line no-continue
|
|
241
240
|
if (!metaSteps[i])
|
|
242
241
|
continue;
|
|
243
242
|
if (metaSteps[i].isBDD()) {
|
|
@@ -274,10 +273,15 @@ function CodeceptReporter(config) {
|
|
|
274
273
|
async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
|
|
275
274
|
if (!attachments?.length)
|
|
276
275
|
return;
|
|
277
|
-
|
|
276
|
+
if (client.uploader.isEnabled) {
|
|
277
|
+
console.log(constants_js_1.APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
|
|
278
|
+
}
|
|
278
279
|
const promises = attachments.map(async (attachment) => {
|
|
279
280
|
const { rid, title, path, type } = attachment;
|
|
280
281
|
const file = { path, type, title };
|
|
282
|
+
// we are storing file if upload is disabled
|
|
283
|
+
if (!client.uploader.isEnabled)
|
|
284
|
+
return client.uploader.storeUploadedFile(path, client.runId, rid, false);
|
|
281
285
|
return client.addTestRun(undefined, {
|
|
282
286
|
...stripExampleFromTitle(title),
|
|
283
287
|
rid,
|
|
@@ -318,5 +322,6 @@ function getTestLogs(test) {
|
|
|
318
322
|
}
|
|
319
323
|
return logs;
|
|
320
324
|
}
|
|
325
|
+
module.exports = CodeceptReporter;
|
|
321
326
|
|
|
322
327
|
module.exports.CodeceptReporter = CodeceptReporter;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default CucumberReporter;
|
|
2
|
+
export class CucumberReporter extends Formatter {
|
|
3
|
+
constructor(options: any);
|
|
4
|
+
failures: any[];
|
|
5
|
+
cases: any[];
|
|
6
|
+
client: TestomatClient;
|
|
7
|
+
status: string;
|
|
8
|
+
parseEnvelope(envelope: any): void;
|
|
9
|
+
onTestCaseStarted(testCaseStarted: any): void;
|
|
10
|
+
onTestCaseFinished(testCaseFinished: any): void;
|
|
11
|
+
onTestRunFinished(envelope: any): void;
|
|
12
|
+
}
|
|
13
|
+
import { Formatter } from '@cucumber/cucumber';
|
|
14
|
+
import TestomatClient from '../../client.js';
|
|
File without changes
|
|
@@ -40,20 +40,20 @@ const testomatioReporter = on => {
|
|
|
40
40
|
const suiteId = (0, utils_js_1.parseSuite)(suiteTitle);
|
|
41
41
|
if (!error && test.displayError) {
|
|
42
42
|
error = { message: test.displayError };
|
|
43
|
-
// eslint-disable-next-line
|
|
44
43
|
error.inspect = function () {
|
|
45
44
|
return this.message;
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
|
-
const formattedError = error
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
const formattedError = error
|
|
48
|
+
? {
|
|
49
|
+
message: error.message,
|
|
50
|
+
name: error.name,
|
|
51
|
+
inspect: error.inspect ||
|
|
52
|
+
function () {
|
|
53
|
+
return this.message;
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
: undefined;
|
|
57
57
|
const screenshots = Array.isArray(results.screenshots)
|
|
58
58
|
? results.screenshots
|
|
59
59
|
.filter(screenshot => screenshot?.path && screenshot?.path.includes(title) && screenshot?.takenAt)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default JasmineReporter;
|
|
2
|
+
export class JasmineReporter {
|
|
3
|
+
constructor(options: any);
|
|
4
|
+
testTimeMap: {};
|
|
5
|
+
client: TestomatClient;
|
|
6
|
+
getDuration(test: any): number;
|
|
7
|
+
specStarted(result: any): void;
|
|
8
|
+
specDone(result: any): void;
|
|
9
|
+
jasmineDone(suiteInfo: any, done: any): void;
|
|
10
|
+
}
|
|
11
|
+
import TestomatClient from '../client.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class JestReporter {
|
|
2
|
+
constructor(globalConfig: any, options: any);
|
|
3
|
+
_globalConfig: any;
|
|
4
|
+
_options: any;
|
|
5
|
+
client: TestomatClient;
|
|
6
|
+
onRunStart(): void;
|
|
7
|
+
onTestStart(testFile: any): void;
|
|
8
|
+
onTestCaseStart(test: any, testCase: any): void;
|
|
9
|
+
onTestResult(test: any, testResult: any): void;
|
|
10
|
+
onRunComplete(contexts: any, results: any): void;
|
|
11
|
+
}
|
|
12
|
+
export default JestReporter;
|
|
13
|
+
import TestomatClient from '../client.js';
|
package/lib/adapter/mocha.js
CHANGED
|
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
7
6
|
const mocha_1 = __importDefault(require("mocha"));
|
|
8
7
|
const client_js_1 = __importDefault(require("../client.js"));
|
|
9
8
|
const constants_js_1 = require("../constants.js");
|
|
@@ -22,6 +21,7 @@ function MochaReporter(runner, opts) {
|
|
|
22
21
|
const client = new client_js_1.default({ apiKey });
|
|
23
22
|
runner.on(EVENT_RUN_BEGIN, () => {
|
|
24
23
|
client.createRun();
|
|
24
|
+
// clear dir with artifacts/logs
|
|
25
25
|
utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
|
|
26
26
|
});
|
|
27
27
|
runner.on(EVENT_SUITE_BEGIN, async (suite) => {
|
|
@@ -47,7 +47,7 @@ function MochaReporter(runner, opts) {
|
|
|
47
47
|
test_id: testId,
|
|
48
48
|
suite_title: getSuiteTitle(test),
|
|
49
49
|
title: getTestName(test),
|
|
50
|
-
code: test.body.toString(),
|
|
50
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
51
51
|
file: getFile(test),
|
|
52
52
|
time: test.duration,
|
|
53
53
|
logs,
|
|
@@ -62,7 +62,7 @@ function MochaReporter(runner, opts) {
|
|
|
62
62
|
client.addTestRun(constants_js_1.STATUS.SKIPPED, {
|
|
63
63
|
title: getTestName(test),
|
|
64
64
|
suite_title: getSuiteTitle(test),
|
|
65
|
-
code: test.body.toString(),
|
|
65
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
66
66
|
file: getFile(test),
|
|
67
67
|
test_id: testId,
|
|
68
68
|
time: test.duration,
|
|
@@ -79,7 +79,7 @@ function MochaReporter(runner, opts) {
|
|
|
79
79
|
file: getFile(test),
|
|
80
80
|
test_id: testId,
|
|
81
81
|
title: getTestName(test),
|
|
82
|
-
code: test.body.toString(),
|
|
82
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
83
83
|
time: test.duration,
|
|
84
84
|
logs,
|
|
85
85
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
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 client_js_1 = __importDefault(require("../client.js"));
|
|
7
|
+
const config_js_1 = require("../config.js");
|
|
8
|
+
const constants_1 = require("../constants");
|
|
9
|
+
const utils_js_1 = require("../utils/utils.js");
|
|
10
|
+
const apiKey = config_js_1.config.TESTOMATIO;
|
|
11
|
+
const client = new client_js_1.default({ apiKey });
|
|
12
|
+
module.exports = {
|
|
13
|
+
write: async (results, options, done) => {
|
|
14
|
+
await client.createRun();
|
|
15
|
+
const testFiles = results.modules;
|
|
16
|
+
for (const fileName in testFiles) {
|
|
17
|
+
// in nightwatch: object containing tests from a single file
|
|
18
|
+
const testModule = testFiles[fileName];
|
|
19
|
+
// passed and failed tests (tests with assertions)
|
|
20
|
+
const completedTests = testModule.completed;
|
|
21
|
+
// skipped tests (skipped by user or tests without assertions)
|
|
22
|
+
const skippedTests = testModule.skipped;
|
|
23
|
+
const tags = testModule.tags || [];
|
|
24
|
+
// if test file contains multiple suites, the last suite name is used as a name 🤷♂️
|
|
25
|
+
// no other places which contain suite name (even inside test object)
|
|
26
|
+
const suiteTitle = testModule.name;
|
|
27
|
+
for (const testTitle in completedTests) {
|
|
28
|
+
const test = completedTests[testTitle];
|
|
29
|
+
let status;
|
|
30
|
+
switch (test.status) {
|
|
31
|
+
case 'pass':
|
|
32
|
+
status = constants_1.STATUS.PASSED;
|
|
33
|
+
break;
|
|
34
|
+
case 'fail':
|
|
35
|
+
status = constants_1.STATUS.FAILED;
|
|
36
|
+
break;
|
|
37
|
+
// probably not required (because skipped tests are in separate array), but just in case
|
|
38
|
+
case 'skip':
|
|
39
|
+
status = constants_1.STATUS.SKIPPED;
|
|
40
|
+
console.info('Skipped test is in completed tests array:', test, 'Not expected behavior.');
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
console.error('Test status processing error:', test.status);
|
|
44
|
+
}
|
|
45
|
+
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(testTitle);
|
|
46
|
+
client.addTestRun(status, {
|
|
47
|
+
error: { name: test.assertions?.[0]?.name, message: test.assertions?.[0]?.message, stack: test.stackTrace },
|
|
48
|
+
file: testModule.modulePath?.replace(process.cwd(), ''),
|
|
49
|
+
message: test.assertions?.[0]?.message,
|
|
50
|
+
rid: `${testModule.uuid || ''}_${testTitle || ''}`,
|
|
51
|
+
stack: test.stackTrace,
|
|
52
|
+
suite_title: suiteTitle,
|
|
53
|
+
tags,
|
|
54
|
+
test_id: testId,
|
|
55
|
+
time: test.timeMs,
|
|
56
|
+
title: testTitle,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// just array with skipped tests titles, no any other info
|
|
60
|
+
for (const testTitle of skippedTests) {
|
|
61
|
+
client.addTestRun(constants_1.STATUS.SKIPPED, {
|
|
62
|
+
suite_title: suiteTitle,
|
|
63
|
+
tags,
|
|
64
|
+
rid: `${testModule.uuid || ''}_${testTitle || ''}`,
|
|
65
|
+
title: testTitle,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* @type {'passed' | 'failed' | 'finished'}
|
|
71
|
+
*/
|
|
72
|
+
let runStatus = 'finished';
|
|
73
|
+
if (results.failed)
|
|
74
|
+
runStatus = 'failed';
|
|
75
|
+
else if (results.passed)
|
|
76
|
+
runStatus = 'passed';
|
|
77
|
+
await client.updateRunStatus(runStatus);
|
|
78
|
+
done();
|
|
79
|
+
},
|
|
80
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default PlaywrightReporter;
|
|
2
|
+
declare class PlaywrightReporter {
|
|
3
|
+
constructor(config?: {});
|
|
4
|
+
client: TestomatioClient;
|
|
5
|
+
uploads: any[];
|
|
6
|
+
onBegin(config: any, suite: any): void;
|
|
7
|
+
suite: any;
|
|
8
|
+
config: any;
|
|
9
|
+
onTestBegin(testInfo: any): void;
|
|
10
|
+
onTestEnd(test: any, result: any): void;
|
|
11
|
+
onEnd(result: any): Promise<void>;
|
|
12
|
+
#private;
|
|
13
|
+
}
|
|
14
|
+
import TestomatioClient from '../client.js';
|
|
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.initPlaywrightForStorage = initPlaywrightForStorage;
|
|
7
6
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
8
7
|
const crypto_1 = __importDefault(require("crypto"));
|
|
9
8
|
const os_1 = __importDefault(require("os"));
|
|
@@ -12,7 +11,6 @@ const uuid_1 = require("uuid");
|
|
|
12
11
|
const fs_1 = __importDefault(require("fs"));
|
|
13
12
|
const constants_js_1 = require("../constants.js");
|
|
14
13
|
const client_js_1 = __importDefault(require("../client.js"));
|
|
15
|
-
const fileUploader_js_1 = require("../fileUploader.js");
|
|
16
14
|
const utils_js_1 = require("../utils/utils.js");
|
|
17
15
|
const index_js_1 = require("../services/index.js");
|
|
18
16
|
const data_storage_js_1 = require("../data-storage.js");
|
|
@@ -55,10 +53,36 @@ class PlaywrightReporter {
|
|
|
55
53
|
logs = `\n\n${picocolors_1.default.bold('Logs:')}\n${picocolors_1.default.red(result.stderr.join(''))}\n${result.stdout.join('')}`;
|
|
56
54
|
}
|
|
57
55
|
const manuallyAttachedArtifacts = index_js_1.services.artifacts.get(fullTestTitle);
|
|
58
|
-
const
|
|
56
|
+
const testMeta = index_js_1.services.keyValues.get(fullTestTitle);
|
|
59
57
|
const rid = test.id || test.testId || (0, uuid_1.v4)();
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
/**
|
|
59
|
+
* @type {{
|
|
60
|
+
* browser?: string,
|
|
61
|
+
* dependencies: string[],
|
|
62
|
+
* isMobile?: boolean
|
|
63
|
+
* metadata: Record<string, any>,
|
|
64
|
+
* name: string,
|
|
65
|
+
* }}
|
|
66
|
+
*/
|
|
67
|
+
const project = {
|
|
68
|
+
browser: test.parent.project().use.defaultBrowserType,
|
|
69
|
+
dependencies: test.parent.project().dependencies,
|
|
70
|
+
isMobile: test.parent.project().use.isMobile,
|
|
71
|
+
metadata: test.parent.project().metadata,
|
|
72
|
+
name: test.parent.project().name,
|
|
73
|
+
};
|
|
74
|
+
let status = result.status;
|
|
75
|
+
// process test.fail() annotation
|
|
76
|
+
if (test.expectedStatus === 'failed') {
|
|
77
|
+
// actual status = expected
|
|
78
|
+
if (result.status === 'failed')
|
|
79
|
+
status = 'passed';
|
|
80
|
+
// actual status != expected
|
|
81
|
+
if (result.status === 'passed')
|
|
82
|
+
status = 'failed';
|
|
83
|
+
}
|
|
84
|
+
const reportTestPromise = this.client.addTestRun(checkStatus(status), {
|
|
85
|
+
rid: `${rid}-${project.name}`,
|
|
62
86
|
error,
|
|
63
87
|
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${test.tags?.join(' ')}`),
|
|
64
88
|
suite_title,
|
|
@@ -67,11 +91,18 @@ class PlaywrightReporter {
|
|
|
67
91
|
time: duration,
|
|
68
92
|
logs,
|
|
69
93
|
manuallyAttachedArtifacts,
|
|
70
|
-
meta:
|
|
94
|
+
meta: {
|
|
95
|
+
browser: project.browser,
|
|
96
|
+
isMobile: project.isMobile,
|
|
97
|
+
project: project.name,
|
|
98
|
+
projectDependencies: project.dependencies?.length ? project.dependencies : null,
|
|
99
|
+
...testMeta,
|
|
100
|
+
...project.metadata, // metadata has any type (in playwright), but we will stringify it in client.js
|
|
101
|
+
},
|
|
71
102
|
file: test.location?.file,
|
|
72
103
|
});
|
|
73
104
|
this.uploads.push({
|
|
74
|
-
rid
|
|
105
|
+
rid: `${rid}-${project.name}`,
|
|
75
106
|
title: test.title,
|
|
76
107
|
files: result.attachments.filter(a => a.body || a.path),
|
|
77
108
|
file: test.location?.file,
|
|
@@ -87,9 +118,12 @@ class PlaywrightReporter {
|
|
|
87
118
|
return path_1.default.join(this.config.outputDir || this.config.projects[0].outputDir, artifact.path);
|
|
88
119
|
}
|
|
89
120
|
if (artifact.body) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
121
|
+
let filePath = generateTmpFilepath(artifact.name);
|
|
122
|
+
const extension = artifact.contentType?.split('/')[1]?.replace('jpeg', 'jpg');
|
|
123
|
+
if (extension)
|
|
124
|
+
filePath += `.${extension}`;
|
|
125
|
+
fs_1.default.writeFileSync(filePath, artifact.body);
|
|
126
|
+
return filePath;
|
|
93
127
|
}
|
|
94
128
|
return null;
|
|
95
129
|
}
|
|
@@ -97,16 +131,22 @@ class PlaywrightReporter {
|
|
|
97
131
|
if (!this.client)
|
|
98
132
|
return;
|
|
99
133
|
await Promise.all(reportTestPromises);
|
|
100
|
-
if (this.uploads.length
|
|
101
|
-
|
|
134
|
+
if (this.uploads.length) {
|
|
135
|
+
if (this.client.uploader.isEnabled)
|
|
136
|
+
console.log(constants_js_1.APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
|
|
102
137
|
const promises = [];
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const
|
|
138
|
+
// ? possible move to addTestRun (needs investigation if files are ready)
|
|
139
|
+
for (const upload of this.uploads) {
|
|
140
|
+
const { rid, file, title } = upload;
|
|
141
|
+
const files = upload.files.map(attachment => ({
|
|
106
142
|
path: this.#getArtifactPath(attachment),
|
|
107
143
|
title,
|
|
108
144
|
type: attachment.contentType,
|
|
109
145
|
}));
|
|
146
|
+
if (!this.client.uploader.isEnabled) {
|
|
147
|
+
files.forEach(f => this.client.uploader.storeUploadedFile(f, this.client.runId, rid, false));
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
110
150
|
promises.push(this.client.addTestRun(undefined, {
|
|
111
151
|
rid,
|
|
112
152
|
title,
|
|
@@ -163,9 +203,10 @@ function appendStep(step, shift = 0) {
|
|
|
163
203
|
}
|
|
164
204
|
return resultStep;
|
|
165
205
|
}
|
|
166
|
-
function
|
|
206
|
+
function generateTmpFilepath(filename = '') {
|
|
207
|
+
filename = filename || `tmp.${crypto_1.default.randomBytes(16).toString('hex')}`;
|
|
167
208
|
const tmpdir = os_1.default.tmpdir();
|
|
168
|
-
return path_1.default.join(tmpdir,
|
|
209
|
+
return path_1.default.join(tmpdir, filename);
|
|
169
210
|
}
|
|
170
211
|
/**
|
|
171
212
|
* Returns filename + test title
|
|
@@ -175,20 +216,4 @@ function tmpFile(prefix = 'tmp.') {
|
|
|
175
216
|
function getTestContextName(test) {
|
|
176
217
|
return `${test._requireFile || ''}_${test.title}`;
|
|
177
218
|
}
|
|
178
|
-
function initPlaywrightForStorage() {
|
|
179
|
-
try {
|
|
180
|
-
// @ts-ignore-next-line
|
|
181
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
182
|
-
const { test } = require('@playwright/test');
|
|
183
|
-
// eslint-disable-next-line no-empty-pattern
|
|
184
|
-
test.beforeEach(async ({}, testInfo) => {
|
|
185
|
-
global.testomatioTestTitle = `${testInfo.file || ''}_${testInfo.title}`;
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
catch (e) {
|
|
189
|
-
// ignore
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
219
|
module.exports = PlaywrightReporter;
|
|
193
|
-
|
|
194
|
-
module.exports.initPlaywrightForStorage = initPlaywrightForStorage;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export default VitestReporter;
|
|
2
|
+
export type VitestTest = import("../../types/types.js").VitestTest;
|
|
3
|
+
export type VitestTestFile = import("../../types/types.js").VitestTestFile;
|
|
4
|
+
export type VitestSuite = import("../../types/types.js").VitestSuite;
|
|
5
|
+
export type VitestTestLogs = import("../../types/types.js").VitestTestLogs;
|
|
6
|
+
export type ErrorWithDiff = import("../../types/vitest.types.js").ErrorWithDiff;
|
|
7
|
+
export type STATUS = typeof import("../constants.js").STATUS;
|
|
8
|
+
export type TestData = import("../../types/types.js").TestData;
|
|
9
|
+
/**
|
|
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
|
+
* @typedef {typeof import('../constants.js').STATUS} STATUS
|
|
16
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
17
|
+
*/
|
|
18
|
+
export class VitestReporter {
|
|
19
|
+
constructor(config?: {});
|
|
20
|
+
client: TestomatioClient;
|
|
21
|
+
/**
|
|
22
|
+
* @type {(TestData & {status: string})[]} tests
|
|
23
|
+
*/
|
|
24
|
+
tests: (TestData & {
|
|
25
|
+
status: string;
|
|
26
|
+
})[];
|
|
27
|
+
onInit(): void;
|
|
28
|
+
/**
|
|
29
|
+
* @param {VitestTestFile[] | undefined} files // array with results;
|
|
30
|
+
* @param {unknown[] | undefined} errors // errors does not contain errors from tests; probably its testrunner errors
|
|
31
|
+
*/
|
|
32
|
+
onFinished(files: VitestTestFile[] | undefined, errors: unknown[] | undefined): Promise<void>;
|
|
33
|
+
#private;
|
|
34
|
+
}
|
|
35
|
+
import { Client as TestomatioClient } from '../client.js';
|
package/lib/adapter/vitest.js
CHANGED
|
@@ -11,13 +11,13 @@ const utils_js_1 = require("../utils/utils.js");
|
|
|
11
11
|
const debug_1 = __importDefault(require("debug"));
|
|
12
12
|
const debug = (0, debug_1.default)('@testomatio/reporter:adapter-jest');
|
|
13
13
|
/**
|
|
14
|
-
* @typedef {import('../../types').VitestTest} VitestTest
|
|
15
|
-
* @typedef {import('../../types').VitestTestFile} VitestTestFile
|
|
16
|
-
* @typedef {import('../../types').VitestSuite} VitestSuite
|
|
17
|
-
* @typedef {import('../../types').VitestTestLogs} VitestTestLogs
|
|
18
|
-
* @typedef {import('../../vitest.types').ErrorWithDiff} ErrorWithDiff
|
|
14
|
+
* @typedef {import('../../types/types.js').VitestTest} VitestTest
|
|
15
|
+
* @typedef {import('../../types/types.js').VitestTestFile} VitestTestFile
|
|
16
|
+
* @typedef {import('../../types/types.js').VitestSuite} VitestSuite
|
|
17
|
+
* @typedef {import('../../types/types.js').VitestTestLogs} VitestTestLogs
|
|
18
|
+
* @typedef {import('../../types/vitest.types.js').ErrorWithDiff} ErrorWithDiff
|
|
19
19
|
* @typedef {typeof import('../constants.js').STATUS} STATUS
|
|
20
|
-
* @typedef {import('../../types').TestData} TestData
|
|
20
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
21
21
|
*/
|
|
22
22
|
class VitestReporter {
|
|
23
23
|
constructor(config = {}) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default WebdriverReporter;
|
|
2
|
+
declare class WebdriverReporter extends WDIOReporter {
|
|
3
|
+
constructor(options: any);
|
|
4
|
+
client: TestomatClient;
|
|
5
|
+
_addTestPromises: any[];
|
|
6
|
+
_isSynchronising: boolean;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {RunnerStats} runData
|
|
10
|
+
*/
|
|
11
|
+
onRunnerEnd(runData: RunnerStats): Promise<void>;
|
|
12
|
+
onRunnerStart(): void;
|
|
13
|
+
onTestStart(test: any): void;
|
|
14
|
+
onTestEnd(test: any): void;
|
|
15
|
+
onSuiteEnd(scerario: any): void;
|
|
16
|
+
addTest(test: any): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('../../types/types.js').WebdriverIOScenario} scenario
|
|
19
|
+
*/
|
|
20
|
+
addBddScenario(scenario: import("../../types/types.js").WebdriverIOScenario): Promise<import("../../types/types.js").PipeResult[]>;
|
|
21
|
+
}
|
|
22
|
+
import WDIOReporter from '@wdio/reporter';
|
|
23
|
+
import TestomatClient from '../client.js';
|
|
24
|
+
import { RunnerStats } from '@wdio/reporter';
|