@testomatio/reporter 1.6.13 → 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 +295 -335
- package/lib/adapter/cucumber/current.d.ts +14 -0
- package/lib/adapter/cucumber/current.js +195 -203
- package/lib/adapter/cucumber/legacy.d.ts +0 -0
- package/lib/adapter/cucumber/legacy.js +130 -155
- package/lib/adapter/cucumber.d.ts +2 -0
- package/lib/adapter/cucumber.js +5 -16
- package/lib/adapter/cypress-plugin/index.d.ts +2 -0
- package/lib/adapter/cypress-plugin/index.js +93 -105
- package/lib/adapter/jasmine.d.ts +11 -0
- package/lib/adapter/jasmine.js +54 -53
- package/lib/adapter/jest.d.ts +13 -0
- package/lib/adapter/jest.js +97 -99
- package/lib/adapter/mocha.d.ts +2 -0
- package/lib/adapter/mocha.js +112 -140
- package/lib/adapter/playwright.d.ts +14 -0
- package/lib/adapter/playwright.js +195 -231
- package/lib/adapter/vitest.d.ts +35 -0
- package/lib/adapter/vitest.js +150 -149
- package/lib/adapter/webdriver.d.ts +24 -0
- package/lib/adapter/webdriver.js +134 -119
- package/lib/bin/cli.d.ts +2 -0
- package/lib/bin/cli.js +164 -211
- package/lib/bin/reportXml.d.ts +2 -0
- package/lib/bin/reportXml.js +49 -52
- package/lib/bin/startTest.d.ts +2 -0
- package/lib/bin/startTest.js +82 -95
- package/lib/bin/uploadArtifacts.d.ts +2 -0
- package/lib/bin/uploadArtifacts.js +55 -61
- package/lib/client.d.ts +76 -0
- package/lib/client.js +411 -465
- package/lib/config.d.ts +1 -0
- package/lib/config.js +16 -21
- package/lib/constants.d.ts +25 -0
- package/lib/constants.js +50 -44
- package/lib/data-storage.d.ts +34 -0
- package/lib/data-storage.js +206 -188
- package/lib/junit-adapter/adapter.d.ts +9 -0
- package/lib/junit-adapter/adapter.js +17 -20
- package/lib/junit-adapter/csharp.d.ts +4 -0
- package/lib/junit-adapter/csharp.js +18 -14
- package/lib/junit-adapter/index.d.ts +3 -0
- package/lib/junit-adapter/index.js +27 -25
- package/lib/junit-adapter/java.d.ts +5 -0
- package/lib/junit-adapter/java.js +41 -53
- package/lib/junit-adapter/javascript.d.ts +4 -0
- package/lib/junit-adapter/javascript.js +30 -27
- package/lib/junit-adapter/python.d.ts +5 -0
- package/lib/junit-adapter/python.js +38 -37
- package/lib/junit-adapter/ruby.d.ts +4 -0
- package/lib/junit-adapter/ruby.js +11 -8
- package/lib/output.d.ts +11 -0
- package/lib/output.js +44 -52
- package/lib/package.json +3 -0
- package/lib/pipe/bitbucket.d.ts +23 -0
- package/lib/pipe/bitbucket.js +210 -229
- package/lib/pipe/csv.d.ts +47 -0
- package/lib/pipe/csv.js +113 -126
- package/lib/pipe/debug.d.ts +29 -0
- package/lib/pipe/debug.js +104 -99
- package/lib/pipe/github.d.ts +30 -0
- package/lib/pipe/github.js +186 -213
- package/lib/pipe/gitlab.d.ts +23 -0
- package/lib/pipe/gitlab.js +166 -207
- package/lib/pipe/html.d.ts +34 -0
- package/lib/pipe/html.js +260 -319
- package/lib/pipe/index.d.ts +1 -0
- package/lib/pipe/index.js +84 -66
- package/lib/pipe/testomatio.d.ts +70 -0
- package/lib/pipe/testomatio.js +413 -462
- package/lib/reporter-functions.d.ts +34 -0
- package/lib/reporter-functions.js +28 -26
- package/lib/reporter.d.ts +232 -0
- package/lib/reporter.js +34 -29
- package/lib/services/artifacts.d.ts +33 -0
- package/lib/services/artifacts.js +55 -51
- package/lib/services/index.d.ts +9 -0
- package/lib/services/index.js +14 -12
- package/lib/services/key-values.d.ts +27 -0
- package/lib/services/key-values.js +56 -53
- package/lib/services/logger.d.ts +64 -0
- package/lib/services/logger.js +227 -245
- package/lib/template/testomatio.hbs +651 -1366
- package/lib/uploader.d.ts +60 -0
- package/lib/uploader.js +291 -360
- package/lib/utils/pipe_utils.d.ts +41 -0
- package/lib/utils/pipe_utils.js +89 -85
- package/lib/utils/utils.d.ts +45 -0
- package/lib/utils/utils.js +347 -307
- package/lib/xmlReader.d.ts +92 -0
- package/lib/xmlReader.js +490 -529
- package/package.json +57 -15
- package/src/adapter/codecept.js +375 -0
- package/src/adapter/cucumber/current.js +228 -0
- package/src/adapter/cucumber/legacy.js +158 -0
- package/src/adapter/cucumber.js +4 -0
- package/src/adapter/cypress-plugin/index.js +112 -0
- package/src/adapter/jasmine.js +60 -0
- package/src/adapter/jest.js +107 -0
- package/src/adapter/mocha.cjs +2 -0
- package/src/adapter/mocha.js +157 -0
- package/src/adapter/playwright.js +250 -0
- package/src/adapter/vitest.js +183 -0
- package/src/adapter/webdriver.js +142 -0
- package/src/bin/cli.js +280 -0
- package/src/bin/reportXml.js +74 -0
- package/src/bin/startTest.js +123 -0
- package/src/bin/uploadArtifacts.js +90 -0
- package/src/client.js +504 -0
- package/src/config.js +30 -0
- package/src/constants.js +53 -0
- package/src/data-storage.js +204 -0
- package/src/junit-adapter/adapter.js +23 -0
- package/src/junit-adapter/csharp.js +16 -0
- package/src/junit-adapter/index.js +28 -0
- package/src/junit-adapter/java.js +58 -0
- package/src/junit-adapter/javascript.js +31 -0
- package/src/junit-adapter/python.js +42 -0
- package/src/junit-adapter/ruby.js +10 -0
- package/src/output.js +57 -0
- package/src/pipe/bitbucket.js +254 -0
- package/src/pipe/csv.js +140 -0
- package/src/pipe/debug.js +104 -0
- package/src/pipe/github.js +233 -0
- package/src/pipe/gitlab.js +229 -0
- package/src/pipe/html.js +374 -0
- package/src/pipe/index.js +71 -0
- package/src/pipe/testomatio.js +503 -0
- package/src/reporter-functions.js +55 -0
- package/src/reporter.cjs_decprecated +21 -0
- package/src/reporter.js +33 -0
- package/src/services/artifacts.js +59 -0
- package/src/services/index.js +13 -0
- package/src/services/key-values.js +59 -0
- package/src/services/logger.js +316 -0
- package/src/template/emptyData.svg +23 -0
- package/src/template/testomatio.hbs +706 -0
- package/src/uploader.js +371 -0
- package/src/utils/pipe_utils.js +119 -0
- package/src/utils/utils.js +383 -0
- package/src/xmlReader.js +562 -0
package/lib/adapter/vitest.js
CHANGED
|
@@ -1,122 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
+
exports.VitestReporter = void 0;
|
|
7
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
8
|
+
const client_js_1 = require("../client.js");
|
|
9
|
+
const constants_js_1 = require("../constants.js");
|
|
10
|
+
const utils_js_1 = require("../utils/utils.js");
|
|
11
|
+
const debug_1 = __importDefault(require("debug"));
|
|
12
|
+
const debug = (0, debug_1.default)('@testomatio/reporter:adapter-jest');
|
|
7
13
|
/**
|
|
8
|
-
* @typedef {import('../../types').VitestTest} VitestTest
|
|
9
|
-
* @typedef {import('../../types').VitestTestFile} VitestTestFile
|
|
10
|
-
* @typedef {import('../../types').VitestSuite} VitestSuite
|
|
11
|
-
* @typedef {import('../../types').VitestTestLogs} VitestTestLogs
|
|
12
|
-
* @typedef {import('../../vitest.types').ErrorWithDiff} ErrorWithDiff
|
|
13
|
-
* @typedef {typeof import('../constants').STATUS} STATUS
|
|
14
|
-
* @typedef {import('../../types').TestData} TestData
|
|
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
|
+
* @typedef {typeof import('../constants.js').STATUS} STATUS
|
|
20
|
+
* @typedef {import('../../types/types.js').TestData} TestData
|
|
15
21
|
*/
|
|
16
|
-
|
|
17
22
|
class VitestReporter {
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
constructor(config = {}) {
|
|
24
|
+
this.client = new client_js_1.Client({ apiKey: config?.apiKey });
|
|
25
|
+
/**
|
|
26
|
+
* @type {(TestData & {status: string})[]} tests
|
|
27
|
+
*/
|
|
28
|
+
this.tests = [];
|
|
29
|
+
}
|
|
30
|
+
// on run start
|
|
31
|
+
onInit() {
|
|
32
|
+
this.client.createRun();
|
|
33
|
+
}
|
|
20
34
|
/**
|
|
21
|
-
* @
|
|
35
|
+
* @param {VitestTestFile[] | undefined} files // array with results;
|
|
36
|
+
* @param {unknown[] | undefined} errors // errors does not contain errors from tests; probably its testrunner errors
|
|
22
37
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.#processTasksOfSuite(suite);
|
|
47
|
-
} else {
|
|
48
|
-
throw new Error('Unprocessed case. Unknown task type');
|
|
38
|
+
async onFinished(files, errors) {
|
|
39
|
+
if (!files || !files.length)
|
|
40
|
+
console.info('No tests executed');
|
|
41
|
+
files.forEach(file => {
|
|
42
|
+
// task could be test or suite
|
|
43
|
+
file.tasks.forEach(taskOrSuite => {
|
|
44
|
+
if (taskOrSuite.type === 'test') {
|
|
45
|
+
const test = taskOrSuite;
|
|
46
|
+
this.tests.push(this.#getDataFromTest(test));
|
|
47
|
+
}
|
|
48
|
+
else if (taskOrSuite.type === 'suite') {
|
|
49
|
+
const suite = taskOrSuite;
|
|
50
|
+
this.#processTasksOfSuite(suite);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
throw new Error('Unprocessed case. Unknown task type');
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
debug(this.tests.length, 'tests collected');
|
|
58
|
+
// send tests to Testomat.io
|
|
59
|
+
for (const test of this.tests) {
|
|
60
|
+
await this.client.addTestRun(test.status, test);
|
|
49
61
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
console.log('finished');
|
|
63
|
+
if (errors.length)
|
|
64
|
+
console.error('Vitest adapter errors:', errors);
|
|
65
|
+
await this.client.updateRunStatus(getRunStatusFromResults(files));
|
|
66
|
+
}
|
|
67
|
+
/* non-used listeners
|
|
68
|
+
onUserConsoleLog(log) {}
|
|
69
|
+
onPathsCollected(paths) {} // paths array to files with tests
|
|
70
|
+
onCollected(files) {} // files array with tests (but without results)
|
|
71
|
+
onTaskUpdate(packs) {} // some updates come here on afterAll block execution
|
|
72
|
+
onTestRemoved(trigger) {}
|
|
73
|
+
onWatcherStart(files, errors) {}
|
|
74
|
+
onWatcherRerun(files, trigger) {}
|
|
75
|
+
onServerRestart(reason) {}
|
|
76
|
+
onProcessTimeout() {}
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* Recursively gets all tasks from suite and pushes them to "tests" array
|
|
80
|
+
*
|
|
81
|
+
* @param {VitestSuite} suite
|
|
82
|
+
*/
|
|
83
|
+
#processTasksOfSuite(suite) {
|
|
84
|
+
suite.tasks.forEach(taskOrSuite => {
|
|
85
|
+
if (taskOrSuite.type === 'test') {
|
|
86
|
+
const test = taskOrSuite;
|
|
87
|
+
this.tests.push(this.#getDataFromTest(test));
|
|
88
|
+
}
|
|
89
|
+
else if (taskOrSuite.type === 'suite') {
|
|
90
|
+
const theSuite = taskOrSuite;
|
|
91
|
+
this.#processTasksOfSuite(theSuite);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
throw new Error('Unprocessed case. Unknown task type');
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Processes task and returns test data ready to be sent to Testomat.io
|
|
100
|
+
*
|
|
101
|
+
* @param {VitestTest} test
|
|
102
|
+
*
|
|
103
|
+
* @returns {TestData & {status: string}}
|
|
104
|
+
*/
|
|
105
|
+
#getDataFromTest(test) {
|
|
106
|
+
return {
|
|
107
|
+
error: test.result?.errors ? test.result.errors[0] : undefined,
|
|
108
|
+
file: test.file.name,
|
|
109
|
+
logs: test.logs ? transformLogsToString(test.logs) : '',
|
|
110
|
+
meta: test.meta,
|
|
111
|
+
status: getTestStatus(test),
|
|
112
|
+
suite_title: test.suite.name || test.file?.name,
|
|
113
|
+
test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(test.name),
|
|
114
|
+
time: test.result?.duration || 0,
|
|
115
|
+
title: test.name,
|
|
116
|
+
// testomatio functions (artifacts, logs, steps, meta) are not supported
|
|
117
|
+
};
|
|
58
118
|
}
|
|
59
|
-
|
|
60
|
-
console.log('finished');
|
|
61
|
-
if (errors.length) console.error('Vitest adapter errors:', errors);
|
|
62
|
-
|
|
63
|
-
await this.client.updateRunStatus(getRunStatusFromResults(files));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/* non-used listeners
|
|
67
|
-
onUserConsoleLog(log) {}
|
|
68
|
-
onPathsCollected(paths) {} // paths array to files with tests
|
|
69
|
-
onCollected(files) {} // files array with tests (but without results)
|
|
70
|
-
onTaskUpdate(packs) {} // some updates come here on afterAll block execution
|
|
71
|
-
onTestRemoved(trigger) {}
|
|
72
|
-
onWatcherStart(files, errors) {}
|
|
73
|
-
onWatcherRerun(files, trigger) {}
|
|
74
|
-
onServerRestart(reason) {}
|
|
75
|
-
onProcessTimeout() {}
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Recursively gets all tasks from suite and pushes them to "tests" array
|
|
80
|
-
*
|
|
81
|
-
* @param {VitestSuite} suite
|
|
82
|
-
*/
|
|
83
|
-
#processTasksOfSuite(suite) {
|
|
84
|
-
suite.tasks.forEach(taskOrSuite => {
|
|
85
|
-
if (taskOrSuite.type === 'test') {
|
|
86
|
-
const test = taskOrSuite;
|
|
87
|
-
this.tests.push(this.#getDataFromTest(test));
|
|
88
|
-
} else if (taskOrSuite.type === 'suite') {
|
|
89
|
-
const theSuite = taskOrSuite;
|
|
90
|
-
this.#processTasksOfSuite(theSuite);
|
|
91
|
-
} else {
|
|
92
|
-
throw new Error('Unprocessed case. Unknown task type');
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Processes task and returns test data ready to be sent to Testomat.io
|
|
99
|
-
*
|
|
100
|
-
* @param {VitestTest} test
|
|
101
|
-
*
|
|
102
|
-
* @returns {TestData & {status: string}}
|
|
103
|
-
*/
|
|
104
|
-
#getDataFromTest(test) {
|
|
105
|
-
return {
|
|
106
|
-
error: test.result?.errors ? test.result.errors[0] : undefined,
|
|
107
|
-
file: test.file.name,
|
|
108
|
-
logs: test.logs ? transformLogsToString(test.logs) : '',
|
|
109
|
-
meta: test.meta,
|
|
110
|
-
status: getTestStatus(test),
|
|
111
|
-
suite_title: test.suite.name || test.file?.name,
|
|
112
|
-
test_id: getTestomatIdFromTestTitle(test.name),
|
|
113
|
-
time: test.result?.duration || 0,
|
|
114
|
-
title: test.name,
|
|
115
|
-
// testomatio functions (artifacts, logs, steps, meta) are not supported
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
+
exports.VitestReporter = VitestReporter;
|
|
120
121
|
/**
|
|
121
122
|
* Returns run status based on test results
|
|
122
123
|
*
|
|
@@ -124,32 +125,28 @@ class VitestReporter {
|
|
|
124
125
|
* @returns {'passed' | 'failed' | 'finished'}
|
|
125
126
|
*/
|
|
126
127
|
function getRunStatusFromResults(files) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
128
|
+
/**
|
|
129
|
+
* @type {'passed' | 'failed' | 'finished'}
|
|
130
|
+
*/
|
|
131
|
+
let status = 'finished'; // default status (if no failed or passed tests)
|
|
132
|
+
files.forEach(file => {
|
|
133
|
+
// search for failed tests
|
|
134
|
+
file.tasks.forEach(taskOrSuite => {
|
|
135
|
+
if (taskOrSuite.result?.state === 'fail') {
|
|
136
|
+
status = 'failed'; // set status to failed if any test failed
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// if there are no failed tests > search for passed tests
|
|
140
|
+
if (status !== 'failed') {
|
|
141
|
+
file.tasks.forEach(taskOrSuite => {
|
|
142
|
+
if (taskOrSuite.result?.state === 'pass') {
|
|
143
|
+
status = 'passed'; // set status to passed if any test passed (and there are no failed tests)
|
|
144
|
+
}
|
|
145
|
+
});
|
|
145
146
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
return status;
|
|
147
|
+
});
|
|
148
|
+
return status;
|
|
151
149
|
}
|
|
152
|
-
|
|
153
150
|
/**
|
|
154
151
|
* Returns test status in Testomat.io format
|
|
155
152
|
*
|
|
@@ -157,26 +154,30 @@ function getRunStatusFromResults(files) {
|
|
|
157
154
|
* @returns 'passed' | 'failed' | 'skipped'
|
|
158
155
|
*/
|
|
159
156
|
function getTestStatus(test) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
if (test.result?.state === 'fail')
|
|
158
|
+
return constants_js_1.STATUS.FAILED;
|
|
159
|
+
if (test.result?.state === 'pass')
|
|
160
|
+
return constants_js_1.STATUS.PASSED;
|
|
161
|
+
if (!test.result && test.mode === 'skip')
|
|
162
|
+
return constants_js_1.STATUS.SKIPPED;
|
|
163
|
+
console.error(picocolors_1.default.red('Unprocessed case for defining test status. Contact dev team. Test:'), test);
|
|
164
164
|
}
|
|
165
|
-
|
|
166
165
|
/**
|
|
167
166
|
* @param {VitestTestLogs[]} logs
|
|
168
167
|
* @returns string
|
|
169
168
|
*/
|
|
170
169
|
function transformLogsToString(logs) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
170
|
+
if (!logs)
|
|
171
|
+
return '';
|
|
172
|
+
let logsStr = '';
|
|
173
|
+
logs.forEach(log => {
|
|
174
|
+
if (log.type === 'stdout')
|
|
175
|
+
logsStr += `${log.content}\n`;
|
|
176
|
+
if (log.type === 'stderr')
|
|
177
|
+
logsStr += `${picocolors_1.default.red(log.content)}\n`;
|
|
178
|
+
});
|
|
179
|
+
return logsStr;
|
|
178
180
|
}
|
|
181
|
+
module.exports = VitestReporter;
|
|
179
182
|
|
|
180
183
|
module.exports.VitestReporter = VitestReporter;
|
|
181
|
-
module.exports.default = VitestReporter;
|
|
182
|
-
module.exports = VitestReporter;
|
|
@@ -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
|
@@ -1,130 +1,145 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class WebdriverReporter extends WDIOReporter {
|
|
9
|
-
constructor(options) {
|
|
10
|
-
super(options);
|
|
11
|
-
|
|
12
|
-
this.client = new TestomatClient({ apiKey: options?.apiKey });
|
|
13
|
-
options = Object.assign(options, { stdout: true });
|
|
14
|
-
|
|
15
|
-
this._addTestPromises = [];
|
|
16
|
-
|
|
17
|
-
this._isSynchronising = false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
onRunnerStart() {
|
|
21
|
-
// clear dir with artifacts/logs
|
|
22
|
-
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
onTestStart(test) {
|
|
26
|
-
services.setContext(test.fullTitle);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get isSynchronised() {
|
|
30
|
-
return this._isSynchronising === false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async onRunnerEnd() {
|
|
34
|
-
this._isSynchronising = true;
|
|
35
|
-
|
|
36
|
-
await Promise.all(this._addTestPromises);
|
|
37
|
-
|
|
38
|
-
this._isSynchronising = false;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
onTestEnd(test) {
|
|
42
|
-
test.suite = test.parent;
|
|
43
|
-
const logs = getTestLogs(test.fullTitle);
|
|
44
|
-
// TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
|
|
45
|
-
// const artifacts = services.artifacts.get(test.fullTitle);
|
|
46
|
-
// const keyValues = services.keyValues.get(test.fullTitle);
|
|
47
|
-
test.logs = logs;
|
|
48
|
-
// test.artifacts = artifacts;
|
|
49
|
-
// test.meta = keyValues;
|
|
50
|
-
this._addTestPromises.push(this.addTest(test));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// wdio-cucumber does not trigger onTestEnd hook, thus, using this one
|
|
54
|
-
onSuiteEnd(scerario) {
|
|
55
|
-
if (scerario.type === 'scenario') {
|
|
56
|
-
this._addTestPromises.push(this.addBddScenario(scerario));
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
57
7
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
// eslint-disable-next-line
|
|
30
|
+
const reporter_1 = __importStar(require("@wdio/reporter"));
|
|
31
|
+
const client_js_1 = __importDefault(require("../client.js"));
|
|
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");
|
|
35
|
+
class WebdriverReporter extends reporter_1.default {
|
|
36
|
+
constructor(options) {
|
|
37
|
+
super(options);
|
|
38
|
+
this.client = new client_js_1.default({ apiKey: options?.apiKey });
|
|
39
|
+
options = Object.assign(options, { stdout: true });
|
|
40
|
+
this._addTestPromises = [];
|
|
41
|
+
this._isSynchronising = false;
|
|
42
|
+
// NOTE: new functionality; may break everything
|
|
43
|
+
this.client.createRun();
|
|
44
|
+
}
|
|
45
|
+
get isSynchronised() {
|
|
46
|
+
return this._isSynchronising === false;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param {RunnerStats} runData
|
|
51
|
+
*/
|
|
52
|
+
async onRunnerEnd(runData) {
|
|
53
|
+
this._isSynchronising = true;
|
|
54
|
+
await Promise.all(this._addTestPromises);
|
|
55
|
+
this._isSynchronising = false;
|
|
56
|
+
// NOTE: new functionality; may break everything
|
|
57
|
+
// also this may require additional status mapping
|
|
58
|
+
await this.client.updateRunStatus(runData.failures ? 'failed' : 'passed');
|
|
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
|
+
}
|
|
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;
|
|
77
|
+
this._addTestPromises.push(this.addTest(test));
|
|
78
|
+
}
|
|
79
|
+
// wdio-cucumber does not trigger onTestEnd hook, thus, using this one
|
|
80
|
+
onSuiteEnd(scerario) {
|
|
81
|
+
if (scerario.type === 'scenario') {
|
|
82
|
+
this._addTestPromises.push(this.addBddScenario(scerario));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async addTest(test) {
|
|
86
|
+
if (!this.client)
|
|
87
|
+
return;
|
|
88
|
+
const { title, _duration: duration, state, error, output } = test;
|
|
89
|
+
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(title);
|
|
90
|
+
const screenshotEndpoint = '/session/:sessionId/screenshot';
|
|
91
|
+
const screenshotsBuffers = output
|
|
92
|
+
.filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
|
|
93
|
+
.map(el => Buffer.from(el.result.value, 'base64'));
|
|
94
|
+
await this.client.addTestRun(state, {
|
|
95
|
+
manuallyAttachedArtifacts: test.artifacts,
|
|
96
|
+
error,
|
|
97
|
+
logs: test.logs,
|
|
98
|
+
meta: test.meta,
|
|
99
|
+
title,
|
|
100
|
+
test_id: testId,
|
|
101
|
+
time: duration,
|
|
102
|
+
filesBuffers: screenshotsBuffers,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @param {import('../../types/types.js').WebdriverIOScenario} scenario
|
|
107
|
+
*/
|
|
108
|
+
addBddScenario(scenario) {
|
|
109
|
+
if (!this.client)
|
|
110
|
+
return;
|
|
111
|
+
const { title, _duration: duration } = scenario;
|
|
112
|
+
const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(title || scenario.tags.map(tag => tag.name).join(' '));
|
|
113
|
+
let scenarioState = scenario.tests.every(test => test.state === 'passed') ? 'passed' : 'failed';
|
|
114
|
+
if (scenario.tests.every(test => test.state === 'skipped')) {
|
|
115
|
+
scenarioState = 'skipped';
|
|
116
|
+
}
|
|
117
|
+
const errors = scenario.tests
|
|
118
|
+
.filter(test => test.state === 'failed')
|
|
119
|
+
.map(test => test.error?.stack)
|
|
120
|
+
.filter(Boolean);
|
|
121
|
+
const error = errors.join('\n');
|
|
122
|
+
const tags = scenario.tags.map(tag => tag.name);
|
|
123
|
+
return this.client.addTestRun(scenarioState, {
|
|
124
|
+
error: error ? Error(error) : null,
|
|
125
|
+
title,
|
|
126
|
+
test_id: testId,
|
|
127
|
+
time: duration,
|
|
128
|
+
tags,
|
|
129
|
+
file: scenario.file,
|
|
130
|
+
// filesBuffers: screenshotsBuffers,
|
|
131
|
+
});
|
|
97
132
|
}
|
|
98
|
-
const errors = scenario.tests
|
|
99
|
-
.filter(test => test.state === 'failed')
|
|
100
|
-
.map(test => test.error?.stack)
|
|
101
|
-
.filter(Boolean);
|
|
102
|
-
const error = errors.join('\n');
|
|
103
|
-
|
|
104
|
-
const tags = scenario.tags.map(tag => tag.name);
|
|
105
|
-
|
|
106
|
-
return this.client.addTestRun(scenarioState, {
|
|
107
|
-
error: error ? Error(error) : null,
|
|
108
|
-
title,
|
|
109
|
-
test_id: testId,
|
|
110
|
-
time: duration,
|
|
111
|
-
tags,
|
|
112
|
-
file: scenario.file,
|
|
113
|
-
// filesBuffers: screenshotsBuffers,
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
133
|
}
|
|
117
|
-
|
|
118
134
|
/**
|
|
119
135
|
*
|
|
120
136
|
* @param {*} fullTestTitle
|
|
121
137
|
* @returns string
|
|
122
138
|
*/
|
|
123
139
|
function getTestLogs(fullTestTitle) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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;
|
|
128
144
|
}
|
|
129
|
-
|
|
130
145
|
module.exports = WebdriverReporter;
|
package/lib/bin/cli.d.ts
ADDED