@testomatio/reporter 1.3.0-beta β 1.3.0
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 +61 -54
- package/lib/adapter/codecept.js +96 -35
- package/lib/adapter/cucumber/current.js +18 -11
- package/lib/adapter/cucumber/legacy.js +6 -5
- package/lib/adapter/cucumber.js +2 -2
- package/lib/adapter/cypress-plugin/index.js +52 -25
- package/lib/adapter/jasmine.js +1 -1
- package/lib/adapter/jest.js +49 -16
- package/lib/adapter/mocha.js +103 -51
- package/lib/adapter/playwright.js +95 -33
- package/lib/adapter/webdriver.js +1 -1
- package/lib/bin/reportXml.js +22 -16
- package/lib/bin/startTest.js +27 -6
- package/lib/client.js +180 -61
- package/lib/config.js +34 -0
- package/lib/constants.js +32 -7
- package/lib/data-storage.js +203 -0
- package/lib/fileUploader.js +135 -54
- package/lib/junit-adapter/adapter.js +0 -2
- package/lib/junit-adapter/csharp.js +3 -4
- package/lib/junit-adapter/index.js +3 -3
- package/lib/junit-adapter/java.js +35 -17
- package/lib/junit-adapter/javascript.js +1 -2
- package/lib/junit-adapter/python.js +12 -14
- package/lib/junit-adapter/ruby.js +1 -2
- package/lib/pipe/csv.js +5 -3
- package/lib/pipe/github.js +27 -39
- package/lib/pipe/gitlab.js +22 -26
- package/lib/pipe/html.js +354 -0
- package/lib/pipe/index.js +3 -1
- package/lib/pipe/testomatio.js +259 -53
- package/lib/reporter-functions.js +46 -0
- package/lib/reporter.js +11 -9
- package/lib/services/artifacts.js +57 -0
- package/lib/services/index.js +13 -0
- package/lib/services/key-values.js +58 -0
- package/lib/services/logger.js +311 -0
- package/lib/template/testomatio.hbs +1236 -0
- package/lib/utils/pipe_utils.js +129 -0
- package/lib/{util.js β utils/utils.js} +144 -14
- package/lib/xmlReader.js +211 -122
- package/package.json +17 -8
- package/lib/_ArtifactStorageOld.js +0 -142
- package/lib/artifactStorage.js +0 -25
- package/lib/dataStorage.js +0 -244
- package/lib/logger.js +0 -294
package/README.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# Testomatio Reporter
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
π Hey, do you need some test reporting?
|
|
5
4
|
|
|
6
5
|
Testomat.io Reporter is a library that integrates with popular **JavaScript and TypeScript** test frameworks to provide a common interface for test reporting. By default, Testomat.io Reporter works with our reporting cloud service [Testomat.io App](https://testomat.io), however it is not locked to it. Reporter can be used as a standalone tool.
|
|
@@ -9,18 +8,17 @@ Testomat.io Reporter is a library that integrates with popular **JavaScript and
|
|
|
9
8
|
|
|
10
9
|
Testomat.io Reporter (this npm package) supports:
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
- π Integarion with all popular [JavaScript/TypeScript frameworks](./docs/frameworks.md)
|
|
12
|
+
- ποΈ Screenshots, videos, traces [uploaded into S3 bucket](./docs/artifacts.md)
|
|
13
|
+
- π [Stack traces](./docs/stacktrace.md) and error messages
|
|
14
|
+
- π [GitHub](./docs/pipes/github.md) & [GitLab](./docs/pipes/gitlab.md) integration
|
|
15
|
+
- π
Realtime reports
|
|
16
|
+
- ποΈ Other test frameworks supported via [JUNit XML](./docs/junit.md)
|
|
17
|
+
- πΆββοΈ Steps _(work in progress)_
|
|
18
|
+
- π [Logger](./docs/logger.md) _(work in progress, supports Jest for now)_
|
|
19
|
+
- βοΈ Custom properties and metadata _(work in progress)_
|
|
20
|
+
- π― Free & open-source.
|
|
21
|
+
- π Public and private Run reports on cloud via [Testomat.io App](https://testomat.io) π
|
|
24
22
|
|
|
25
23
|

|
|
26
24
|
|
|
@@ -29,12 +27,12 @@ Testomat.io Reporter (this npm package) supports:
|
|
|
29
27
|
Testomat.io Reporter provides common API to store and organize test reports.
|
|
30
28
|
It can receive test result data from any [test framework](./docs/frameworks.md) and send it to different services via [pipes](./docs/pipes.md).
|
|
31
29
|
|
|
32
|
-
| π Input
|
|
33
|
-
|
|
34
|
-
| Playwright
|
|
35
|
-
| Cypress
|
|
36
|
-
| Jest
|
|
37
|
-
| ...
|
|
30
|
+
| π Input | π Output |
|
|
31
|
+
| ---------- | -------------------------------------------- |
|
|
32
|
+
| Playwright | Report to GitHub |
|
|
33
|
+
| Cypress | Report to GitLab |
|
|
34
|
+
| Jest | Report to [Testomat.io](https://testomat.io) |
|
|
35
|
+
| ... | ... your custom report |
|
|
38
36
|
|
|
39
37
|
If you use multiple test frameworks and you need to use one customizable reporter, check Testomat.io Reporter, as you can adjust it once and attach it to all your projects.
|
|
40
38
|
|
|
@@ -46,7 +44,6 @@ Artifacts like screenshots, videos, traces, are **uploaded to your own cloud sto
|
|
|
46
44
|
|
|
47
45
|
To enable Testomat.io Reporter install `@testomatio/reporter` package
|
|
48
46
|
|
|
49
|
-
|
|
50
47
|
Use one of your favorite package managers:
|
|
51
48
|
|
|
52
49
|
```
|
|
@@ -65,46 +62,52 @@ yarn add @testomatio/reporter --dev
|
|
|
65
62
|
|
|
66
63
|
### 1οΈβ£ Attach Reporter to the Test Runner
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
* #### [Detox](./docs/frameworks.md#Detox)
|
|
76
|
-
* #### [Codeception](https://github.com/testomatio/php-reporter)
|
|
77
|
-
* #### [Newman (Postman)](./docs/frameworks.md#Newman)
|
|
78
|
-
* #### [JUnit](./docs/junit.md#junit)
|
|
79
|
-
* #### [NUnit](./docs/junit.md#nunit)
|
|
80
|
-
* #### [PyTest](./docs/junit.md#pytest)
|
|
81
|
-
* #### [PHPUnit](./docs/junit.md#phpunit)
|
|
82
|
-
* #### [Protractor](./docs/frameworks.md#protractor)
|
|
83
|
-
|
|
84
|
-
or any [other via JUnit](./docs/junit.md) report....
|
|
65
|
+
| | | |
|
|
66
|
+
| ----------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- |
|
|
67
|
+
| [Playwright](./docs/frameworks.md#playwright) | [CodeceptJS](./docs/frameworks.md#CodeceptJS) | [Cypress](./docs/frameworks.md#Cypress) |
|
|
68
|
+
| [Jest](./docs/frameworks.md#Jest) | [Mocha](./docs/frameworks.md#Mocha) | [WebDriverIO](./docs/frameworks.md#WebDriverIO) |
|
|
69
|
+
| [TestCafe](./docs/frameworks.md#TestCafe) | [Detox](./docs/frameworks.md#Detox) | [Codeception](https://github.com/testomatio/php-reporter) |
|
|
70
|
+
| [Newman (Postman)](./docs/frameworks.md#Newman) | [JUnit](./docs/junit.md#junit) | [NUnit](./docs/junit.md#nunit) |
|
|
71
|
+
| [PyTest](./docs/junit.md#pytest) | [PHPUnit](./docs/junit.md#phpunit) | [Protractor](./docs/frameworks.md#protractor) |
|
|
85
72
|
|
|
86
|
-
|
|
73
|
+
or **any [other via JUnit](./docs/junit.md)** report....
|
|
87
74
|
|
|
88
|
-
|
|
89
|
-
* [Create brief summary report for GitHub Pull Request](./docs/pipes.md#github-pipe) π
|
|
90
|
-
* [Create brief summary report for GitLab Merge Request](./docs/pipes.md#gitlab-pipe).
|
|
91
|
-
* [Configure other pipes](./docs/pipes.md) for other ways to process test results output.
|
|
75
|
+
### 2οΈβ£ Configure Reports
|
|
92
76
|
|
|
77
|
+
- [Create report on Testomat.io](./docs/pipes/testomatio.md).
|
|
78
|
+
- [Create brief summary report for GitHub Pull Request](./docs/pipes/github.md) π
|
|
79
|
+
- [Create brief summary report for GitLab Merge Request](./docs/pipes/gitlab.md).
|
|
80
|
+
- [Configure other pipes](./docs/pipes/md) for other ways to process test results output.
|
|
93
81
|
|
|
94
|
-

|
|
82
|
+

|
|
95
83
|
|
|
96
84
|
GitHub report published as a comment to Pull Request:
|
|
97
85
|
|
|
98
86
|
### 3οΈβ£ Enable Artifacts Storage
|
|
99
87
|
|
|
100
|
-
1. Create bucket on AWS, Google Cloud, or any other cloud storage provider supporting S3 protocol.
|
|
88
|
+
1. Create bucket on AWS, Google Cloud, or any other cloud storage provider supporting S3 protocol.
|
|
101
89
|
2. [Pass S3 credentials](./docs/artifacts.md) to reporter to enable artifacts uploading.
|
|
102
90
|
|
|
103
91
|
### 4οΈβ£ Use Logger
|
|
104
92
|
|
|
105
93
|
Intercept your logger messages or log anything with our [Logger](./docs/logger.md) (_work in progress_).
|
|
106
94
|
|
|
107
|
-
### 5οΈβ£
|
|
95
|
+
### 5οΈβ£ TESTOMATIO HTML Report
|
|
96
|
+
|
|
97
|
+
Testomatio now features a custom reporting tool that allows you to generate a standalone HTML/CSS report for easy visualization of your test runs. This mode provides a quick way to gain a clear and visually appealing overview of your test execution.
|
|
98
|
+
|
|
99
|
+
With our reporter, you can:
|
|
100
|
+
|
|
101
|
+
- Easily analyze the results of your test runs in a convenient HTML format.
|
|
102
|
+
|
|
103
|
+
* Visualize data on successful and failed tests, including statistics and error details.
|
|
104
|
+
* Quickly share reports with your team members or stakeholders.
|
|
105
|
+
|
|
106
|
+

|
|
107
|
+
|
|
108
|
+
Learn more about generating HTML reports [here](./docs/pipes/html.md)
|
|
109
|
+
|
|
110
|
+
### 6οΈβ£ Add to CI Pipeline
|
|
108
111
|
|
|
109
112
|
After you tested reporter locally add it to your CI pipeline.
|
|
110
113
|
|
|
@@ -116,20 +119,23 @@ After you tested reporter locally add it to your CI pipeline.
|
|
|
116
119
|
|
|
117
120
|
Bring this reporter on CI and never lose test results again!
|
|
118
121
|
|
|
119
|
-
|
|
120
122
|
## Documentation
|
|
121
123
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
- π οΈ [Frameworks](./docs/frameworks.md)
|
|
125
|
+
- β² [Pipes](./docs/pipes.md)
|
|
126
|
+
- [Testomat.io](./docs/pipes/testomatio.md)
|
|
127
|
+
- [GitHub](./docs/pipes/github.md)
|
|
128
|
+
- [Gitlab](./docs/pipes/gitlab.md)
|
|
129
|
+
- [CSV](./docs/pipes/csv.md)
|
|
130
|
+
- [HTML report](./docs/pipes/html.md)
|
|
131
|
+
- π [JUnit](./docs/junit.md)
|
|
132
|
+
- ποΈ [Artifacts](./docs/artifacts.md)
|
|
133
|
+
- π [Workflows](./docs/workflows.md)
|
|
134
|
+
- ποΈ [Logger](./docs/logger.md)
|
|
128
135
|
|
|
129
136
|
## Development
|
|
130
137
|
|
|
131
|
-
|
|
132
|
-
### REST API
|
|
138
|
+
### REST API
|
|
133
139
|
|
|
134
140
|
Testomat.io App uses REST API to collect data from the reporter.
|
|
135
141
|
|
|
@@ -144,6 +150,7 @@ To print all reporter logs:
|
|
|
144
150
|
```
|
|
145
151
|
DEBUG=@testomatio/reporter:*
|
|
146
152
|
```
|
|
153
|
+
|
|
147
154
|
To print all reporter logs of a specific pipe:
|
|
148
155
|
|
|
149
156
|
```
|
package/lib/adapter/codecept.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const debug = require('debug')('@testomatio/reporter:adapter:codeceptjs');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const TestomatClient = require('../client');
|
|
4
|
-
const { STATUS, APP_PREFIX,
|
|
4
|
+
const { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
|
|
5
5
|
const upload = require('../fileUploader');
|
|
6
|
-
const { parseTest
|
|
6
|
+
const { parseTest, fileSystem } = require('../utils/utils');
|
|
7
|
+
const { services } = require('../services');
|
|
7
8
|
|
|
8
9
|
if (!global.codeceptjs) {
|
|
9
10
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
@@ -51,21 +52,56 @@ function CodeceptReporter(config) {
|
|
|
51
52
|
|
|
52
53
|
recorder.startUnlessRunning();
|
|
53
54
|
|
|
54
|
-
global.testomatioRunningEnvironment = 'codeceptjs';
|
|
55
|
-
|
|
56
55
|
// Listening to events
|
|
57
56
|
event.dispatcher.on(event.all.before, () => {
|
|
58
57
|
// clear tmp dir
|
|
59
|
-
fileSystem.clearDir(
|
|
58
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
60
59
|
|
|
61
|
-
recorder.add('Creating new run', () =>
|
|
60
|
+
// recorder.add('Creating new run', () => );
|
|
61
|
+
client.createRun();
|
|
62
62
|
videos = [];
|
|
63
63
|
traces = [];
|
|
64
64
|
|
|
65
65
|
if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
let hookSteps = [];
|
|
69
|
+
let suiteHookRunning = false;
|
|
70
|
+
|
|
71
|
+
event.dispatcher.on(event.suite.before, suite => {
|
|
72
|
+
suiteHookRunning = true;
|
|
73
|
+
hookSteps = [];
|
|
74
|
+
global.testomatioDataStore.steps = [];
|
|
75
|
+
|
|
76
|
+
services.setContext(suite.fullTitle());
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
event.dispatcher.on(event.suite.after, () => {
|
|
80
|
+
services.setContext(null);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
event.dispatcher.on(event.hook.started, () => {
|
|
84
|
+
// global.testomatioDataStore.steps = [];
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
event.dispatcher.on(event.hook.passed, () => {
|
|
88
|
+
if (suiteHookRunning) {
|
|
89
|
+
hookSteps.push(...global.testomatioDataStore.steps);
|
|
90
|
+
services.setContext(null);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
event.dispatcher.on(event.hook.failed, () => {
|
|
95
|
+
if (suiteHookRunning) {
|
|
96
|
+
hookSteps.push(...global.testomatioDataStore.steps);
|
|
97
|
+
services.setContext(null);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
event.dispatcher.on(event.test.before, test => {
|
|
102
|
+
suiteHookRunning = false;
|
|
103
|
+
global.testomatioDataStore.steps = [];
|
|
104
|
+
|
|
69
105
|
recorder.add(() => {
|
|
70
106
|
currentMetaStep = [];
|
|
71
107
|
// output.reset();
|
|
@@ -73,12 +109,18 @@ function CodeceptReporter(config) {
|
|
|
73
109
|
stepShift = 0;
|
|
74
110
|
});
|
|
75
111
|
|
|
112
|
+
if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
113
|
+
// reset steps
|
|
76
114
|
global.testomatioDataStore.steps = [];
|
|
115
|
+
|
|
116
|
+
services.setContext(test.fullTitle());
|
|
77
117
|
});
|
|
78
118
|
|
|
79
119
|
event.dispatcher.on(event.test.started, test => {
|
|
120
|
+
services.setContext(test.fullTitle());
|
|
121
|
+
|
|
80
122
|
testTimeMap[test.id] = Date.now();
|
|
81
|
-
|
|
123
|
+
// start logging
|
|
82
124
|
});
|
|
83
125
|
|
|
84
126
|
event.dispatcher.on(event.all.result, async () => {
|
|
@@ -100,8 +142,14 @@ function CodeceptReporter(config) {
|
|
|
100
142
|
if (id && failedTests.includes(id)) {
|
|
101
143
|
failedTests = failedTests.filter(failed => id !== failed);
|
|
102
144
|
}
|
|
103
|
-
const testId = parseTest(tags);
|
|
145
|
+
const testId = parseTest(`${title} ${tags.join(' ')}`);
|
|
104
146
|
const testObj = getTestAndMessage(title);
|
|
147
|
+
|
|
148
|
+
const logs = getTestLogs(test);
|
|
149
|
+
const manuallyAttachedArtifacts = services.artifacts.get(test.fullTitle());
|
|
150
|
+
const keyValues = services.keyValues.get(test.fullTitle());
|
|
151
|
+
services.setContext(null);
|
|
152
|
+
|
|
105
153
|
client.addTestRun(STATUS.PASSED, {
|
|
106
154
|
...stripExampleFromTitle(title),
|
|
107
155
|
suite_title: test.parent && test.parent.title,
|
|
@@ -109,6 +157,9 @@ function CodeceptReporter(config) {
|
|
|
109
157
|
time: getDuration(test),
|
|
110
158
|
steps: global.testomatioDataStore.steps.join('\n') || null,
|
|
111
159
|
test_id: testId,
|
|
160
|
+
logs,
|
|
161
|
+
manuallyAttachedArtifacts,
|
|
162
|
+
meta: keyValues,
|
|
112
163
|
});
|
|
113
164
|
// output.stop();
|
|
114
165
|
});
|
|
@@ -125,7 +176,7 @@ function CodeceptReporter(config) {
|
|
|
125
176
|
for (const test of suite.tests) {
|
|
126
177
|
const { id, tags, title } = test;
|
|
127
178
|
failedTests.push(id || title);
|
|
128
|
-
const testId = parseTest(tags);
|
|
179
|
+
const testId = parseTest(`${title} ${tags.join(' ')}`);
|
|
129
180
|
|
|
130
181
|
client.addTestRun(STATUS.FAILED, {
|
|
131
182
|
...stripExampleFromTitle(title),
|
|
@@ -143,16 +194,18 @@ function CodeceptReporter(config) {
|
|
|
143
194
|
if (test.err) error = test.err;
|
|
144
195
|
const { id, tags, title, artifacts } = test;
|
|
145
196
|
failedTests.push(id || title);
|
|
146
|
-
let testId = parseTest(tags);
|
|
197
|
+
let testId = parseTest(`${title} ${tags.join(' ')}`);
|
|
147
198
|
const testObj = getTestAndMessage(title);
|
|
148
|
-
if (error && error.stack && test.steps && test.steps.length) {
|
|
149
|
-
error.stack = test.steps[test.steps.length - 1].line();
|
|
150
|
-
}
|
|
151
199
|
|
|
152
200
|
const files = [];
|
|
153
201
|
if (artifacts.screenshot) files.push({ path: artifacts.screenshot, type: 'image/png' });
|
|
154
202
|
// todo: video must be uploaded later....
|
|
155
203
|
|
|
204
|
+
const logs = getTestLogs(test);
|
|
205
|
+
const manuallyAttachedArtifacts = services.artifacts.get(test.fullTitle());
|
|
206
|
+
const keyValues = services.keyValues.get(test.fullTitle());
|
|
207
|
+
services.setContext(null);
|
|
208
|
+
|
|
156
209
|
const reportTestPromise = client
|
|
157
210
|
.addTestRun(STATUS.FAILED, {
|
|
158
211
|
...stripExampleFromTitle(title),
|
|
@@ -162,7 +215,10 @@ function CodeceptReporter(config) {
|
|
|
162
215
|
message: testObj.message,
|
|
163
216
|
time: getDuration(test),
|
|
164
217
|
files,
|
|
165
|
-
steps: global.testomatioDataStore
|
|
218
|
+
steps: global.testomatioDataStore?.steps?.join('\n') || null,
|
|
219
|
+
logs,
|
|
220
|
+
manuallyAttachedArtifacts,
|
|
221
|
+
meta: keyValues,
|
|
166
222
|
})
|
|
167
223
|
.then(pipes => {
|
|
168
224
|
testId = pipes.filter(p => p.pipe.includes('Testomatio'))[0]?.result?.data?.test_id;
|
|
@@ -184,7 +240,7 @@ function CodeceptReporter(config) {
|
|
|
184
240
|
const { id, tags, title } = test;
|
|
185
241
|
if (failedTests.includes(id || title)) return;
|
|
186
242
|
|
|
187
|
-
const testId = parseTest(tags);
|
|
243
|
+
const testId = parseTest(`${title} ${tags.join(' ')}`);
|
|
188
244
|
const testObj = getTestAndMessage(title);
|
|
189
245
|
client.addTestRun(STATUS.SKIPPED, {
|
|
190
246
|
...stripExampleFromTitle(title),
|
|
@@ -219,19 +275,19 @@ function CodeceptReporter(config) {
|
|
|
219
275
|
if (!metaSteps[i]) continue;
|
|
220
276
|
if (metaSteps[i].isBDD()) {
|
|
221
277
|
// output.push(repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment);
|
|
222
|
-
global.testomatioDataStore
|
|
278
|
+
global.testomatioDataStore?.steps?.push(
|
|
223
279
|
repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment,
|
|
224
280
|
);
|
|
225
281
|
} else {
|
|
226
282
|
// output.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
|
|
227
|
-
global.testomatioDataStore
|
|
283
|
+
global.testomatioDataStore?.steps?.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
|
|
228
284
|
}
|
|
229
285
|
}
|
|
230
286
|
}
|
|
231
287
|
currentMetaStep = metaSteps;
|
|
232
288
|
stepShift = 2 * shift;
|
|
233
289
|
|
|
234
|
-
const durationMs = +new Date() -
|
|
290
|
+
const durationMs = +new Date() - +stepStart;
|
|
235
291
|
let duration = '';
|
|
236
292
|
if (durationMs) {
|
|
237
293
|
duration = repeat(1) + chalk.grey(`(${durationMs}ms)`);
|
|
@@ -239,16 +295,16 @@ function CodeceptReporter(config) {
|
|
|
239
295
|
|
|
240
296
|
if (step.status === STATUS.FAILED) {
|
|
241
297
|
// output.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
|
|
242
|
-
global.testomatioDataStore
|
|
298
|
+
global.testomatioDataStore?.steps?.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
|
|
243
299
|
} else {
|
|
244
300
|
// output.push(repeat(stepShift) + step.toString() + duration);
|
|
245
|
-
global.testomatioDataStore
|
|
301
|
+
global.testomatioDataStore?.steps?.push(repeat(stepShift) + step.toString() + duration);
|
|
246
302
|
}
|
|
247
303
|
});
|
|
248
304
|
|
|
249
305
|
event.dispatcher.on(event.step.comment, step => {
|
|
250
306
|
// output.push(chalk.cyan.bold(step.toString()));
|
|
251
|
-
global.testomatioDataStore
|
|
307
|
+
global.testomatioDataStore?.steps?.push(chalk.cyan.bold(step.toString()));
|
|
252
308
|
});
|
|
253
309
|
}
|
|
254
310
|
|
|
@@ -256,7 +312,7 @@ async function uploadAttachments(client, attachments, messagePrefix, attachmentT
|
|
|
256
312
|
if (attachments.length > 0) {
|
|
257
313
|
console.log(APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType}/-s ...`);
|
|
258
314
|
|
|
259
|
-
const promises = attachments.map(async
|
|
315
|
+
const promises = attachments.map(async attachment => {
|
|
260
316
|
const { testId, title, path, type } = attachment;
|
|
261
317
|
const file = { path, type, title };
|
|
262
318
|
return client.addTestRun(undefined, {
|
|
@@ -270,18 +326,6 @@ async function uploadAttachments(client, attachments, messagePrefix, attachmentT
|
|
|
270
326
|
}
|
|
271
327
|
}
|
|
272
328
|
|
|
273
|
-
function parseTest(tags) {
|
|
274
|
-
if (tags) {
|
|
275
|
-
for (const tag of tags) {
|
|
276
|
-
if (tag.startsWith('@T')) {
|
|
277
|
-
return tag.substring(2, tag.length);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return null;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
329
|
function getTestAndMessage(title) {
|
|
286
330
|
const testObj = { message: '' };
|
|
287
331
|
const testArr = title.split(/\s(\|\s\{.*?\})/);
|
|
@@ -304,4 +348,21 @@ function repeat(num) {
|
|
|
304
348
|
return ''.padStart(num, ' ');
|
|
305
349
|
}
|
|
306
350
|
|
|
351
|
+
// TODO: think about moving to some common utils
|
|
352
|
+
function getTestLogs(test) {
|
|
353
|
+
const suiteLogsArr = services.logger.getLogs(test.parent.fullTitle());
|
|
354
|
+
const suiteLogs = suiteLogsArr ? suiteLogsArr.join('\n').trim() : '';
|
|
355
|
+
const testLogsArr = services.logger.getLogs(test.fullTitle());
|
|
356
|
+
const testLogs = testLogsArr ? testLogsArr.join('\n').trim() : '';
|
|
357
|
+
|
|
358
|
+
let logs = '';
|
|
359
|
+
if (suiteLogs) {
|
|
360
|
+
logs += `${chalk.bold('\t--- BeforeSuite ---')}\n${suiteLogs}`;
|
|
361
|
+
}
|
|
362
|
+
if (testLogs) {
|
|
363
|
+
logs += `\n${chalk.bold('\t--- Test ---')}\n${testLogs}`;
|
|
364
|
+
}
|
|
365
|
+
return logs;
|
|
366
|
+
}
|
|
367
|
+
|
|
307
368
|
module.exports = CodeceptReporter;
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
const { Formatter, formatterHelpers } = require('@cucumber/cucumber');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const { STATUS,
|
|
5
|
+
const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
|
|
6
6
|
const TestomatClient = require('../../client');
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const { parseTest, fileSystem } = require('../../utils/utils');
|
|
8
|
+
const config = require('../../config');
|
|
9
|
+
const { services } = require('../../services');
|
|
9
10
|
|
|
10
11
|
const { GherkinDocumentParser, PickleParser } = formatterHelpers;
|
|
11
12
|
const { getGherkinScenarioLocationMap, getGherkinStepMap } = GherkinDocumentParser;
|
|
@@ -29,15 +30,13 @@ class CucumberReporter extends Formatter {
|
|
|
29
30
|
this.failures = [];
|
|
30
31
|
this.cases = [];
|
|
31
32
|
|
|
32
|
-
this.client = new TestomatClient({ apiKey: options.apiKey ||
|
|
33
|
+
this.client = new TestomatClient({ apiKey: options.apiKey || config.TESTOMATIO });
|
|
33
34
|
this.status = STATUS.PASSED;
|
|
34
|
-
|
|
35
|
-
global.testomatioRunningEnvironment = 'cucumber:current';
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
parseEnvelope(envelope) {
|
|
39
38
|
if (envelope.testRunStarted) {
|
|
40
|
-
fileSystem.clearDir(
|
|
39
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
41
40
|
}
|
|
42
41
|
if (envelope.testCaseStarted && this.client) {
|
|
43
42
|
this.client.createRun();
|
|
@@ -49,9 +48,10 @@ class CucumberReporter extends Formatter {
|
|
|
49
48
|
|
|
50
49
|
onTestCaseStarted(testCaseStarted) {
|
|
51
50
|
const testCaseAttempt = this.eventDataCollector.getTestCaseAttempt(testCaseStarted.id);
|
|
52
|
-
const testId = getTestId(testCaseAttempt.pickle);
|
|
53
51
|
if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
54
|
-
|
|
52
|
+
|
|
53
|
+
const testTitle = testCaseAttempt.pickle.name + testCaseAttempt.pickle.uri;
|
|
54
|
+
services.setContext(testTitle);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
onTestCaseFinished(testCaseFinished) {
|
|
@@ -109,7 +109,10 @@ class CucumberReporter extends Formatter {
|
|
|
109
109
|
|
|
110
110
|
if (!this.client) return;
|
|
111
111
|
|
|
112
|
-
const
|
|
112
|
+
const testTitle = testCaseAttempt.pickle.name + testCaseAttempt.pickle.uri;
|
|
113
|
+
const logs = services.logger.getLogs(testTitle).join('\n');
|
|
114
|
+
const artifacts = services.artifacts.get(testTitle);
|
|
115
|
+
const keyValues = services.keyValues.get(testTitle);
|
|
113
116
|
|
|
114
117
|
this.client.addTestRun(status, {
|
|
115
118
|
// error: testCaseAttempt.worstTestStepResult.message,
|
|
@@ -119,11 +122,15 @@ class CucumberReporter extends Formatter {
|
|
|
119
122
|
.join('\n')
|
|
120
123
|
.trim(),
|
|
121
124
|
example: { ...example },
|
|
122
|
-
|
|
125
|
+
logs,
|
|
126
|
+
manuallyAttachedArtifacts: artifacts,
|
|
127
|
+
meta: keyValues,
|
|
123
128
|
title: scenario,
|
|
124
129
|
test_id: testId,
|
|
125
130
|
time,
|
|
126
131
|
});
|
|
132
|
+
|
|
133
|
+
services.setContext(null);
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
onTestRunFinished(envelope) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
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 { parseTest, fileSystem } = require('../../
|
|
5
|
-
const { STATUS,
|
|
4
|
+
const { parseTest, fileSystem } = require('../../utils/utils');
|
|
5
|
+
const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
|
|
6
6
|
const TestomatClient = require('../../client');
|
|
7
|
+
const config = require('../../config');
|
|
7
8
|
|
|
8
9
|
const createTestomatFormatter = apiKey => {
|
|
9
10
|
if (!apiKey || apiKey === '') {
|
|
@@ -97,7 +98,7 @@ const createTestomatFormatter = apiKey => {
|
|
|
97
98
|
|
|
98
99
|
options.eventBroadcaster.on('gherkin-document', addDocument);
|
|
99
100
|
options.eventBroadcaster.on('test-run-started', () => {
|
|
100
|
-
fileSystem.clearDir(
|
|
101
|
+
fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
|
|
101
102
|
this?.client?.createRun();
|
|
102
103
|
});
|
|
103
104
|
options.eventBroadcaster.on('test-case-finished', this.onTestCaseFinished.bind(this));
|
|
@@ -110,7 +111,7 @@ const createTestomatFormatter = apiKey => {
|
|
|
110
111
|
onTestCaseStarted(event) {
|
|
111
112
|
const scenario = getScenario(event.sourceLocation);
|
|
112
113
|
const testId = getTestId(scenario);
|
|
113
|
-
|
|
114
|
+
|
|
114
115
|
if (!global.testomatioDataStore) global.testomatioDataStore = {};
|
|
115
116
|
global.testomatioDataStore.currentlyRunningTestId = testId;
|
|
116
117
|
}
|
|
@@ -151,4 +152,4 @@ const createTestomatFormatter = apiKey => {
|
|
|
151
152
|
};
|
|
152
153
|
};
|
|
153
154
|
|
|
154
|
-
module.exports = createTestomatFormatter(
|
|
155
|
+
module.exports = createTestomatFormatter(config.TESTOMATIO);
|
package/lib/adapter/cucumber.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
try {
|
|
2
2
|
// eslint-disable-next-line import/no-unresolved
|
|
3
|
-
require.resolve(
|
|
3
|
+
require.resolve('@cucumber/cucumber');
|
|
4
4
|
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
5
5
|
module.exports = require('./cucumber/current');
|
|
6
6
|
} catch (_e) {
|
|
@@ -11,6 +11,6 @@ try {
|
|
|
11
11
|
module.exports = require('./cucumber/legacy');
|
|
12
12
|
} catch (_err) {
|
|
13
13
|
console.error('Cucumber packages: "@cucumber/cucumber" or "cucumber" were not detected. Report won\'t be sent');
|
|
14
|
-
module.exports = {}
|
|
14
|
+
module.exports = {};
|
|
15
15
|
}
|
|
16
16
|
}
|