@testomatio/reporter 2.0.0-beta-esm → 2.0.1-beta-ignore-xml
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 +27 -16
- 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,7 +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
13
|
// eslint-disable-next-line
|
|
15
14
|
const codeceptjs_1 = __importDefault(require("codeceptjs"));
|
|
16
15
|
const debug = (0, debug_1.default)('@testomatio/reporter:adapter:codeceptjs');
|
|
@@ -41,8 +40,10 @@ function CodeceptReporter(config) {
|
|
|
41
40
|
const testTimeMap = {};
|
|
42
41
|
const { apiKey } = config;
|
|
43
42
|
const getDuration = test => {
|
|
44
|
-
if (
|
|
45
|
-
return
|
|
43
|
+
if (!test.uid)
|
|
44
|
+
return 0;
|
|
45
|
+
if (testTimeMap[test.uid]) {
|
|
46
|
+
return Date.now() - testTimeMap[test.uid];
|
|
46
47
|
}
|
|
47
48
|
return 0;
|
|
48
49
|
};
|
|
@@ -103,24 +104,24 @@ function CodeceptReporter(config) {
|
|
|
103
104
|
event.dispatcher.on(event.test.started, test => {
|
|
104
105
|
index_js_1.services.setContext(test.fullTitle());
|
|
105
106
|
testTimeMap[test.id] = Date.now();
|
|
106
|
-
|
|
107
|
+
if (!test.uid)
|
|
108
|
+
return;
|
|
109
|
+
testTimeMap[test.uid] = Date.now();
|
|
107
110
|
});
|
|
108
111
|
event.dispatcher.on(event.all.result, async () => {
|
|
109
112
|
debug('waiting for all tests to be reported');
|
|
110
113
|
// all tests were reported and we can upload videos
|
|
111
114
|
await Promise.all(reportTestPromises);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
await uploadAttachments(client, traces, '📁 Uploading', 'trace');
|
|
115
|
-
}
|
|
115
|
+
await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
|
|
116
|
+
await uploadAttachments(client, traces, '📁 Uploading', 'trace');
|
|
116
117
|
const status = failedTests.length === 0 ? constants_js_1.STATUS.PASSED : constants_js_1.STATUS.FAILED;
|
|
117
118
|
// @ts-ignore
|
|
118
119
|
client.updateRunStatus(status);
|
|
119
120
|
});
|
|
120
121
|
event.dispatcher.on(event.test.passed, test => {
|
|
121
|
-
const {
|
|
122
|
-
if (
|
|
123
|
-
failedTests = failedTests.filter(failed =>
|
|
122
|
+
const { uid, tags, title } = test;
|
|
123
|
+
if (uid && failedTests.includes(uid)) {
|
|
124
|
+
failedTests = failedTests.filter(failed => uid !== failed);
|
|
124
125
|
}
|
|
125
126
|
const testObj = getTestAndMessage(title);
|
|
126
127
|
const logs = getTestLogs(test);
|
|
@@ -129,7 +130,7 @@ function CodeceptReporter(config) {
|
|
|
129
130
|
index_js_1.services.setContext(null);
|
|
130
131
|
client.addTestRun(constants_js_1.STATUS.PASSED, {
|
|
131
132
|
...stripExampleFromTitle(title),
|
|
132
|
-
rid:
|
|
133
|
+
rid: uid,
|
|
133
134
|
suite_title: test.parent && test.parent.title,
|
|
134
135
|
message: testObj.message,
|
|
135
136
|
time: getDuration(test),
|
|
@@ -151,11 +152,11 @@ function CodeceptReporter(config) {
|
|
|
151
152
|
if (!suite.tests)
|
|
152
153
|
return;
|
|
153
154
|
for (const test of suite.tests) {
|
|
154
|
-
const {
|
|
155
|
-
failedTests.push(
|
|
155
|
+
const { uid, tags, title } = test;
|
|
156
|
+
failedTests.push(uid || title);
|
|
156
157
|
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`);
|
|
157
158
|
client.addTestRun(constants_js_1.STATUS.FAILED, {
|
|
158
|
-
rid:
|
|
159
|
+
rid: uid,
|
|
159
160
|
...stripExampleFromTitle(title),
|
|
160
161
|
suite_title: suite.title,
|
|
161
162
|
test_id: testId,
|
|
@@ -170,8 +171,8 @@ function CodeceptReporter(config) {
|
|
|
170
171
|
return;
|
|
171
172
|
if (test.err)
|
|
172
173
|
error = test.err;
|
|
173
|
-
const {
|
|
174
|
-
failedTests.push(
|
|
174
|
+
const { uid, tags, title, artifacts } = test;
|
|
175
|
+
failedTests.push(uid || title);
|
|
175
176
|
const testObj = getTestAndMessage(title);
|
|
176
177
|
const files = [];
|
|
177
178
|
if (artifacts.screenshot)
|
|
@@ -183,7 +184,7 @@ function CodeceptReporter(config) {
|
|
|
183
184
|
index_js_1.services.setContext(null);
|
|
184
185
|
client.addTestRun(constants_js_1.STATUS.FAILED, {
|
|
185
186
|
...stripExampleFromTitle(title),
|
|
186
|
-
rid:
|
|
187
|
+
rid: uid,
|
|
187
188
|
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
|
|
188
189
|
suite_title: test.parent && test.parent.title,
|
|
189
190
|
error,
|
|
@@ -198,19 +199,19 @@ function CodeceptReporter(config) {
|
|
|
198
199
|
debug('artifacts', artifacts);
|
|
199
200
|
for (const aid in artifacts) {
|
|
200
201
|
if (aid.startsWith('video'))
|
|
201
|
-
videos.push({ rid:
|
|
202
|
+
videos.push({ rid: uid, title, path: artifacts[aid], type: 'video/webm' });
|
|
202
203
|
if (aid.startsWith('trace'))
|
|
203
|
-
traces.push({ rid:
|
|
204
|
+
traces.push({ rid: uid, title, path: artifacts[aid], type: 'application/zip' });
|
|
204
205
|
}
|
|
205
206
|
// output.stop();
|
|
206
207
|
});
|
|
207
208
|
event.dispatcher.on(event.test.skipped, test => {
|
|
208
|
-
const {
|
|
209
|
-
if (failedTests.includes(
|
|
209
|
+
const { uid, tags, title } = test;
|
|
210
|
+
if (failedTests.includes(uid || title))
|
|
210
211
|
return;
|
|
211
212
|
const testObj = getTestAndMessage(title);
|
|
212
213
|
client.addTestRun(constants_js_1.STATUS.SKIPPED, {
|
|
213
|
-
rid:
|
|
214
|
+
rid: uid,
|
|
214
215
|
...stripExampleFromTitle(title),
|
|
215
216
|
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
|
|
216
217
|
suite_title: test.parent && test.parent.title,
|
|
@@ -274,10 +275,15 @@ function CodeceptReporter(config) {
|
|
|
274
275
|
async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
|
|
275
276
|
if (!attachments?.length)
|
|
276
277
|
return;
|
|
277
|
-
|
|
278
|
+
if (client.uploader.isEnabled) {
|
|
279
|
+
console.log(constants_js_1.APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
|
|
280
|
+
}
|
|
278
281
|
const promises = attachments.map(async (attachment) => {
|
|
279
282
|
const { rid, title, path, type } = attachment;
|
|
280
283
|
const file = { path, type, title };
|
|
284
|
+
// we are storing file if upload is disabled
|
|
285
|
+
if (!client.uploader.isEnabled)
|
|
286
|
+
return client.uploader.storeUploadedFile(path, client.runId, rid, false);
|
|
281
287
|
return client.addTestRun(undefined, {
|
|
282
288
|
...stripExampleFromTitle(title),
|
|
283
289
|
rid,
|
|
@@ -318,5 +324,6 @@ function getTestLogs(test) {
|
|
|
318
324
|
}
|
|
319
325
|
return logs;
|
|
320
326
|
}
|
|
327
|
+
module.exports = CodeceptReporter;
|
|
321
328
|
|
|
322
329
|
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
|
|
@@ -45,15 +45,17 @@ const testomatioReporter = on => {
|
|
|
45
45
|
return this.message;
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
const formattedError = error
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
const formattedError = error
|
|
49
|
+
? {
|
|
50
|
+
message: error.message,
|
|
51
|
+
name: error.name,
|
|
52
|
+
inspect: error.inspect ||
|
|
53
|
+
// eslint-disable-next-line
|
|
54
|
+
function () {
|
|
55
|
+
return this.message;
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
: undefined;
|
|
57
59
|
const screenshots = Array.isArray(results.screenshots)
|
|
58
60
|
? results.screenshots
|
|
59
61
|
.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
|
@@ -22,6 +22,7 @@ function MochaReporter(runner, opts) {
|
|
|
22
22
|
const client = new client_js_1.default({ apiKey });
|
|
23
23
|
runner.on(EVENT_RUN_BEGIN, () => {
|
|
24
24
|
client.createRun();
|
|
25
|
+
// clear dir with artifacts/logs
|
|
25
26
|
utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
|
|
26
27
|
});
|
|
27
28
|
runner.on(EVENT_SUITE_BEGIN, async (suite) => {
|
|
@@ -47,7 +48,7 @@ function MochaReporter(runner, opts) {
|
|
|
47
48
|
test_id: testId,
|
|
48
49
|
suite_title: getSuiteTitle(test),
|
|
49
50
|
title: getTestName(test),
|
|
50
|
-
code: test.body.toString(),
|
|
51
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
51
52
|
file: getFile(test),
|
|
52
53
|
time: test.duration,
|
|
53
54
|
logs,
|
|
@@ -62,7 +63,7 @@ function MochaReporter(runner, opts) {
|
|
|
62
63
|
client.addTestRun(constants_js_1.STATUS.SKIPPED, {
|
|
63
64
|
title: getTestName(test),
|
|
64
65
|
suite_title: getSuiteTitle(test),
|
|
65
|
-
code: test.body.toString(),
|
|
66
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
66
67
|
file: getFile(test),
|
|
67
68
|
test_id: testId,
|
|
68
69
|
time: test.duration,
|
|
@@ -79,7 +80,7 @@ function MochaReporter(runner, opts) {
|
|
|
79
80
|
file: getFile(test),
|
|
80
81
|
test_id: testId,
|
|
81
82
|
title: getTestName(test),
|
|
82
|
-
code: test.body.toString(),
|
|
83
|
+
code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
|
|
83
84
|
time: test.duration,
|
|
84
85
|
logs,
|
|
85
86
|
});
|
|
@@ -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';
|
package/lib/adapter/webdriver.js
CHANGED
|
@@ -30,6 +30,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
const reporter_1 = __importStar(require("@wdio/reporter"));
|
|
31
31
|
const client_js_1 = __importDefault(require("../client.js"));
|
|
32
32
|
const utils_js_1 = require("../utils/utils.js");
|
|
33
|
+
const index_js_1 = require("../services/index.js");
|
|
34
|
+
const constants_js_1 = require("../constants.js");
|
|
33
35
|
class WebdriverReporter extends reporter_1.default {
|
|
34
36
|
constructor(options) {
|
|
35
37
|
super(options);
|
|
@@ -51,18 +53,30 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
51
53
|
this._isSynchronising = true;
|
|
52
54
|
await Promise.all(this._addTestPromises);
|
|
53
55
|
this._isSynchronising = false;
|
|
54
|
-
// NOTE: new functionality; may break everything
|
|
56
|
+
// NOTE: new functionality; may break everything
|
|
55
57
|
// also this may require additional status mapping
|
|
56
58
|
await this.client.updateRunStatus(runData.failures ? 'failed' : 'passed');
|
|
57
59
|
}
|
|
60
|
+
onRunnerStart() {
|
|
61
|
+
// clear dir with artifacts/logs
|
|
62
|
+
//
|
|
63
|
+
utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
|
|
64
|
+
}
|
|
65
|
+
onTestStart(test) {
|
|
66
|
+
index_js_1.services.setContext(test.fullTitle);
|
|
67
|
+
}
|
|
58
68
|
onTestEnd(test) {
|
|
69
|
+
test.suite = test.parent;
|
|
70
|
+
const logs = getTestLogs(test.fullTitle);
|
|
71
|
+
// TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
|
|
72
|
+
// const artifacts = services.artifacts.get(test.fullTitle);
|
|
73
|
+
// const keyValues = services.keyValues.get(test.fullTitle);
|
|
74
|
+
test.logs = logs;
|
|
75
|
+
// test.artifacts = artifacts;
|
|
76
|
+
// test.meta = keyValues;
|
|
59
77
|
this._addTestPromises.push(this.addTest(test));
|
|
60
78
|
}
|
|
61
79
|
// wdio-cucumber does not trigger onTestEnd hook, thus, using this one
|
|
62
|
-
/**
|
|
63
|
-
*
|
|
64
|
-
* @returns
|
|
65
|
-
*/
|
|
66
80
|
onSuiteEnd(scerario) {
|
|
67
81
|
if (scerario.type === 'scenario') {
|
|
68
82
|
this._addTestPromises.push(this.addBddScenario(scerario));
|
|
@@ -78,7 +92,10 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
78
92
|
.filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
|
|
79
93
|
.map(el => Buffer.from(el.result.value, 'base64'));
|
|
80
94
|
await this.client.addTestRun(state, {
|
|
95
|
+
manuallyAttachedArtifacts: test.artifacts,
|
|
81
96
|
error,
|
|
97
|
+
logs: test.logs,
|
|
98
|
+
meta: test.meta,
|
|
82
99
|
title,
|
|
83
100
|
test_id: testId,
|
|
84
101
|
time: duration,
|
|
@@ -86,7 +103,7 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
86
103
|
});
|
|
87
104
|
}
|
|
88
105
|
/**
|
|
89
|
-
* @param {import('../../types').WebdriverIOScenario} scenario
|
|
106
|
+
* @param {import('../../types/types.js').WebdriverIOScenario} scenario
|
|
90
107
|
*/
|
|
91
108
|
addBddScenario(scenario) {
|
|
92
109
|
if (!this.client)
|
|
@@ -114,4 +131,15 @@ class WebdriverReporter extends reporter_1.default {
|
|
|
114
131
|
});
|
|
115
132
|
}
|
|
116
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @param {*} fullTestTitle
|
|
137
|
+
* @returns string
|
|
138
|
+
*/
|
|
139
|
+
function getTestLogs(fullTestTitle) {
|
|
140
|
+
const logsArr = index_js_1.services.logger.getLogs(fullTestTitle);
|
|
141
|
+
// remove duplicates (for some reason, logs are duplicated several times)
|
|
142
|
+
const logs = logsArr ? Array.from(new Set(logsArr)).join('\n').trim() : '';
|
|
143
|
+
return logs;
|
|
144
|
+
}
|
|
117
145
|
module.exports = WebdriverReporter;
|
package/lib/bin/cli.d.ts
ADDED