@testomatio/reporter 1.3.0-beta β†’ 1.3.0-ignore-stack-for-passed.1

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.
Files changed (47) hide show
  1. package/README.md +61 -54
  2. package/lib/adapter/codecept.js +96 -35
  3. package/lib/adapter/cucumber/current.js +18 -11
  4. package/lib/adapter/cucumber/legacy.js +6 -5
  5. package/lib/adapter/cucumber.js +2 -2
  6. package/lib/adapter/cypress-plugin/index.js +52 -25
  7. package/lib/adapter/jasmine.js +1 -1
  8. package/lib/adapter/jest.js +49 -16
  9. package/lib/adapter/mocha.js +103 -51
  10. package/lib/adapter/playwright.js +95 -33
  11. package/lib/adapter/webdriver.js +1 -1
  12. package/lib/bin/reportXml.js +14 -13
  13. package/lib/bin/startTest.js +27 -6
  14. package/lib/client.js +180 -61
  15. package/lib/config.js +34 -0
  16. package/lib/constants.js +19 -7
  17. package/lib/data-storage.js +203 -0
  18. package/lib/fileUploader.js +128 -53
  19. package/lib/junit-adapter/adapter.js +0 -2
  20. package/lib/junit-adapter/csharp.js +3 -4
  21. package/lib/junit-adapter/index.js +3 -3
  22. package/lib/junit-adapter/java.js +35 -17
  23. package/lib/junit-adapter/javascript.js +1 -2
  24. package/lib/junit-adapter/python.js +12 -14
  25. package/lib/junit-adapter/ruby.js +1 -2
  26. package/lib/pipe/csv.js +5 -3
  27. package/lib/pipe/github.js +27 -39
  28. package/lib/pipe/gitlab.js +20 -24
  29. package/lib/pipe/html.js +317 -0
  30. package/lib/pipe/index.js +3 -1
  31. package/lib/pipe/testomatio.js +189 -56
  32. package/lib/reporter-functions.js +46 -0
  33. package/lib/reporter.js +11 -9
  34. package/lib/services/artifacts.js +57 -0
  35. package/lib/services/index.js +13 -0
  36. package/lib/services/key-values.js +58 -0
  37. package/lib/services/logger.js +311 -0
  38. package/lib/template/template-draft.hbs +249 -0
  39. package/lib/template/testomatio.hbs +388 -0
  40. package/lib/utils/pipe_utils.js +128 -0
  41. package/lib/{util.js β†’ utils/utils.js} +144 -14
  42. package/lib/xmlReader.js +211 -122
  43. package/package.json +16 -7
  44. package/lib/_ArtifactStorageOld.js +0 -142
  45. package/lib/artifactStorage.js +0 -25
  46. package/lib/dataStorage.js +0 -244
  47. 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
- * πŸ„ Integarion with all popular [JavaScript/TypeScript frameworks](./docs/frameworks.md)
13
- * πŸ—„οΈ Screenshots, videos, traces [uploaded into S3 bucket](./docs/artifacts.md)
14
- * πŸ”Ž Stack traces and error messages
15
- * πŸ™ [GitHub](./docs/pipes.md#github-pipe) & [GitLab](./docs/pipes.md#gitlab-pipe) integration
16
- * πŸš… Realtime reports
17
- * πŸ—ƒοΈ Other test frameworks supported via [JUNit XML](./docs/junit.md)
18
- * πŸšΆβ€β™€οΈ Steps *(work in progress)*
19
- * πŸ“„ Logger *(work in progress, supports Jest for now)*
20
- * ☁️ Custom properties and metadata *(work in progress)*
21
- * πŸ’― Free & open-source.
22
- * πŸ“Š Public and private Run reports on cloud via [Testomat.io App](https://testomat.io) πŸ‘‡
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
  ![](./docs/images/app.png)
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 | πŸ“Š Output |
33
- |---------------|----------------------------------------|
34
- | Playwright | Report to GitHub |
35
- | Cypress | Report to GitLab |
36
- | Jest | Report to [Testomat.io](https://testomat.io) |
37
- | ... | ... your custom report |
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
- * #### [Playwright](./docs/frameworks.md#playwright)
69
- * #### [CodeceptJS](./docs/frameworks.md#CodeceptJS)
70
- * #### [Cypress](./docs/frameworks.md#Cypress)
71
- * #### [Jest](./docs/frameworks.md#Jest)
72
- * #### [Mocha](./docs/frameworks.md#Mocha)
73
- * #### [WebDriverIO](./docs/frameworks.md#WebDriverIO)
74
- * #### [TestCafe](./docs/frameworks.md#TestCafe)
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
- ### 2️⃣ Configure Reports
73
+ or **any [other via JUnit](./docs/junit.md)** report....
87
74
 
88
- * [Create report on Testomat.io](./docs/pipes.md#testomatio-pipe).
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
- ![GitHub report](./docs/images/github.png)
82
+ ![GitHub report](./docs/pipes/images/github.png)
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️⃣ Add to CI Pipeline
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
+ ![HTML report](./docs/images/html_reporter_example.gif)
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
- * πŸ› οΈ [Frameworks](./docs/frameworks.md)
123
- * β›² [Pipes](./docs/pipes.md)
124
- * πŸ““ [JUnit](./docs/junit.md)
125
- * πŸ—„οΈ [Artifacts](./docs/artifacts.md)
126
- * πŸ”‚ [Workflows](./docs/workflows.md)
127
- * πŸ”‚ [Logger](./docs/logger.md)
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
  ```
@@ -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, TESTOMAT_TMP_STORAGE } = require('../constants');
4
+ const { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
5
5
  const upload = require('../fileUploader');
6
- const { parseTest: getIdFromTestTitle, fileSystem } = require('../util');
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(TESTOMAT_TMP_STORAGE.mainDir);
58
+ fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
60
59
 
61
- recorder.add('Creating new run', () => client.createRun());
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
- event.dispatcher.on(event.test.before, () => {
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
- if (global.testomatioDataStore) global.testomatioDataStore.currentlyRunningTestId = getIdFromTestTitle(test.title);
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.steps.join('\n') || null,
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.steps.push(
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.steps.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
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() - (+stepStart);
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.steps.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
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.steps.push(repeat(stepShift) + step.toString() + duration);
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.steps.push(chalk.cyan.bold(step.toString()));
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 (attachment) => {
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, TESTOMAT_TMP_STORAGE } = require('../../constants');
5
+ const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
6
6
  const TestomatClient = require('../../client');
7
- const logger = require('../../logger');
8
- const { parseTest, fileSystem } = require('../../util');
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 || process.env.TESTOMATIO });
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(TESTOMAT_TMP_STORAGE.mainDir);
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
- global.testomatioDataStore.currentlyRunningTestId = testId;
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 logs = logger.getLogs(testId);
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
- stack: logs,
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('../../util');
5
- const { STATUS, TESTOMAT_TMP_STORAGE } = require('../../constants');
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(TESTOMAT_TMP_STORAGE.mainDir);
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(process.env.TESTOMATIO);
155
+ module.exports = createTestomatFormatter(config.TESTOMATIO);
@@ -1,6 +1,6 @@
1
1
  try {
2
2
  // eslint-disable-next-line import/no-unresolved
3
- require.resolve("@cucumber/cucumber");
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
  }