@testomatio/reporter 2.0.1-beta.5-timestamp → 2.0.1-beta.7

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 (152) hide show
  1. package/README.md +1 -0
  2. package/lib/adapter/codecept.d.ts +2 -0
  3. package/lib/adapter/codecept.js +297 -335
  4. package/lib/adapter/cucumber/current.d.ts +14 -0
  5. package/lib/adapter/cucumber/current.js +195 -203
  6. package/lib/adapter/cucumber/legacy.d.ts +0 -0
  7. package/lib/adapter/cucumber/legacy.js +130 -155
  8. package/lib/adapter/cucumber.d.ts +2 -0
  9. package/lib/adapter/cucumber.js +5 -16
  10. package/lib/adapter/cypress-plugin/index.d.ts +2 -0
  11. package/lib/adapter/cypress-plugin/index.js +91 -105
  12. package/lib/adapter/jasmine.d.ts +11 -0
  13. package/lib/adapter/jasmine.js +54 -53
  14. package/lib/adapter/jest.d.ts +13 -0
  15. package/lib/adapter/jest.js +97 -99
  16. package/lib/adapter/mocha.d.ts +2 -0
  17. package/lib/adapter/mocha.js +112 -141
  18. package/lib/adapter/nightwatch.d.ts +4 -0
  19. package/lib/adapter/nightwatch.js +80 -0
  20. package/lib/adapter/playwright.d.ts +14 -0
  21. package/lib/adapter/playwright.js +208 -231
  22. package/lib/adapter/vitest.d.ts +35 -0
  23. package/lib/adapter/vitest.js +150 -149
  24. package/lib/adapter/webdriver.d.ts +24 -0
  25. package/lib/adapter/webdriver.js +144 -121
  26. package/lib/bin/cli.d.ts +2 -0
  27. package/lib/bin/cli.js +229 -211
  28. package/lib/bin/reportXml.d.ts +2 -0
  29. package/lib/bin/reportXml.js +51 -52
  30. package/lib/bin/startTest.d.ts +2 -0
  31. package/lib/bin/startTest.js +83 -95
  32. package/lib/bin/uploadArtifacts.d.ts +2 -0
  33. package/lib/bin/uploadArtifacts.js +56 -61
  34. package/lib/client.d.ts +76 -0
  35. package/lib/client.js +431 -465
  36. package/lib/config.d.ts +1 -0
  37. package/lib/config.js +18 -23
  38. package/lib/constants.d.ts +25 -0
  39. package/lib/constants.js +50 -44
  40. package/lib/data-storage.d.ts +34 -0
  41. package/lib/data-storage.js +216 -188
  42. package/lib/junit-adapter/adapter.d.ts +9 -0
  43. package/lib/junit-adapter/adapter.js +17 -20
  44. package/lib/junit-adapter/csharp.d.ts +5 -0
  45. package/lib/junit-adapter/csharp.js +28 -14
  46. package/lib/junit-adapter/index.d.ts +3 -0
  47. package/lib/junit-adapter/index.js +27 -25
  48. package/lib/junit-adapter/java.d.ts +5 -0
  49. package/lib/junit-adapter/java.js +41 -53
  50. package/lib/junit-adapter/javascript.d.ts +4 -0
  51. package/lib/junit-adapter/javascript.js +30 -27
  52. package/lib/junit-adapter/python.d.ts +5 -0
  53. package/lib/junit-adapter/python.js +38 -37
  54. package/lib/junit-adapter/ruby.d.ts +4 -0
  55. package/lib/junit-adapter/ruby.js +11 -8
  56. package/lib/output.d.ts +11 -0
  57. package/lib/output.js +44 -52
  58. package/lib/package.json +3 -0
  59. package/lib/pipe/bitbucket.d.ts +25 -0
  60. package/lib/pipe/bitbucket.js +223 -230
  61. package/lib/pipe/csv.d.ts +47 -0
  62. package/lib/pipe/csv.js +113 -126
  63. package/lib/pipe/debug.d.ts +29 -0
  64. package/lib/pipe/debug.js +125 -99
  65. package/lib/pipe/github.d.ts +30 -0
  66. package/lib/pipe/github.js +218 -213
  67. package/lib/pipe/gitlab.d.ts +25 -0
  68. package/lib/pipe/gitlab.js +183 -206
  69. package/lib/pipe/html.d.ts +35 -0
  70. package/lib/pipe/html.js +258 -321
  71. package/lib/pipe/index.d.ts +1 -0
  72. package/lib/pipe/index.js +94 -66
  73. package/lib/pipe/testomatio.d.ts +71 -0
  74. package/lib/pipe/testomatio.js +429 -474
  75. package/lib/replay.d.ts +31 -0
  76. package/lib/replay.js +255 -0
  77. package/lib/reporter-functions.d.ts +41 -0
  78. package/lib/reporter-functions.js +64 -26
  79. package/lib/reporter.d.ts +235 -0
  80. package/lib/reporter.js +37 -29
  81. package/lib/services/artifacts.d.ts +33 -0
  82. package/lib/services/artifacts.js +55 -51
  83. package/lib/services/index.d.ts +11 -0
  84. package/lib/services/index.js +16 -12
  85. package/lib/services/key-values.d.ts +27 -0
  86. package/lib/services/key-values.js +56 -53
  87. package/lib/services/labels.d.ts +22 -0
  88. package/lib/services/labels.js +62 -0
  89. package/lib/services/logger.d.ts +64 -0
  90. package/lib/services/logger.js +226 -245
  91. package/lib/template/testomatio.hbs +1026 -1366
  92. package/lib/uploader.d.ts +60 -0
  93. package/lib/uploader.js +295 -364
  94. package/lib/utils/pipe_utils.d.ts +41 -0
  95. package/lib/utils/pipe_utils.js +89 -85
  96. package/lib/utils/utils.d.ts +54 -0
  97. package/lib/utils/utils.js +398 -307
  98. package/lib/xmlReader.d.ts +92 -0
  99. package/lib/xmlReader.js +525 -532
  100. package/package.json +64 -21
  101. package/src/adapter/codecept.js +377 -0
  102. package/src/adapter/cucumber/current.js +228 -0
  103. package/src/adapter/cucumber/legacy.js +158 -0
  104. package/src/adapter/cucumber.js +4 -0
  105. package/src/adapter/cypress-plugin/index.js +110 -0
  106. package/src/adapter/jasmine.js +60 -0
  107. package/src/adapter/jest.js +107 -0
  108. package/src/adapter/mocha.cjs +2 -0
  109. package/src/adapter/mocha.js +156 -0
  110. package/src/adapter/nightwatch.js +88 -0
  111. package/src/adapter/playwright.js +258 -0
  112. package/src/adapter/vitest.js +183 -0
  113. package/src/adapter/webdriver.js +142 -0
  114. package/src/bin/cli.js +348 -0
  115. package/src/bin/reportXml.js +77 -0
  116. package/src/bin/startTest.js +124 -0
  117. package/src/bin/uploadArtifacts.js +91 -0
  118. package/src/client.js +519 -0
  119. package/src/config.js +30 -0
  120. package/src/constants.js +53 -0
  121. package/src/data-storage.js +204 -0
  122. package/src/junit-adapter/adapter.js +23 -0
  123. package/src/junit-adapter/csharp.js +28 -0
  124. package/src/junit-adapter/index.js +28 -0
  125. package/src/junit-adapter/java.js +58 -0
  126. package/src/junit-adapter/javascript.js +31 -0
  127. package/src/junit-adapter/python.js +42 -0
  128. package/src/junit-adapter/ruby.js +10 -0
  129. package/src/output.js +57 -0
  130. package/src/pipe/bitbucket.js +252 -0
  131. package/src/pipe/csv.js +140 -0
  132. package/src/pipe/debug.js +125 -0
  133. package/src/pipe/github.js +232 -0
  134. package/src/pipe/gitlab.js +247 -0
  135. package/src/pipe/html.js +373 -0
  136. package/src/pipe/index.js +71 -0
  137. package/src/pipe/testomatio.js +504 -0
  138. package/src/replay.js +262 -0
  139. package/src/reporter-functions.js +96 -0
  140. package/src/reporter.cjs_decprecated +21 -0
  141. package/src/reporter.js +36 -0
  142. package/src/services/artifacts.js +59 -0
  143. package/src/services/index.js +15 -0
  144. package/src/services/key-values.js +59 -0
  145. package/src/services/labels.js +59 -0
  146. package/src/services/logger.js +315 -0
  147. package/src/template/emptyData.svg +23 -0
  148. package/src/template/testomatio.hbs +1081 -0
  149. package/src/uploader.js +376 -0
  150. package/src/utils/pipe_utils.js +119 -0
  151. package/src/utils/utils.js +416 -0
  152. package/src/xmlReader.js +614 -0
