@testomatio/reporter 0.8.0-beta.30 → 0.8.0-beta.32
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/README.md +16 -9
- package/lib/ArtifactStorage.js +131 -0
- package/lib/adapter/codecept.js +24 -18
- package/lib/adapter/cucumber/current.js +16 -12
- package/lib/adapter/cucumber/legacy.js +14 -10
- package/lib/adapter/cypress-plugin/index.js +7 -7
- package/lib/adapter/jasmine.js +5 -4
- package/lib/adapter/jest.js +7 -11
- package/lib/adapter/mocha.js +53 -18
- package/lib/adapter/playwright.js +7 -4
- package/lib/adapter/webdriver.js +2 -1
- package/lib/bin/reportXml.js +0 -1
- package/lib/bin/startTest.js +2 -2
- package/lib/client.js +61 -42
- package/lib/constants.js +9 -3
- package/lib/fileUploader.js +8 -4
- package/lib/junit-adapter/csharp.js +0 -1
- package/lib/junit-adapter/index.js +3 -2
- package/lib/pipe/csv.js +20 -6
- package/lib/pipe/github.js +19 -12
- package/lib/pipe/gitlab.js +24 -24
- package/lib/pipe/index.js +5 -3
- package/lib/pipe/testomatio.js +67 -42
- package/lib/reporter.js +2 -0
- package/lib/util.js +31 -13
- package/lib/xmlReader.js +19 -15
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ You can verify installed packages via `npm list` or `npm list -g`.
|
|
|
37
37
|
|
|
38
38
|
### CodeceptJS
|
|
39
39
|
|
|
40
|
-
Make sure you load all your tests using [check-
|
|
40
|
+
Make sure you load all your tests using [check-tests](https://github.com/testomatio/check-tests#cli).
|
|
41
41
|
|
|
42
42
|
Add plugin to [codecept conf](https://github.com/testomatio/reporter/blob/master/example/codecept/codecept.conf.js#L23):
|
|
43
43
|
|
|
@@ -94,7 +94,7 @@ TESTOMATIO={API_KEY} npx playwright test
|
|
|
94
94
|
|
|
95
95
|
### Mocha
|
|
96
96
|
|
|
97
|
-
Load the test using using `check-
|
|
97
|
+
Load the test using using `check-tests` if not done already. Get the test id from testomat account and add it to your mocha test like in this [example](https://github.com/testomatio/reporter/blob/master/example/mocha/test/index.test.js#L4).
|
|
98
98
|
|
|
99
99
|
Run the following command from you project folder:
|
|
100
100
|
|
|
@@ -104,7 +104,7 @@ mocha --reporter ./node_modules/testomat-reporter/lib/adapter/mocha.js --reporte
|
|
|
104
104
|
|
|
105
105
|
### Jest
|
|
106
106
|
|
|
107
|
-
Load the test using using `check-
|
|
107
|
+
Load the test using using `check-tests`. Add the test id to your tests like in this [example](https://github.com/testomatio/reporter/blob/master/example/jest/index.test.js#L1).
|
|
108
108
|
|
|
109
109
|
Add the following line to [jest.config.js](https://github.com/testomatio/reporter/blob/master/example/jest/jest.config.js#L100):
|
|
110
110
|
|
|
@@ -126,7 +126,7 @@ TESTOMATIO={API_KEY} ./node_modules/.bin/cucumber-js --format ./node_modules/@te
|
|
|
126
126
|
|
|
127
127
|
### TestCafe
|
|
128
128
|
|
|
129
|
-
Load the test using using `check-
|
|
129
|
+
Load the test using using `check-tests`.
|
|
130
130
|
|
|
131
131
|
Run the following command from you project folder:
|
|
132
132
|
|
|
@@ -138,14 +138,16 @@ TESTOMATIO={API_KEY} npx testcafe chrome -r testomatio
|
|
|
138
138
|
|
|
139
139
|
Run collection and specify `testomatio` as reporter:
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
```bash
|
|
142
|
+
TESTOMATIO={API_KEY} npx newman run {collection_name.json} -r testomatio
|
|
143
|
+
```
|
|
142
144
|
|
|
143
|
-
> _`check-
|
|
145
|
+
> _`check-tests` not supported for newman for now, tests will be created on testomatio by default_
|
|
144
146
|
|
|
145
147
|
|
|
146
148
|
### Cypress
|
|
147
149
|
|
|
148
|
-
Load the test using using `check-
|
|
150
|
+
Load the test using using `check-tests`.
|
|
149
151
|
|
|
150
152
|
Register our `cypress-plugin` in `cypress/plugins/index.js`:
|
|
151
153
|
|
|
@@ -173,7 +175,7 @@ TESTOMATIO={API_KEY} npx cypress run
|
|
|
173
175
|
|
|
174
176
|
### Protractor
|
|
175
177
|
|
|
176
|
-
Load the test using using `check-
|
|
178
|
+
Load the test using using `check-tests`.
|
|
177
179
|
|
|
178
180
|
Add the following lines to [conf.js](https://github.com/angular/protractor/blob/5.4.1/example/conf.js):
|
|
179
181
|
|
|
@@ -195,7 +197,7 @@ TESTOMATIO={API_KEY} npx start-test-run -c 'npx protractor conf.js'
|
|
|
195
197
|
|
|
196
198
|
### WebdriverIO
|
|
197
199
|
|
|
198
|
-
Load the test using using `check-
|
|
200
|
+
Load the test using using `check-tests`.
|
|
199
201
|
|
|
200
202
|
Add the following lines to [wdio.conf.js](https://webdriver.io/docs/configurationfile/):
|
|
201
203
|
|
|
@@ -583,3 +585,8 @@ If you want to finish a run started by `--launch` use `--finish` option. `TESTOM
|
|
|
583
585
|
```bash
|
|
584
586
|
TESTOMATIO={API_KEY} TESTOMATIO_RUN={RUN_ID} npx start-test-run --finish
|
|
585
587
|
```
|
|
588
|
+
|
|
589
|
+
### Debug logs
|
|
590
|
+
Pass `DEBUG` variable with module name e.g. `DEBUG=@testomatio/reporter:pipe:github`.
|
|
591
|
+
(Module name could be taken directly from the required module code).
|
|
592
|
+
To log all debug info pass `DEBUG=*`.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const debug = require('debug')('@testomatio/reporter:storage');
|
|
2
|
+
const { join, resolve } = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const uuid = require('uuid');
|
|
6
|
+
const { TESTOMAT_ARTIFACT_SUFFIX } = require('./constants');
|
|
7
|
+
const { specificTestInfo } = require('./util');
|
|
8
|
+
|
|
9
|
+
class ArtifactStorage {
|
|
10
|
+
|
|
11
|
+
constructor(params) {
|
|
12
|
+
this._tmpPrefix = "tsmt_reporter";
|
|
13
|
+
this.isFile = false;
|
|
14
|
+
this.isMemory = true;
|
|
15
|
+
this.storage = params?.toFile;
|
|
16
|
+
|
|
17
|
+
if (this.storage) {
|
|
18
|
+
this.isFile = true;
|
|
19
|
+
this.isMemory = false;
|
|
20
|
+
this.tmpDirFullpath = this.createTestomatTmpDir(this._tmpPrefix);
|
|
21
|
+
debug('SAVE to tmp folder mode enabled!');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static async storeToFile(tmpDirName, artifact, testSuffix = "test") {
|
|
26
|
+
const suffix = TESTOMAT_ARTIFACT_SUFFIX + uuid.v4() + testSuffix;
|
|
27
|
+
const dirpath = join(os.tmpdir(), tmpDirName);
|
|
28
|
+
const filepath = resolve(dirpath, `${suffix}.json`);
|
|
29
|
+
|
|
30
|
+
return fs.promises.appendFile(filepath, JSON.stringify(artifact));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static async artifact(artifact, context) {
|
|
34
|
+
// TODO: mode for different pre-hooks. As variant - "all-tests" || "only_fail"
|
|
35
|
+
// const mode = process.env.TESTOMAT_ARTIFACTS || "only_fail";
|
|
36
|
+
|
|
37
|
+
if (Array.isArray(global.testomatioArtifacts)) {
|
|
38
|
+
debug("Saving artifacts to global storage");
|
|
39
|
+
|
|
40
|
+
global.testomatioArtifacts.push(artifact);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (global?.testomatioArtifacts === undefined) {
|
|
44
|
+
const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
|
|
45
|
+
|
|
46
|
+
const testSuffix = specificTestInfo(context.test);
|
|
47
|
+
|
|
48
|
+
if (Array.isArray(tmpDirNames) && tmpDirNames.length) {
|
|
49
|
+
debug("Saving artifacts to memory tmp folder");
|
|
50
|
+
|
|
51
|
+
return ArtifactStorage.storeToFile(tmpDirNames[tmpDirNames.length - 1], artifact, testSuffix);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async artifactByTestName(test) {
|
|
57
|
+
const list = [];
|
|
58
|
+
|
|
59
|
+
if (this.isFile && this.tmpDirFullpath) {
|
|
60
|
+
const files = fs.readdirSync(this.tmpDirFullpath);
|
|
61
|
+
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
if (file.includes(test)) {
|
|
64
|
+
const buff = await fs.promises.readFile(`${this.tmpDirFullpath }/${ file}`);
|
|
65
|
+
|
|
66
|
+
list.push(JSON.parse(buff.toString()));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return list;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async tmpContents() {
|
|
75
|
+
const contents = [];
|
|
76
|
+
|
|
77
|
+
if (this.isFile && this.tmpDirFullpath) {
|
|
78
|
+
const files = fs.readdirSync(this.tmpDirFullpath);
|
|
79
|
+
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
const buff = await fs.promises.readFile(`${this.tmpDirFullpath }/${ file}`);
|
|
82
|
+
const content = buff.toString();
|
|
83
|
+
|
|
84
|
+
contents.push(content);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return contents;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
createTestomatTmpDir(clientPrefix) {
|
|
92
|
+
return fs.mkdtempSync(join(os.tmpdir(), clientPrefix));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
clearTmpDirByName(name) {
|
|
96
|
+
const tmpDirPath = join(os.tmpdir(), name);
|
|
97
|
+
|
|
98
|
+
if (fs.existsSync(tmpDirPath)) {
|
|
99
|
+
fs.rmSync(tmpDirPath, { recursive: true });
|
|
100
|
+
debug(` Testomat tmpDir = ${tmpDirPath} was deleted successfully!`);
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static tmpTestomatDirNames() {
|
|
107
|
+
const subname = this._tmpPrefix || "tsmt_reporter";
|
|
108
|
+
|
|
109
|
+
return fs.readdirSync(os.tmpdir(), { withFileTypes: true })
|
|
110
|
+
.filter((item) => item.isDirectory())
|
|
111
|
+
.map((item) => item.name)
|
|
112
|
+
.filter((name) => name.includes(subname));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
cleanup() {
|
|
116
|
+
if (this.isFile && this.tmpDirFullpath) {
|
|
117
|
+
const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
|
|
118
|
+
|
|
119
|
+
if (Array.isArray(tmpDirNames) && tmpDirNames.length) {
|
|
120
|
+
for (const name of tmpDirNames) {
|
|
121
|
+
this.clearTmpDirByName(name);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
debug("The tmp folder has not been created! Nothing to delete");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = ArtifactStorage;
|
package/lib/adapter/codecept.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const TestomatClient = require('../client');
|
|
3
|
+
const { STATUS, APP_PREFIX } = require('../constants');
|
|
4
|
+
const upload = require('../fileUploader');
|
|
5
|
+
const Output = require('../output');
|
|
6
|
+
|
|
1
7
|
if (!global.codeceptjs) {
|
|
2
8
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
3
9
|
global.codeceptjs = require('codeceptjs');
|
|
4
10
|
}
|
|
5
11
|
|
|
6
12
|
const { event, recorder, codecept } = global.codeceptjs;
|
|
7
|
-
const chalk = require('chalk');
|
|
8
|
-
const TestomatClient = require('../client');
|
|
9
|
-
const { FAILED } = require('../constants');
|
|
10
|
-
const TRConstants = require('../constants');
|
|
11
|
-
const upload = require('../fileUploader');
|
|
12
|
-
const Output = require('../output');
|
|
13
13
|
|
|
14
14
|
let currentMetaStep = [];
|
|
15
15
|
let error;
|
|
@@ -68,15 +68,16 @@ function CodeceptReporter(config) {
|
|
|
68
68
|
|
|
69
69
|
event.dispatcher.on(event.all.result, async () => {
|
|
70
70
|
if (videos.length && upload.isArtifactsEnabled()) {
|
|
71
|
-
console.log(
|
|
71
|
+
console.log(APP_PREFIX, `🎞️ Uploading ${videos.length} videos...`);
|
|
72
72
|
|
|
73
73
|
const promises = [];
|
|
74
74
|
for (const video of videos) {
|
|
75
75
|
const { testId, title, path, type } = video;
|
|
76
76
|
const file = { path, type, title };
|
|
77
77
|
promises.push(
|
|
78
|
-
client.addTestRun(
|
|
78
|
+
client.addTestRun(undefined, {
|
|
79
79
|
...stripExampleFromTitle(title),
|
|
80
|
+
test_id: testId,
|
|
80
81
|
files: [file],
|
|
81
82
|
}),
|
|
82
83
|
);
|
|
@@ -84,7 +85,7 @@ function CodeceptReporter(config) {
|
|
|
84
85
|
await Promise.all(promises);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
const status = failedTests.length === 0 ?
|
|
88
|
+
const status = failedTests.length === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
88
89
|
client.updateRunStatus(status);
|
|
89
90
|
});
|
|
90
91
|
|
|
@@ -95,12 +96,13 @@ function CodeceptReporter(config) {
|
|
|
95
96
|
}
|
|
96
97
|
const testId = parseTest(tags);
|
|
97
98
|
const testObj = getTestAndMessage(title);
|
|
98
|
-
client.addTestRun(
|
|
99
|
+
client.addTestRun(STATUS.PASSED, {
|
|
99
100
|
...stripExampleFromTitle(title),
|
|
100
101
|
suite_title: test.parent && test.parent.title,
|
|
101
102
|
message: testObj.message,
|
|
102
103
|
time: getDuration(test),
|
|
103
104
|
steps: output.text(),
|
|
105
|
+
test_id: testId,
|
|
104
106
|
});
|
|
105
107
|
output.stop();
|
|
106
108
|
});
|
|
@@ -119,9 +121,10 @@ function CodeceptReporter(config) {
|
|
|
119
121
|
failedTests.push(id || title);
|
|
120
122
|
const testId = parseTest(tags);
|
|
121
123
|
|
|
122
|
-
client.addTestRun(
|
|
124
|
+
client.addTestRun(STATUS.FAILED, {
|
|
123
125
|
...stripExampleFromTitle(title),
|
|
124
126
|
suite_title: suite.title,
|
|
127
|
+
test_id: testId,
|
|
125
128
|
error,
|
|
126
129
|
time: 0,
|
|
127
130
|
});
|
|
@@ -130,7 +133,7 @@ function CodeceptReporter(config) {
|
|
|
130
133
|
});
|
|
131
134
|
|
|
132
135
|
event.dispatcher.on(event.test.after, test => {
|
|
133
|
-
if (test.state && test.state !== FAILED) return;
|
|
136
|
+
if (test.state && test.state !== STATUS.FAILED) return;
|
|
134
137
|
if (test.err) error = test.err;
|
|
135
138
|
const { id, tags, title, artifacts } = test;
|
|
136
139
|
failedTests.push(id || title);
|
|
@@ -149,8 +152,9 @@ function CodeceptReporter(config) {
|
|
|
149
152
|
if (aid.startsWith('trace')) files.push({ testId: id, title, path: artifacts[aid], type: 'application/zip' });
|
|
150
153
|
}
|
|
151
154
|
|
|
152
|
-
client.addTestRun(
|
|
155
|
+
client.addTestRun(STATUS.FAILED, {
|
|
153
156
|
...stripExampleFromTitle(title),
|
|
157
|
+
test_id: testId,
|
|
154
158
|
suite_title: test.parent && test.parent.title,
|
|
155
159
|
error,
|
|
156
160
|
message: testObj.message,
|
|
@@ -167,8 +171,9 @@ function CodeceptReporter(config) {
|
|
|
167
171
|
|
|
168
172
|
const testId = parseTest(tags);
|
|
169
173
|
const testObj = getTestAndMessage(title);
|
|
170
|
-
client.addTestRun(
|
|
174
|
+
client.addTestRun(STATUS.SKIPPED, {
|
|
171
175
|
...stripExampleFromTitle(title),
|
|
176
|
+
test_id: testId,
|
|
172
177
|
suite_title: test.parent && test.parent.title,
|
|
173
178
|
message: testObj.message,
|
|
174
179
|
time: getDuration(test),
|
|
@@ -207,12 +212,13 @@ function CodeceptReporter(config) {
|
|
|
207
212
|
currentMetaStep = metaSteps;
|
|
208
213
|
stepShift = 2 * shift;
|
|
209
214
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
const durationMs = (+new Date() - (+stepStart));
|
|
216
|
+
let duration = '';
|
|
217
|
+
if (durationMs) {
|
|
218
|
+
duration = repeat(1) + chalk.grey(`(${durationMs}ms)`);
|
|
213
219
|
}
|
|
214
220
|
|
|
215
|
-
if (step.status ===
|
|
221
|
+
if (step.status === STATUS.FAILED) {
|
|
216
222
|
output.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
|
|
217
223
|
} else {
|
|
218
224
|
output.push(repeat(stepShift) + step.toString() + duration);
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
const { Formatter, formatterHelpers } = require("@cucumber/cucumber");
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const {
|
|
5
|
+
const { STATUS } = require('../../constants');
|
|
6
|
+
const TestomatClient = require('../../client');
|
|
6
7
|
|
|
7
8
|
const { GherkinDocumentParser, PickleParser } = formatterHelpers
|
|
8
9
|
const {
|
|
@@ -19,7 +20,7 @@ class CucumberReporter extends Formatter {
|
|
|
19
20
|
this.cases = [];
|
|
20
21
|
|
|
21
22
|
this.client = new TestomatClient();
|
|
22
|
-
this.status =
|
|
23
|
+
this.status = STATUS.PASSED;
|
|
23
24
|
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -33,7 +34,8 @@ class CucumberReporter extends Formatter {
|
|
|
33
34
|
const testCaseAttempt = this.eventDataCollector.getTestCaseAttempt(testCaseFinished.testCaseStartedId);
|
|
34
35
|
|
|
35
36
|
let example;
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
let status = STATUS.PASSED;
|
|
37
39
|
let color = 'green';
|
|
38
40
|
let message;
|
|
39
41
|
|
|
@@ -41,22 +43,23 @@ class CucumberReporter extends Formatter {
|
|
|
41
43
|
|
|
42
44
|
if (testCaseAttempt.worstTestStepResult) {
|
|
43
45
|
if (testCaseAttempt.worstTestStepResult.status === 'SKIPPED') {
|
|
44
|
-
status =
|
|
46
|
+
status = STATUS.SKIPPED;
|
|
45
47
|
}
|
|
46
48
|
if (testCaseAttempt.worstTestStepResult.status === 'UNDEFINED') {
|
|
47
|
-
status =
|
|
49
|
+
status = STATUS.SKIPPED;
|
|
48
50
|
message = 'Undefined steps. Implement missing steps and rerun this scenario';
|
|
49
51
|
}
|
|
50
52
|
if (testCaseAttempt.worstTestStepResult.status === 'FAILED') {
|
|
51
53
|
message = testCaseAttempt?.worstTestStepResult?.message;
|
|
52
|
-
status =
|
|
54
|
+
status = STATUS.FAILED;
|
|
53
55
|
}
|
|
54
56
|
color = getStatusColor(testCaseAttempt.worstTestStepResult.status);
|
|
55
|
-
if (status !==
|
|
57
|
+
if (status !== STATUS.PASSED) this.failures.push(testCaseAttempt);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
if (testCaseAttempt.pickle.astNodeIds.length > 1) {
|
|
59
61
|
example = getExample(testCaseAttempt);
|
|
62
|
+
// @ts-ignore
|
|
60
63
|
testCaseAttempt.example = example;
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -70,8 +73,8 @@ class CucumberReporter extends Formatter {
|
|
|
70
73
|
if (message) cliMessage += chalk.gray(message.split('\n')[0]);
|
|
71
74
|
console.log(cliMessage);
|
|
72
75
|
|
|
73
|
-
if (status !==
|
|
74
|
-
this.status =
|
|
76
|
+
if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
|
|
77
|
+
this.status = STATUS.FAILED;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
const time = Object.values(testCaseAttempt.stepResults)
|
|
@@ -80,12 +83,13 @@ class CucumberReporter extends Formatter {
|
|
|
80
83
|
|
|
81
84
|
if (!this.client) return;
|
|
82
85
|
|
|
83
|
-
this.client.addTestRun(
|
|
86
|
+
this.client.addTestRun(status, {
|
|
84
87
|
// error: testCaseAttempt.worstTestStepResult.message,
|
|
85
88
|
message,
|
|
86
89
|
steps: getSteps(testCaseAttempt).map(s => s.toString()).join('\n').trim(),
|
|
87
90
|
example: { ...example},
|
|
88
91
|
title: scenario,
|
|
92
|
+
test_id: testId,
|
|
89
93
|
time,
|
|
90
94
|
});
|
|
91
95
|
}
|
|
@@ -121,9 +125,9 @@ class CucumberReporter extends Formatter {
|
|
|
121
125
|
|
|
122
126
|
if (!this.client) return;
|
|
123
127
|
|
|
124
|
-
this.client.updateRunStatus(testRunFinished.success ?
|
|
128
|
+
this.client.updateRunStatus(testRunFinished.success ? STATUS.PASSED : STATUS.FAILED)
|
|
125
129
|
}
|
|
126
|
-
}
|
|
130
|
+
}
|
|
127
131
|
|
|
128
132
|
function getSteps(tc) {
|
|
129
133
|
const stepIds = Object.keys(tc.stepResults);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
// eslint-disable-next-line import/no-unresolved
|
|
1
|
+
// eslint-disable-next-line global-require, import/no-extraneous-dependencies, import/no-unresolved
|
|
2
2
|
const { Formatter } = require('cucumber');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
|
-
const { TestomatClient, TRConstants } = require('../../reporter');
|
|
5
4
|
const { parseTest } = require('../../util');
|
|
5
|
+
const { STATUS } = require('../../constants');
|
|
6
|
+
const TestomatClient = require('../../client');
|
|
6
7
|
|
|
7
8
|
const createTestomatFormatter = apiKey => {
|
|
8
9
|
if (!apiKey || apiKey === '') {
|
|
@@ -92,18 +93,18 @@ const createTestomatFormatter = apiKey => {
|
|
|
92
93
|
if (!apiKey) return;
|
|
93
94
|
|
|
94
95
|
this.client = new TestomatClient({ apiKey });
|
|
95
|
-
this.status =
|
|
96
|
+
this.status = STATUS.PASSED.toString();
|
|
96
97
|
|
|
97
98
|
options.eventBroadcaster.on('gherkin-document', addDocument);
|
|
98
|
-
options.eventBroadcaster.on('test-run-started', () => this
|
|
99
|
+
options.eventBroadcaster.on('test-run-started', () => this?.client?.createRun());
|
|
99
100
|
options.eventBroadcaster.on('test-case-finished', this.onTestCaseFinished.bind(this));
|
|
100
|
-
options.eventBroadcaster.on('test-run-finished', () => this
|
|
101
|
+
options.eventBroadcaster.on('test-run-finished', () => this?.client?.updateRunStatus(this.status));
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
onTestCaseFinished(event) {
|
|
104
105
|
const scenario = getScenario(event.sourceLocation);
|
|
105
106
|
const testId = getTestId(scenario);
|
|
106
|
-
const status = event.result.status === 'undefined' ?
|
|
107
|
+
const status = event.result.status === 'undefined' ? STATUS.SKIPPED : event.result.status;
|
|
107
108
|
|
|
108
109
|
let example = getDataTableMap(scenario, event.sourceLocation);
|
|
109
110
|
if (example) example = JSON.parse(example);
|
|
@@ -120,14 +121,17 @@ const createTestomatFormatter = apiKey => {
|
|
|
120
121
|
message = 'Undefined steps. Implement missing steps and rerun this scenario';
|
|
121
122
|
}
|
|
122
123
|
console.log(cliMessage);
|
|
123
|
-
if (status !==
|
|
124
|
-
this.status =
|
|
124
|
+
if (status !== STATUS.PASSED && status !== STATUS.SKIPPED) {
|
|
125
|
+
this.status = STATUS.FAILED;
|
|
125
126
|
}
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
|
|
128
|
+
this.client?.addTestRun(status, {
|
|
129
|
+
error: event.result.exception instanceof Error ? event.result.exception : undefined,
|
|
128
130
|
message,
|
|
129
131
|
example,
|
|
132
|
+
test_id: testId,
|
|
130
133
|
title: getTitle(scenario),
|
|
134
|
+
suite_title: getTitle(getFeature(event.sourceLocation.uri)),
|
|
131
135
|
});
|
|
132
136
|
}
|
|
133
137
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { STATUS } = require('../../constants');
|
|
2
2
|
const { parseTest, parseSuite } = require('../../util');
|
|
3
3
|
const TestomatClient = require('../../client');
|
|
4
4
|
|
|
@@ -57,16 +57,16 @@ const testomatioReporter = on => {
|
|
|
57
57
|
|
|
58
58
|
let state;
|
|
59
59
|
switch (test.state) {
|
|
60
|
-
case 'passed': state =
|
|
61
|
-
case 'failed': state =
|
|
60
|
+
case 'passed': state = STATUS.PASSED; break;
|
|
61
|
+
case 'failed': state = STATUS.FAILED; break;
|
|
62
62
|
case 'skipped':
|
|
63
63
|
case 'pending':
|
|
64
64
|
default:
|
|
65
|
-
state =
|
|
65
|
+
state = STATUS.SKIPPED;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
addSpecTestsPromises.push(client.addTestRun(
|
|
69
|
-
title, time, example, error, files, suite_title: suiteTitle, suite_id: suiteId
|
|
68
|
+
addSpecTestsPromises.push(client.addTestRun(state, {
|
|
69
|
+
title, time, example, error, files, suite_title: suiteTitle, test_id: testId, suite_id: suiteId
|
|
70
70
|
}));
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -74,7 +74,7 @@ const testomatioReporter = on => {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
on('after:run', async results => {
|
|
77
|
-
const status = results.totalFailed ?
|
|
77
|
+
const status = results.totalFailed ? STATUS.FAILED : STATUS.PASSED;
|
|
78
78
|
await client.updateRunStatus(status);
|
|
79
79
|
});
|
|
80
80
|
};
|
package/lib/adapter/jasmine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const TestomatClient = require('../client');
|
|
2
2
|
const { parseTest, ansiRegExp } = require('../util');
|
|
3
|
-
const {
|
|
3
|
+
const { STATUS } = require('../constants');
|
|
4
4
|
|
|
5
5
|
class JasmineReporter {
|
|
6
6
|
constructor(options) {
|
|
@@ -32,13 +32,14 @@ class JasmineReporter {
|
|
|
32
32
|
errorMessage = `${errorMessage}Failure: ${result.failedExpectations[i].message}\n`;
|
|
33
33
|
errorMessage = `${errorMessage}\n ${result.failedExpectations[i].stack}`;
|
|
34
34
|
}
|
|
35
|
-
console.log(`${title} : ${PASSED}`);
|
|
35
|
+
console.log(`${title} : ${STATUS.PASSED}`);
|
|
36
36
|
console.log(errorMessage);
|
|
37
37
|
const testId = parseTest(title);
|
|
38
38
|
errorMessage = errorMessage.replace(ansiRegExp(), '');
|
|
39
|
-
this.client.addTestRun(
|
|
39
|
+
this.client.addTestRun(status, {
|
|
40
40
|
error: result.failedExpectations[0],
|
|
41
41
|
message: errorMessage,
|
|
42
|
+
test_id: testId,
|
|
42
43
|
title,
|
|
43
44
|
time: this.getDuration(result),
|
|
44
45
|
});
|
|
@@ -48,7 +49,7 @@ class JasmineReporter {
|
|
|
48
49
|
if (!this.client) return;
|
|
49
50
|
|
|
50
51
|
const { overallStatus } = suiteInfo;
|
|
51
|
-
const status = overallStatus === 'failed' ? FAILED : PASSED;
|
|
52
|
+
const status = overallStatus === 'failed' ? STATUS.FAILED : STATUS.PASSED;
|
|
52
53
|
|
|
53
54
|
this.client.updateRunStatus(status).then(() => done);
|
|
54
55
|
}
|
package/lib/adapter/jest.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const TestomatClient = require('../client');
|
|
2
|
-
const
|
|
2
|
+
const { STATUS } = require('../constants');
|
|
3
3
|
const { parseTest, ansiRegExp } = require('../util');
|
|
4
4
|
|
|
5
5
|
class JestReporter {
|
|
@@ -16,26 +16,22 @@ class JestReporter {
|
|
|
16
16
|
|
|
17
17
|
const { testResults } = testResult;
|
|
18
18
|
for (const result of testResults) {
|
|
19
|
-
let error
|
|
20
|
-
let steps
|
|
19
|
+
let error;
|
|
20
|
+
let steps;
|
|
21
21
|
const { status, title, duration, failureMessages } = result;
|
|
22
22
|
if (failureMessages[0]) {
|
|
23
23
|
let errorMessage = failureMessages[0].replace(ansiRegExp(), '');
|
|
24
24
|
errorMessage = errorMessage.split('\n')[0];
|
|
25
|
-
error =
|
|
26
|
-
message: errorMessage,
|
|
27
|
-
};
|
|
25
|
+
error = new Error(errorMessage);
|
|
28
26
|
steps = failureMessages[0];
|
|
29
27
|
}
|
|
30
28
|
const testId = parseTest(title);
|
|
31
29
|
const deducedStatus = status === 'pending' ? 'skipped' : status;
|
|
32
|
-
|
|
33
|
-
const suite_title = result.ancestorTitles && result.ancestorTitles[result.ancestorTitles.length - 1];
|
|
34
30
|
// In jest if test is not matched with test name pattern it is considered as skipped.
|
|
35
31
|
// So adding a check if it is skipped for real or because of test pattern
|
|
36
32
|
if (!this._globalConfig.testNamePattern || deducedStatus !== 'skipped') {
|
|
37
|
-
this.client.addTestRun(
|
|
38
|
-
|
|
33
|
+
this.client.addTestRun(deducedStatus, {
|
|
34
|
+
test_id: testId,
|
|
39
35
|
error,
|
|
40
36
|
steps,
|
|
41
37
|
title,
|
|
@@ -49,7 +45,7 @@ class JestReporter {
|
|
|
49
45
|
if (!this.client) return;
|
|
50
46
|
|
|
51
47
|
const { numFailedTests } = results;
|
|
52
|
-
const status = numFailedTests === 0 ?
|
|
48
|
+
const status = numFailedTests === 0 ? STATUS.PASSED : STATUS.FAILED;
|
|
53
49
|
this.client.updateRunStatus(status);
|
|
54
50
|
}
|
|
55
51
|
}
|