package/README.md CHANGED
@@ -133,6 +133,7 @@ Bring this reporter on CI and never lose test results again!
133
133
  - 🗄️ [Artifacts](./docs/artifacts.md)
134
134
  - 🔂 [Workflows](./docs/workflows.md)
135
135
  - 🖊️ [Logger](./docs/logger.md)
136
+ - 🪲 [Debug File Format](./docs/debug-file-format.md)
136
137
 
137
138
  ## Development
138
139
 
@@ -0,0 +1,2 @@
1
+ export default CodeceptReporter;
2
+ export function CodeceptReporter(config: any): void;
@@ -1,369 +1,331 @@
1
- const debug = require('debug')('@testomatio/reporter:adapter:codeceptjs');
2
- const chalk = require('chalk');
3
- const TestomatClient = require('../client');
4
- const { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
5
- const { getTestomatIdFromTestTitle, fileSystem } = require('../utils/utils');
6
- const { services } = require('../services');
7
-
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.CodeceptReporter = CodeceptReporter;
7
+ const debug_1 = __importDefault(require("debug"));
8
+ const picocolors_1 = __importDefault(require("picocolors"));
9
+ const client_js_1 = __importDefault(require("../client.js"));
10
+ const constants_js_1 = require("../constants.js");
11
+ const utils_js_1 = require("../utils/utils.js");
12
+ const index_js_1 = require("../services/index.js");
13
+ const codeceptjs_1 = __importDefault(require("codeceptjs"));
14
+ const debug = (0, debug_1.default)('@testomatio/reporter:adapter:codeceptjs');
15
+ // @ts-ignore
8
16
  if (!global.codeceptjs) {
9
- // eslint-disable-next-line global-require, import/no-extraneous-dependencies
10
- global.codeceptjs = require('codeceptjs');
17
+ // @ts-ignore
18
+ global.codeceptjs = codeceptjs_1.default;
11
19
  }
12
-
20
+ // @ts-ignore
13
21
  const { event, recorder, codecept } = global.codeceptjs;
14
-
15
22
  let currentMetaStep = [];
16
23
  let error;
17
24
  let stepShift = 0;
18
-
19
25
  // const output = new Output({
20
26
  // filterFn: stack => !stack.includes('codeceptjs/lib/output'), // output from codeceptjs
21
27
  // });
22
-
23
28
  let stepStart = new Date();
24
-
25
29
  const MAJOR_VERSION = parseInt(codecept.version().match(/\d/)[0], 10);
26
-
27
30
  const DATA_REGEXP = /[|\s]+?(\{".*\}|\[.*\])/;
28
-
29
31
  if (MAJOR_VERSION < 3) {
30
- console.log('🔴 This reporter works with CodeceptJS 3+, please update your tests');
32
+ console.log('🔴 This reporter works with CodeceptJS 3+, please update your tests');
31
33
  }
32
-
33
34
  function CodeceptReporter(config) {
34
- let failedTests = [];
35
- let videos = [];
36
- let traces = [];
37
- const reportTestPromises = [];
38
-
39
- const testTimeMap = {};
40
- const { apiKey } = config;
41
-
42
- const getDuration = test => {
43
- if (!test.uid) return 0;
44
- if (testTimeMap[test.uid]) {
45
- return Date.now() - testTimeMap[test.uid];
46
- }
47
-
48
- return 0;
49
- };
50
-
51
- const client = new TestomatClient({ apiKey });
52
-
53
- recorder.startUnlessRunning();
54
-
55
- // Listening to events
56
- event.dispatcher.on(event.all.before, () => {
57
- // clear tmp dir
58
- fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
59
-
60
- // recorder.add('Creating new run', () => );
61
- client.createRun();
62
- videos = [];
63
- traces = [];
64
-
65
- if (!global.testomatioDataStore) global.testomatioDataStore = {};
66
- });
67
-
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
-
105
- recorder.add(() => {
106
- currentMetaStep = [];
107
- // output.reset();
108
- // output.start();
109
- stepShift = 0;
35
+ let failedTests = [];
36
+ let videos = [];
37
+ let traces = [];
38
+ const reportTestPromises = [];
39
+ const testTimeMap = {};
40
+ const { apiKey } = config;
41
+ const getDuration = test => {
42
+ if (!test.uid)
43
+ return 0;
44
+ if (testTimeMap[test.uid]) {
45
+ return Date.now() - testTimeMap[test.uid];
46
+ }
47
+ return 0;
48
+ };
49
+ const client = new client_js_1.default({ apiKey });
50
+ recorder.startUnlessRunning();
51
+ // Listening to events
52
+ event.dispatcher.on(event.all.before, () => {
53
+ // clear tmp dir
54
+ utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
55
+ // recorder.add('Creating new run', () => );
56
+ client.createRun();
57
+ videos = [];
58
+ traces = [];
59
+ if (!global.testomatioDataStore)
60
+ global.testomatioDataStore = {};
110
61
  });
111
-
112
- if (!global.testomatioDataStore) global.testomatioDataStore = {};
113
- // reset steps
114
- global.testomatioDataStore.steps = [];
115
-
116
- services.setContext(test.fullTitle());
117
- });
118
-
119
- event.dispatcher.on(event.test.started, test => {
120
- services.setContext(test.fullTitle());
121
-
122
- if (!test.uid) return;
123
-
124
- testTimeMap[test.uid] = Date.now();
125
- // start logging
126
- });
127
-
128
- event.dispatcher.on(event.all.result, async () => {
129
- debug('waiting for all tests to be reported');
130
- // all tests were reported and we can upload videos
131
- await Promise.all(reportTestPromises);
132
-
133
- await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
134
- await uploadAttachments(client, traces, '📁 Uploading', 'trace');
135
-
136
- const status = failedTests.length === 0 ? STATUS.PASSED : STATUS.FAILED;
137
- client.updateRunStatus(status);
138
- });
139
-
140
- event.dispatcher.on(event.test.passed, test => {
141
- const { uid, tags, title } = test;
142
- if (uid && failedTests.includes(uid)) {
143
- failedTests = failedTests.filter(failed => uid !== failed);
144
- }
145
- const testObj = getTestAndMessage(title);
146
-
147
- const logs = getTestLogs(test);
148
- const manuallyAttachedArtifacts = services.artifacts.get(test.fullTitle());
149
- const keyValues = services.keyValues.get(test.fullTitle());
150
- services.setContext(null);
151
-
152
- client.addTestRun(STATUS.PASSED, {
153
- ...stripExampleFromTitle(title),
154
- rid: uid,
155
- suite_title: test.parent && test.parent.title,
156
- message: testObj.message,
157
- time: getDuration(test),
158
- steps: global.testomatioDataStore.steps.join('\n') || null,
159
- test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
160
- logs,
161
- manuallyAttachedArtifacts,
162
- meta: keyValues,
62
+ let hookSteps = [];
63
+ let suiteHookRunning = false;
64
+ event.dispatcher.on(event.suite.before, suite => {
65
+ suiteHookRunning = true;
66
+ hookSteps = [];
67
+ global.testomatioDataStore.steps = [];
68
+ index_js_1.services.setContext(suite.fullTitle());
163
69
  });
164
- // output.stop();
165
- });
166
-
167
- event.dispatcher.on(event.test.failed, (test, err) => {
168
- error = err;
169
- });
170
-
171
- event.dispatcher.on(event.hook.failed, (suite, err) => {
172
- error = err;
173
-
174
- if (!suite) return;
175
- if (!suite.tests) return;
176
- for (const test of suite.tests) {
177
- const { uid, tags, title } = test;
178
- failedTests.push(uid || title);
179
- const testId = getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`);
180
-
181
- client.addTestRun(STATUS.FAILED, {
182
- rid: uid,
183
- ...stripExampleFromTitle(title),
184
- suite_title: suite.title,
185
- test_id: testId,
186
- error,
187
- time: 0,
188
- });
189
- }
190
- // output.stop();
191
- });
192
-
193
- event.dispatcher.on(event.test.after, test => {
194
- if (test.state && test.state !== STATUS.FAILED) return;
195
- if (test.err) error = test.err;
196
- const { uid, tags, title, artifacts } = test;
197
- failedTests.push(uid || title);
198
- const testObj = getTestAndMessage(title);
199
-
200
- const files = [];
201
- if (artifacts.screenshot) files.push({ path: artifacts.screenshot, type: 'image/png' });
202
- // todo: video must be uploaded later....
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
-
209
- client.addTestRun(STATUS.FAILED, {
210
- ...stripExampleFromTitle(title),
211
- rid: uid,
212
- test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
213
- suite_title: test.parent && test.parent.title,
214
- error,
215
- message: testObj.message,
216
- time: getDuration(test),
217
- files,
218
- steps: global.testomatioDataStore?.steps?.join('\n') || null,
219
- logs,
220
- manuallyAttachedArtifacts,
221
- meta: keyValues,
70
+ event.dispatcher.on(event.suite.after, () => {
71
+ index_js_1.services.setContext(null);
222
72
  });
223
-
224
- debug('artifacts', artifacts);
225
-
226
- for (const aid in artifacts) {
227
- if (aid.startsWith('video')) videos.push({ rid: uid, title, path: artifacts[aid], type: 'video/webm' });
228
- if (aid.startsWith('trace')) traces.push({ rid: uid, title, path: artifacts[aid], type: 'application/zip' });
229
- }
230
-
231
- // output.stop();
232
- });
233
-
234
- event.dispatcher.on(event.test.skipped, test => {
235
- const { uid, tags, title } = test;
236
- if (failedTests.includes(uid || title)) return;
237
-
238
- const testObj = getTestAndMessage(title);
239
- client.addTestRun(STATUS.SKIPPED, {
240
- rid: uid,
241
- ...stripExampleFromTitle(title),
242
- test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
243
- suite_title: test.parent && test.parent.title,
244
- message: testObj.message,
245
- time: getDuration(test),
73
+ event.dispatcher.on(event.hook.started, () => {
74
+ // global.testomatioDataStore.steps = [];
246
75
  });
247
- // output.stop();
248
- });
249
-
250
- event.dispatcher.on(event.step.started, step => {
251
- stepShift = 0;
252
- step.started = true;
253
- stepStart = new Date();
254
- });
255
-
256
- event.dispatcher.on(event.step.finished, step => {
257
- if (!step.started) return;
258
- let processingStep = step;
259
- const metaSteps = [];
260
- while (processingStep.metaStep) {
261
- metaSteps.unshift(processingStep.metaStep);
262
- processingStep = processingStep.metaStep;
263
- }
264
- const shift = metaSteps.length;
265
-
266
- for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
267
- if (currentMetaStep[i] !== metaSteps[i]) {
268
- stepShift = 2 * i;
269
- // eslint-disable-next-line no-continue
270
- if (!metaSteps[i]) continue;
271
- if (metaSteps[i].isBDD()) {
272
- // output.push(repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment);
273
- global.testomatioDataStore?.steps?.push(
274
- repeat(stepShift) + chalk.bold(metaSteps[i].toString()) + metaSteps[i].comment,
275
- );
276
- } else {
277
- // output.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
278
- global.testomatioDataStore?.steps?.push(repeat(stepShift) + chalk.green.bold(metaSteps[i].toString()));
76
+ event.dispatcher.on(event.hook.passed, () => {
77
+ if (suiteHookRunning) {
78
+ hookSteps.push(...global.testomatioDataStore.steps);
79
+ index_js_1.services.setContext(null);
279
80
  }
280
- }
281
- }
282
- currentMetaStep = metaSteps;
283
- stepShift = 2 * shift;
284
-
285
- const durationMs = +new Date() - +stepStart;
286
- let duration = '';
287
- if (durationMs) {
288
- duration = repeat(1) + chalk.grey(`(${durationMs}ms)`);
289
- }
290
-
291
- if (step.status === STATUS.FAILED) {
292
- // output.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
293
- global.testomatioDataStore?.steps?.push(repeat(stepShift) + chalk.red(step.toString()) + duration);
294
- } else {
295
- // output.push(repeat(stepShift) + step.toString() + duration);
296
- global.testomatioDataStore?.steps?.push(repeat(stepShift) + step.toString() + duration);
297
- }
298
- });
299
-
300
- event.dispatcher.on(event.step.comment, step => {
301
- // output.push(chalk.cyan.bold(step.toString()));
302
- global.testomatioDataStore?.steps?.push(chalk.cyan.bold(step.toString()));
303
- });
81
+ });
82
+ event.dispatcher.on(event.hook.failed, () => {
83
+ if (suiteHookRunning) {
84
+ hookSteps.push(...global.testomatioDataStore.steps);
85
+ index_js_1.services.setContext(null);
86
+ }
87
+ });
88
+ event.dispatcher.on(event.test.before, test => {
89
+ suiteHookRunning = false;
90
+ global.testomatioDataStore.steps = [];
91
+ recorder.add(() => {
92
+ currentMetaStep = [];
93
+ // output.reset();
94
+ // output.start();
95
+ stepShift = 0;
96
+ });
97
+ if (!global.testomatioDataStore)
98
+ global.testomatioDataStore = {};
99
+ // reset steps
100
+ global.testomatioDataStore.steps = [];
101
+ index_js_1.services.setContext(test.fullTitle());
102
+ });
103
+ event.dispatcher.on(event.test.started, test => {
104
+ index_js_1.services.setContext(test.fullTitle());
105
+ testTimeMap[test.id] = Date.now();
106
+ if (!test.uid)
107
+ return;
108
+ testTimeMap[test.uid] = Date.now();
109
+ });
110
+ event.dispatcher.on(event.all.result, async () => {
111
+ debug('waiting for all tests to be reported');
112
+ // all tests were reported and we can upload videos
113
+ await Promise.all(reportTestPromises);
114
+ await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
115
+ await uploadAttachments(client, traces, '📁 Uploading', 'trace');
116
+ const status = failedTests.length === 0 ? constants_js_1.STATUS.PASSED : constants_js_1.STATUS.FAILED;
117
+ // @ts-ignore
118
+ client.updateRunStatus(status);
119
+ });
120
+ event.dispatcher.on(event.test.passed, test => {
121
+ const { uid, tags, title } = test;
122
+ if (uid && failedTests.includes(uid)) {
123
+ failedTests = failedTests.filter(failed => uid !== failed);
124
+ }
125
+ const testObj = getTestAndMessage(title);
126
+ const logs = getTestLogs(test);
127
+ const manuallyAttachedArtifacts = index_js_1.services.artifacts.get(test.fullTitle());
128
+ const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
129
+ const labels = index_js_1.services.labels.get(test.fullTitle());
130
+ index_js_1.services.setContext(null);
131
+ client.addTestRun(constants_js_1.STATUS.PASSED, {
132
+ ...stripExampleFromTitle(title),
133
+ rid: uid,
134
+ suite_title: test.parent && test.parent.title,
135
+ message: testObj.message,
136
+ time: getDuration(test),
137
+ steps: global.testomatioDataStore.steps.join('\n') || null,
138
+ test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
139
+ logs,
140
+ manuallyAttachedArtifacts,
141
+ meta: keyValues,
142
+ labels: labels,
143
+ });
144
+ // output.stop();
145
+ });
146
+ event.dispatcher.on(event.test.failed, (test, err) => {
147
+ error = err;
148
+ });
149
+ event.dispatcher.on(event.hook.failed, (suite, err) => {
150
+ error = err;
151
+ if (!suite)
152
+ return;
153
+ if (!suite.tests)
154
+ return;
155
+ for (const test of suite.tests) {
156
+ const { uid, tags, title } = test;
157
+ failedTests.push(uid || title);
158
+ const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`);
159
+ client.addTestRun(constants_js_1.STATUS.FAILED, {
160
+ rid: uid,
161
+ ...stripExampleFromTitle(title),
162
+ suite_title: suite.title,
163
+ test_id: testId,
164
+ error,
165
+ time: 0,
166
+ });
167
+ }
168
+ // output.stop();
169
+ });
170
+ event.dispatcher.on(event.test.after, test => {
171
+ if (test.state && test.state !== constants_js_1.STATUS.FAILED)
172
+ return;
173
+ if (test.err)
174
+ error = test.err;
175
+ const { uid, tags, title, artifacts } = test;
176
+ failedTests.push(uid || title);
177
+ const testObj = getTestAndMessage(title);
178
+ const files = [];
179
+ if (artifacts.screenshot)
180
+ files.push({ path: artifacts.screenshot, type: 'image/png' });
181
+ // todo: video must be uploaded later....
182
+ const logs = getTestLogs(test);
183
+ const manuallyAttachedArtifacts = index_js_1.services.artifacts.get(test.fullTitle());
184
+ const keyValues = index_js_1.services.keyValues.get(test.fullTitle());
185
+ const labels = index_js_1.services.labels.get(test.fullTitle());
186
+ index_js_1.services.setContext(null);
187
+ client.addTestRun(constants_js_1.STATUS.FAILED, {
188
+ ...stripExampleFromTitle(title),
189
+ rid: uid,
190
+ test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
191
+ suite_title: test.parent && test.parent.title,
192
+ error,
193
+ message: testObj.message,
194
+ time: getDuration(test),
195
+ files,
196
+ steps: global.testomatioDataStore?.steps?.join('\n') || null,
197
+ logs,
198
+ manuallyAttachedArtifacts,
199
+ meta: keyValues,
200
+ labels: labels,
201
+ });
202
+ debug('artifacts', artifacts);
203
+ for (const aid in artifacts) {
204
+ if (aid.startsWith('video'))
205
+ videos.push({ rid: uid, title, path: artifacts[aid], type: 'video/webm' });
206
+ if (aid.startsWith('trace'))
207
+ traces.push({ rid: uid, title, path: artifacts[aid], type: 'application/zip' });
208
+ }
209
+ // output.stop();
210
+ });
211
+ event.dispatcher.on(event.test.skipped, test => {
212
+ const { uid, tags, title } = test;
213
+ if (failedTests.includes(uid || title))
214
+ return;
215
+ const testObj = getTestAndMessage(title);
216
+ client.addTestRun(constants_js_1.STATUS.SKIPPED, {
217
+ rid: uid,
218
+ ...stripExampleFromTitle(title),
219
+ test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
220
+ suite_title: test.parent && test.parent.title,
221
+ message: testObj.message,
222
+ time: getDuration(test),
223
+ });
224
+ // output.stop();
225
+ });
226
+ event.dispatcher.on(event.step.started, step => {
227
+ stepShift = 0;
228
+ step.started = true;
229
+ stepStart = new Date();
230
+ });
231
+ event.dispatcher.on(event.step.finished, step => {
232
+ if (!step.started)
233
+ return;
234
+ let processingStep = step;
235
+ const metaSteps = [];
236
+ while (processingStep.metaStep) {
237
+ metaSteps.unshift(processingStep.metaStep);
238
+ processingStep = processingStep.metaStep;
239
+ }
240
+ const shift = metaSteps.length;
241
+ for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
242
+ if (currentMetaStep[i] !== metaSteps[i]) {
243
+ stepShift = 2 * i;
244
+ if (!metaSteps[i])
245
+ continue;
246
+ if (metaSteps[i].isBDD()) {
247
+ // output.push(repeat(stepShift) + pc.bold(metaSteps[i].toString()) + metaSteps[i].comment);
248
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + picocolors_1.default.bold(metaSteps[i].toString()) + metaSteps[i].comment);
249
+ }
250
+ else {
251
+ // output.push(repeat(stepShift) + pc.green.bold(metaSteps[i].toString()));
252
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + picocolors_1.default.green(picocolors_1.default.bold(metaSteps[i].toString())));
253
+ }
254
+ }
255
+ }
256
+ currentMetaStep = metaSteps;
257
+ stepShift = 2 * shift;
258
+ const durationMs = +new Date() - +stepStart;
259
+ let duration = '';
260
+ if (durationMs) {
261
+ duration = repeat(1) + picocolors_1.default.gray(`(${durationMs}ms)`);
262
+ }
263
+ if (step.status === constants_js_1.STATUS.FAILED) {
264
+ // output.push(repeat(stepShift) + pc.red(step.toString()) + duration);
265
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + picocolors_1.default.red(step.toString()) + duration);
266
+ }
267
+ else {
268
+ // output.push(repeat(stepShift) + step.toString() + duration);
269
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + step.toString() + duration);
270
+ }
271
+ });
272
+ event.dispatcher.on(event.step.comment, step => {
273
+ // output.push(pc.cyan.bold(step.toString()));
274
+ global.testomatioDataStore?.steps?.push(picocolors_1.default.cyan(picocolors_1.default.bold(step.toString())));
275
+ });
304
276
  }
305
-
306
277
  async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
307
- if (!attachments?.length) return;
308
-
309
- if (client.uploader.isEnabled) {
310
- console.log(APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
311
- }
312
-
313
- const promises = attachments.map(async attachment => {
314
- const { rid, title, path, type } = attachment;
315
- const file = { path, type, title };
316
-
317
- // we are storing file if upload is disabled
318
- if (!client.uploader.isEnabled) return client.uploader.storeUploadedFile(path, client.runId, rid, false);
319
-
320
- return client.addTestRun(undefined, {
321
- ...stripExampleFromTitle(title),
322
- rid,
323
- files: [file],
278
+ if (!attachments?.length)
279
+ return;
280
+ if (client.uploader.isEnabled) {
281
+ console.log(constants_js_1.APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
282
+ }
283
+ const promises = attachments.map(async (attachment) => {
284
+ const { rid, title, path, type } = attachment;
285
+ const file = { path, type, title };
286
+ // we are storing file if upload is disabled
287
+ if (!client.uploader.isEnabled)
288
+ return client.uploader.storeUploadedFile(path, client.runId, rid, false);
289
+ return client.addTestRun(undefined, {
290
+ ...stripExampleFromTitle(title),
291
+ rid,
292
+ files: [file],
293
+ });
324
294
  });
325
- });
326
-
327
- await Promise.all(promises);
295
+ await Promise.all(promises);
328
296
  }
329
-
330
297
  function getTestAndMessage(title) {
331
- const testObj = { message: '' };
332
- const testArr = title.split(/\s(\|\s\{.*?\})/);
333
- testObj.title = testArr[0];
334
-
335
- return testObj;
298
+ const testObj = { message: '' };
299
+ const testArr = title.split(/\s(\|\s\{.*?\})/);
300
+ testObj.title = testArr[0];
301
+ return testObj;
336
302
  }
337
-
338
303
  function stripExampleFromTitle(title) {
339
- const res = title.match(DATA_REGEXP);
340
- if (!res) return { title, example: null };
341
-
342
- const example = JSON.parse(res[1]);
343
- title = title.replace(DATA_REGEXP, '').trim();
344
-
345
- return { title, example };
304
+ const res = title.match(DATA_REGEXP);
305
+ if (!res)
306
+ return { title, example: null };
307
+ const example = JSON.parse(res[1]);
308
+ title = title.replace(DATA_REGEXP, '').trim();
309
+ return { title, example };
346
310
  }
347
-
348
311
  function repeat(num) {
349
- return ''.padStart(num, ' ');
312
+ return ''.padStart(num, ' ');
350
313
  }
351
-
352
314
  // TODO: think about moving to some common utils
353
315
  function getTestLogs(test) {
354
- const suiteLogsArr = services.logger.getLogs(test.parent.fullTitle());
355
- const suiteLogs = suiteLogsArr ? suiteLogsArr.join('\n').trim() : '';
356
- const testLogsArr = services.logger.getLogs(test.fullTitle());
357
- const testLogs = testLogsArr ? testLogsArr.join('\n').trim() : '';
358
-
359
- let logs = '';
360
- if (suiteLogs) {
361
- logs += `${chalk.bold('\t--- BeforeSuite ---')}\n${suiteLogs}`;
362
- }
363
- if (testLogs) {
364
- logs += `\n${chalk.bold('\t--- Test ---')}\n${testLogs}`;
365
- }
366
- return logs;
316
+ const suiteLogsArr = index_js_1.services.logger.getLogs(test.parent.fullTitle());
317
+ const suiteLogs = suiteLogsArr ? suiteLogsArr.join('\n').trim() : '';
318
+ const testLogsArr = index_js_1.services.logger.getLogs(test.fullTitle());
319
+ const testLogs = testLogsArr ? testLogsArr.join('\n').trim() : '';
320
+ let logs = '';
321
+ if (suiteLogs) {
322
+ logs += `${picocolors_1.default.bold('\t--- BeforeSuite ---')}\n${suiteLogs}`;
323
+ }
324
+ if (testLogs) {
325
+ logs += `\n${picocolors_1.default.bold('\t--- Test ---')}\n${testLogs}`;
326
+ }
327
+ return logs;
367
328
  }
368
-
369
329
  module.exports = CodeceptReporter;
330
+
331
+ module.exports.CodeceptReporter = CodeceptReporter;