@testomatio/reporter 1.6.0-beta-1-artifacts → 2.0.0-beta-esm

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/lib/adapter/codecept.js +288 -330
  2. package/lib/adapter/cucumber/current.js +195 -203
  3. package/lib/adapter/cucumber/legacy.js +130 -155
  4. package/lib/adapter/cucumber.js +5 -16
  5. package/lib/adapter/cypress-plugin/index.js +91 -105
  6. package/lib/adapter/jasmine/jasmine.js +63 -0
  7. package/lib/adapter/jasmine.js +54 -53
  8. package/lib/adapter/jest.js +97 -99
  9. package/lib/adapter/mocha/mocha.js +125 -0
  10. package/lib/adapter/mocha.js +111 -140
  11. package/lib/adapter/playwright.js +168 -200
  12. package/lib/adapter/vitest.js +144 -143
  13. package/lib/adapter/webdriver.js +113 -97
  14. package/lib/bin/reportXml.js +49 -49
  15. package/lib/bin/startTest.js +80 -97
  16. package/lib/client.js +344 -385
  17. package/lib/config.js +16 -21
  18. package/lib/constants.js +49 -43
  19. package/lib/data-storage.js +206 -188
  20. package/lib/fileUploader.js +245 -0
  21. package/lib/junit-adapter/adapter.js +17 -20
  22. package/lib/junit-adapter/csharp.js +18 -14
  23. package/lib/junit-adapter/index.js +27 -25
  24. package/lib/junit-adapter/java.js +41 -53
  25. package/lib/junit-adapter/javascript.js +30 -27
  26. package/lib/junit-adapter/python.js +38 -37
  27. package/lib/junit-adapter/ruby.js +11 -8
  28. package/lib/output.js +44 -52
  29. package/lib/package.json +1 -0
  30. package/lib/pipe/bitbucket.js +208 -227
  31. package/lib/pipe/csv.js +111 -124
  32. package/lib/pipe/github.js +184 -211
  33. package/lib/pipe/gitlab.js +164 -205
  34. package/lib/pipe/html.js +253 -312
  35. package/lib/pipe/index.js +83 -63
  36. package/lib/pipe/testomatio.js +391 -454
  37. package/lib/reporter-functions.js +16 -20
  38. package/lib/reporter.js +47 -17
  39. package/lib/services/artifacts.js +55 -51
  40. package/lib/services/index.js +14 -12
  41. package/lib/services/key-values.js +56 -53
  42. package/lib/services/logger.js +227 -245
  43. package/lib/utils/chalk.js +10 -0
  44. package/lib/utils/pipe_utils.js +91 -86
  45. package/lib/utils/utils.js +289 -273
  46. package/lib/xmlReader.js +480 -519
  47. package/package.json +57 -19
  48. package/src/adapter/codecept.js +369 -0
  49. package/src/adapter/cucumber/current.js +228 -0
  50. package/src/adapter/cucumber/legacy.js +158 -0
  51. package/src/adapter/cucumber.js +4 -0
  52. package/src/adapter/cypress-plugin/index.js +110 -0
  53. package/src/adapter/jasmine.js +60 -0
  54. package/src/adapter/jest.js +107 -0
  55. package/src/adapter/mocha.cjs +2 -0
  56. package/src/adapter/mocha.js +156 -0
  57. package/src/adapter/playwright.js +222 -0
  58. package/src/adapter/vitest.js +183 -0
  59. package/src/adapter/webdriver.js +111 -0
  60. package/src/bin/reportXml.js +67 -0
  61. package/src/bin/startTest.js +119 -0
  62. package/src/client.js +423 -0
  63. package/src/config.js +30 -0
  64. package/src/constants.js +49 -0
  65. package/src/data-storage.js +204 -0
  66. package/src/fileUploader.js +307 -0
  67. package/src/junit-adapter/adapter.js +23 -0
  68. package/src/junit-adapter/csharp.js +16 -0
  69. package/src/junit-adapter/index.js +28 -0
  70. package/src/junit-adapter/java.js +58 -0
  71. package/src/junit-adapter/javascript.js +31 -0
  72. package/src/junit-adapter/python.js +42 -0
  73. package/src/junit-adapter/ruby.js +10 -0
  74. package/src/output.js +57 -0
  75. package/src/pipe/bitbucket.js +254 -0
  76. package/src/pipe/csv.js +140 -0
  77. package/src/pipe/github.js +234 -0
  78. package/src/pipe/gitlab.js +229 -0
  79. package/src/pipe/html.js +366 -0
  80. package/src/pipe/index.js +73 -0
  81. package/src/pipe/testomatio.js +498 -0
  82. package/src/reporter-functions.js +44 -0
  83. package/src/reporter.cjs +22 -0
  84. package/src/reporter.js +24 -0
  85. package/src/services/artifacts.js +59 -0
  86. package/src/services/index.js +13 -0
  87. package/src/services/key-values.js +59 -0
  88. package/src/services/logger.js +314 -0
  89. package/src/template/emptyData.svg +23 -0
  90. package/src/template/testomatio.hbs +1421 -0
  91. package/src/utils/chalk.js +13 -0
  92. package/src/utils/pipe_utils.js +127 -0
  93. package/src/utils/utils.js +341 -0
  94. package/src/xmlReader.js +551 -0
  95. package/lib/bin/cli.js +0 -220
  96. package/lib/bin/uploadArtifacts.js +0 -91
  97. package/lib/uploader.js +0 -308
package/package.json CHANGED
@@ -1,22 +1,26 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "1.6.0-beta-1-artifacts",
3
+ "version": "2.0.0-beta-esm",
4
4
  "description": "Testomatio Reporter Client",
5
- "main": "./lib/reporter.js",
5
+ "engines": {
6
+ "node": ">=18"
7
+ },
6
8
  "typings": "typings/index.d.ts",
7
9
  "repository": "git@github.com:testomatio/reporter.git",
8
10
  "author": "Michael Bodnarchuk <davert@testomat.io>,Koushik Mohan <koushikmohan1996@gmail.com>",
9
11
  "license": "MIT",
12
+ "type": "module",
10
13
  "dependencies": {
11
14
  "@aws-sdk/client-s3": "^3.279.0",
12
15
  "@aws-sdk/lib-storage": "^3.279.0",
16
+ "@cucumber/cucumber": "^10.9.0",
13
17
  "@octokit/rest": "^19.0.5",
14
18
  "aws-sdk": "^2.1072.0",
15
19
  "axios": "^1.6.2",
16
20
  "axios-retry": "^3.9.1",
17
21
  "callsite-record": "^4.1.4",
18
- "chalk": "^4.1.0",
19
- "commander": "^12",
22
+ "chalk": "^5.3.0",
23
+ "commander": "^4.1.1",
20
24
  "cross-spawn": "^7.0.3",
21
25
  "csv-writer": "^1.6.0",
22
26
  "debug": "^4.3.4",
@@ -32,6 +36,7 @@
32
36
  "lodash.memoize": "^4.1.2",
33
37
  "lodash.merge": "^4.6.2",
34
38
  "minimatch": "^9.0.3",
39
+ "picocolors": "^1.0.1",
35
40
  "promise-retry": "^2.0.1",
36
41
  "strip-ansi": "^7.1.0",
37
42
  "uuid": "^9.0.0"
@@ -39,51 +44,84 @@
39
44
  "files": [
40
45
  "bin",
41
46
  "lib",
47
+ "src",
42
48
  "testcafe"
43
49
  ],
44
50
  "scripts": {
51
+ "@cucumber/cucumber": "^10.9.0",
45
52
  "clear-exportdir": "rm -rf export/",
46
53
  "pretty": "npx prettier --check .",
47
54
  "pretty:fix": "prettier --write .",
48
- "lint": "eslint lib",
49
- "lint:fix": "eslint lib --fix",
55
+ "lint": "eslint src",
56
+ "lint:fix": "eslint src --fix",
50
57
  "format": "npm run lint:fix && npm run pretty:fix",
51
58
  "test": "mocha tests/**",
52
59
  "init": "cd ./tests/adapter/examples/cucumber && npm i",
53
- "test:adapter": "mocha './tests/adapter/index.test.js'",
60
+ "test:adapter": "node node_modules/mocha/bin/mocha './tests/adapter/index.test.js'",
54
61
  "test:pipes": "mocha './tests/pipes/*_test.js'",
55
62
  "test:adapter:jest:example": "jest './tests/adapter/examples/jest/index.test.js' --config='./tests/adapter/examples/jest/jest.config.js'",
56
- "test:adapter:mocha:example": "mocha './tests/adapter/examples/mocha/index.test.js' --config='./tests/adapter/examples/mocha/mocha.config.js'",
57
- "test:adapter:jasmine:example": "./tests/adapter/examples/jasmine/passReporterOpts.sh && jasmine './tests/adapter/examples/jasmine/index.test.js' --reporter=./../../../lib/adapter/jasmine.js",
63
+ "test:adapter:mocha:example": "mocha './tests/adapter/examples/mocha/index.test.js' --config='./tests/adapter/examples/mocha/mocha.config.cjs'",
64
+ "test:adapter:jasmine:example": "jasmine './tests/adapter/examples/jasmine/index.test.js' --reporter=./lib/adapter/jasmine.js",
58
65
  "test:adapter:codecept:example": "codeceptjs run --config='./tests/adapter/examples/codecept/codecept.conf.js'",
59
66
  "test:adapter:cucumber:example": "cd ./tests/adapter/examples/cucumber && npx cucumber-js",
60
- "test:adapter:vitest:example": "vitest --config='./tests/adapter/examples/vitest/vitest.config.js'",
61
- "test:storage": "npx mocha tests-storage/artifact-storage.test.js && npx mocha tests-storage/data-storage.test.js && TESTOMATIO_INTERCEPT_CONSOLE_LOGS=true npx mocha tests-storage/logger.test.js && npx mocha tests-storage/logger-2.test.js && npx mocha tests-storage/reporter-functions.test.js"
67
+ "test:adapter:playwright:example": "npx playwright test --config='./tests/adapter/examples/playwright/playwright.config.ts'",
68
+ "test:adapter:vitest:example": "npx vitest --config='./tests/adapter/examples/vitest/vitest.config.ts'",
69
+ "test:storage": "npx mocha tests-storage/artifact-storage.test.js && npx mocha tests-storage/data-storage.test.js && TESTOMATIO_INTERCEPT_CONSOLE_LOGS=true npx mocha tests-storage/logger.test.js && npx mocha tests-storage/logger-2.test.js && npx mocha tests-storage/reporter-functions.test.js",
70
+ "build:cjs": "rm -rf ./cjs && tsc --module commonjs && npx tsx build/scripts/edit-js-files.js && npx tsx build/scripts/edit-package-json.js && chmod +x ./build/scripts/copy-tesmplate.sh && ./build/scripts/copy-tesmplate.sh"
62
71
  },
63
72
  "devDependencies": {
64
- "@cucumber/cucumber": "^9.3.0",
73
+ "@playwright/test": "^1.46.1",
65
74
  "@redocly/cli": "^1.0.0-beta.125",
75
+ "@types/cross-spawn": "^6.0.6",
76
+ "@types/cucumber": "^7.0.0",
77
+ "@types/mocha": "^10.0.7",
66
78
  "@wdio/reporter": "^7.16.13",
67
79
  "chai": "^4.3.6",
68
- "codeceptjs": "^3.5.11",
80
+ "codeceptjs": "^3.6.5",
69
81
  "cucumber": "^6.0.7",
70
- "eslint": "^8.7.0",
82
+ "eslint": "^8.57.0",
71
83
  "eslint-config-airbnb-base": "^15.0.0",
72
84
  "eslint-config-prettier": "^8.3.0",
73
85
  "eslint-plugin-import": "^2.25.4",
74
- "jasmine": "^3.10.0",
86
+ "jasmine": "^5.2.0",
75
87
  "jest": "^27.4.7",
76
88
  "jsdom": "^22.1.0",
77
89
  "mocha": "^9.2.0",
78
90
  "mock-http-server": "^1.4.5",
79
91
  "pino": "^8.15.0",
80
92
  "prettier": "^3.2.5",
81
- "puppeteer": "^22.15.0"
93
+ "puppeteer": "^22.15.0",
94
+ "typescript": "^5.5.4",
95
+ "vitest": "^1.6.0"
82
96
  },
83
97
  "bin": {
84
- "@testomatio/reporter": "./lib/bin/cli.js",
85
98
  "report-xml": "./lib/bin/reportXml.js",
86
- "start-test-run": "./lib/bin/startTest.js",
87
- "upload-artifacts": "./lib/bin/uploadArtifacts.js"
99
+ "start-test-run": "./lib/bin/startTest.js"
100
+ },
101
+ "exports": {
102
+ ".": {
103
+ "import": "./src/reporter.js",
104
+ "require": "./lib/reporter.js",
105
+ "types": "./index.d.ts"
106
+ },
107
+ "./lib/adapter/codecept/codecept.js": "./lib/adapter/codecept.js",
108
+ "./lib/adapter/codecept": "./lib/adapter/codecept.js",
109
+ "./codecept": "./lib/adapter/codecept.js",
110
+ "./lib/adapter/cucumber/cucumber.js": "./lib/adapter/cucumber/current.js",
111
+ "./cucumber": "./lib/adapter/cucumber/current.js",
112
+ "./lib/adapter/cypress-plugin": "./lib/adapter/cypress-plugin/index.js",
113
+ "./cypress-plugin": "./lib/adapter/cypress-plugin/index.js",
114
+ "./lib/adapter/jasmine.js": "./lib/adapter/jasmine.js",
115
+ "./jasmine": "./lib/adapter/jasmine.js",
116
+ "./lib/adapter/jest.js": "./lib/adapter/jest.js",
117
+ "./jest": "./lib/adapter/jest.js",
118
+ "./lib/adapter/mocha/mocha.js": "./lib/adapter/mocha.js",
119
+ "./mocha": "./lib/adapter/mocha.js",
120
+ "./lib/adapter/playwright.js": "./lib/adapter/playwright.js",
121
+ "./playwright": "./lib/adapter/playwright.js",
122
+ "./vitest": "./src/adapter/vitest.js",
123
+ "./lib/adapter/webdriver.js": "./lib/adapter/webdriver.js",
124
+ "./lib/adapter/webdriver": "./lib/adapter/webdriver.js",
125
+ "./webdriver": "./lib/adapter/webdriver.js"
88
126
  }
89
127
  }
@@ -0,0 +1,369 @@
1
+ import createDebugMessages from 'debug';
2
+ import pc from 'picocolors';
3
+ import TestomatClient from '../client.js';
4
+ import { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
5
+ import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
6
+ import { services } from '../services/index.js';
7
+ import { upload } from '../fileUploader.js';
8
+ // eslint-disable-next-line
9
+ import codeceptjs from 'codeceptjs';
10
+
11
+ const debug = createDebugMessages('@testomatio/reporter:adapter:codeceptjs');
12
+ // @ts-ignore
13
+ if (!global.codeceptjs) {
14
+ // @ts-ignore
15
+ global.codeceptjs = codeceptjs;
16
+ }
17
+
18
+ // @ts-ignore
19
+ const { event, recorder, codecept } = global.codeceptjs;
20
+
21
+ let currentMetaStep = [];
22
+ let error;
23
+ let stepShift = 0;
24
+
25
+ // const output = new Output({
26
+ // filterFn: stack => !stack.includes('codeceptjs/lib/output'), // output from codeceptjs
27
+ // });
28
+
29
+ let stepStart = new Date();
30
+
31
+ const MAJOR_VERSION = parseInt(codecept.version().match(/\d/)[0], 10);
32
+
33
+ const DATA_REGEXP = /[|\s]+?(\{".*\}|\[.*\])/;
34
+
35
+ if (MAJOR_VERSION < 3) {
36
+ console.log('🔴 This reporter works with CodeceptJS 3+, please update your tests');
37
+ }
38
+
39
+ function CodeceptReporter(config) {
40
+ let failedTests = [];
41
+ let videos = [];
42
+ let traces = [];
43
+ const reportTestPromises = [];
44
+
45
+ const testTimeMap = {};
46
+ const { apiKey } = config;
47
+
48
+ const getDuration = test => {
49
+ if (testTimeMap[test.id]) {
50
+ return Date.now() - testTimeMap[test.id];
51
+ }
52
+
53
+ return 0;
54
+ };
55
+
56
+ const client = new TestomatClient({ apiKey });
57
+
58
+ recorder.startUnlessRunning();
59
+
60
+ // Listening to events
61
+ event.dispatcher.on(event.all.before, () => {
62
+ // clear tmp dir
63
+ fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
64
+
65
+ // recorder.add('Creating new run', () => );
66
+ client.createRun();
67
+ videos = [];
68
+ traces = [];
69
+
70
+ if (!global.testomatioDataStore) global.testomatioDataStore = {};
71
+ });
72
+
73
+ let hookSteps = [];
74
+ let suiteHookRunning = false;
75
+
76
+ event.dispatcher.on(event.suite.before, suite => {
77
+ suiteHookRunning = true;
78
+ hookSteps = [];
79
+ global.testomatioDataStore.steps = [];
80
+
81
+ services.setContext(suite.fullTitle());
82
+ });
83
+
84
+ event.dispatcher.on(event.suite.after, () => {
85
+ services.setContext(null);
86
+ });
87
+
88
+ event.dispatcher.on(event.hook.started, () => {
89
+ // global.testomatioDataStore.steps = [];
90
+ });
91
+
92
+ event.dispatcher.on(event.hook.passed, () => {
93
+ if (suiteHookRunning) {
94
+ hookSteps.push(...global.testomatioDataStore.steps);
95
+ services.setContext(null);
96
+ }
97
+ });
98
+
99
+ event.dispatcher.on(event.hook.failed, () => {
100
+ if (suiteHookRunning) {
101
+ hookSteps.push(...global.testomatioDataStore.steps);
102
+ services.setContext(null);
103
+ }
104
+ });
105
+
106
+ event.dispatcher.on(event.test.before, test => {
107
+ suiteHookRunning = false;
108
+ global.testomatioDataStore.steps = [];
109
+
110
+ recorder.add(() => {
111
+ currentMetaStep = [];
112
+ // output.reset();
113
+ // output.start();
114
+ stepShift = 0;
115
+ });
116
+
117
+ if (!global.testomatioDataStore) global.testomatioDataStore = {};
118
+ // reset steps
119
+ global.testomatioDataStore.steps = [];
120
+
121
+ services.setContext(test.fullTitle());
122
+ });
123
+
124
+ event.dispatcher.on(event.test.started, test => {
125
+ services.setContext(test.fullTitle());
126
+
127
+ testTimeMap[test.id] = Date.now();
128
+ // start logging
129
+ });
130
+
131
+ event.dispatcher.on(event.all.result, async () => {
132
+ debug('waiting for all tests to be reported');
133
+ // all tests were reported and we can upload videos
134
+ await Promise.all(reportTestPromises);
135
+
136
+ if (upload.isArtifactsEnabled()) {
137
+ await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
138
+ await uploadAttachments(client, traces, '📁 Uploading', 'trace');
139
+ }
140
+
141
+ const status = failedTests.length === 0 ? STATUS.PASSED : STATUS.FAILED;
142
+ // @ts-ignore
143
+ client.updateRunStatus(status);
144
+ });
145
+
146
+ event.dispatcher.on(event.test.passed, test => {
147
+ const { id, tags, title } = test;
148
+ if (id && failedTests.includes(id)) {
149
+ failedTests = failedTests.filter(failed => id !== failed);
150
+ }
151
+ const testObj = getTestAndMessage(title);
152
+
153
+ const logs = getTestLogs(test);
154
+ const manuallyAttachedArtifacts = services.artifacts.get(test.fullTitle());
155
+ const keyValues = services.keyValues.get(test.fullTitle());
156
+ services.setContext(null);
157
+
158
+ client.addTestRun(STATUS.PASSED, {
159
+ ...stripExampleFromTitle(title),
160
+ rid: id,
161
+ suite_title: test.parent && test.parent.title,
162
+ message: testObj.message,
163
+ time: getDuration(test),
164
+ steps: global.testomatioDataStore.steps.join('\n') || null,
165
+ test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
166
+ logs,
167
+ manuallyAttachedArtifacts,
168
+ meta: keyValues,
169
+ });
170
+ // output.stop();
171
+ });
172
+
173
+ event.dispatcher.on(event.test.failed, (test, err) => {
174
+ error = err;
175
+ });
176
+
177
+ event.dispatcher.on(event.hook.failed, (suite, err) => {
178
+ error = err;
179
+
180
+ if (!suite) return;
181
+ if (!suite.tests) return;
182
+ for (const test of suite.tests) {
183
+ const { id, tags, title } = test;
184
+ failedTests.push(id || title);
185
+ const testId = getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`);
186
+
187
+ client.addTestRun(STATUS.FAILED, {
188
+ rid: id,
189
+ ...stripExampleFromTitle(title),
190
+ suite_title: suite.title,
191
+ test_id: testId,
192
+ error,
193
+ time: 0,
194
+ });
195
+ }
196
+ // output.stop();
197
+ });
198
+
199
+ event.dispatcher.on(event.test.after, test => {
200
+ if (test.state && test.state !== STATUS.FAILED) return;
201
+ if (test.err) error = test.err;
202
+ const { id, tags, title, artifacts } = test;
203
+ failedTests.push(id || title);
204
+ const testObj = getTestAndMessage(title);
205
+
206
+ const files = [];
207
+ if (artifacts.screenshot) files.push({ path: artifacts.screenshot, type: 'image/png' });
208
+ // todo: video must be uploaded later....
209
+
210
+ const logs = getTestLogs(test);
211
+ const manuallyAttachedArtifacts = services.artifacts.get(test.fullTitle());
212
+ const keyValues = services.keyValues.get(test.fullTitle());
213
+ services.setContext(null);
214
+
215
+ client.addTestRun(STATUS.FAILED, {
216
+ ...stripExampleFromTitle(title),
217
+ rid: id,
218
+ test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
219
+ suite_title: test.parent && test.parent.title,
220
+ error,
221
+ message: testObj.message,
222
+ time: getDuration(test),
223
+ files,
224
+ steps: global.testomatioDataStore?.steps?.join('\n') || null,
225
+ logs,
226
+ manuallyAttachedArtifacts,
227
+ meta: keyValues,
228
+ });
229
+
230
+ debug('artifacts', artifacts);
231
+
232
+ for (const aid in artifacts) {
233
+ if (aid.startsWith('video')) videos.push({ rid: id, title, path: artifacts[aid], type: 'video/webm' });
234
+ if (aid.startsWith('trace')) traces.push({ rid: id, title, path: artifacts[aid], type: 'application/zip' });
235
+ }
236
+
237
+ // output.stop();
238
+ });
239
+
240
+ event.dispatcher.on(event.test.skipped, test => {
241
+ const { id, tags, title } = test;
242
+ if (failedTests.includes(id || title)) return;
243
+
244
+ const testObj = getTestAndMessage(title);
245
+ client.addTestRun(STATUS.SKIPPED, {
246
+ rid: id,
247
+ ...stripExampleFromTitle(title),
248
+ test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
249
+ suite_title: test.parent && test.parent.title,
250
+ message: testObj.message,
251
+ time: getDuration(test),
252
+ });
253
+ // output.stop();
254
+ });
255
+
256
+ event.dispatcher.on(event.step.started, step => {
257
+ stepShift = 0;
258
+ step.started = true;
259
+ stepStart = new Date();
260
+ });
261
+
262
+ event.dispatcher.on(event.step.finished, step => {
263
+ if (!step.started) return;
264
+ let processingStep = step;
265
+ const metaSteps = [];
266
+ while (processingStep.metaStep) {
267
+ metaSteps.unshift(processingStep.metaStep);
268
+ processingStep = processingStep.metaStep;
269
+ }
270
+ const shift = metaSteps.length;
271
+
272
+ for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
273
+ if (currentMetaStep[i] !== metaSteps[i]) {
274
+ stepShift = 2 * i;
275
+ // eslint-disable-next-line no-continue
276
+ if (!metaSteps[i]) continue;
277
+ if (metaSteps[i].isBDD()) {
278
+ // output.push(repeat(stepShift) + pc.bold(metaSteps[i].toString()) + metaSteps[i].comment);
279
+ global.testomatioDataStore?.steps?.push(
280
+ repeat(stepShift) + pc.bold(metaSteps[i].toString()) + metaSteps[i].comment,
281
+ );
282
+ } else {
283
+ // output.push(repeat(stepShift) + pc.green.bold(metaSteps[i].toString()));
284
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + pc.green(pc.bold(metaSteps[i].toString())));
285
+ }
286
+ }
287
+ }
288
+ currentMetaStep = metaSteps;
289
+ stepShift = 2 * shift;
290
+
291
+ const durationMs = +new Date() - +stepStart;
292
+ let duration = '';
293
+ if (durationMs) {
294
+ duration = repeat(1) + pc.gray(`(${durationMs}ms)`);
295
+ }
296
+
297
+ if (step.status === STATUS.FAILED) {
298
+ // output.push(repeat(stepShift) + pc.red(step.toString()) + duration);
299
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + pc.red(step.toString()) + duration);
300
+ } else {
301
+ // output.push(repeat(stepShift) + step.toString() + duration);
302
+ global.testomatioDataStore?.steps?.push(repeat(stepShift) + step.toString() + duration);
303
+ }
304
+ });
305
+
306
+ event.dispatcher.on(event.step.comment, step => {
307
+ // output.push(pc.cyan.bold(step.toString()));
308
+ global.testomatioDataStore?.steps?.push(pc.cyan(pc.bold(step.toString())));
309
+ });
310
+ }
311
+
312
+ async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
313
+ if (!attachments?.length) return;
314
+
315
+ console.log(APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
316
+
317
+ const promises = attachments.map(async attachment => {
318
+ const { rid, title, path, type } = attachment;
319
+ const file = { path, type, title };
320
+ return client.addTestRun(undefined, {
321
+ ...stripExampleFromTitle(title),
322
+ rid,
323
+ files: [file],
324
+ });
325
+ });
326
+
327
+ await Promise.all(promises);
328
+ }
329
+
330
+ function getTestAndMessage(title) {
331
+ const testObj = { message: '' };
332
+ const testArr = title.split(/\s(\|\s\{.*?\})/);
333
+ testObj.title = testArr[0];
334
+
335
+ return testObj;
336
+ }
337
+
338
+ 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 };
346
+ }
347
+
348
+ function repeat(num) {
349
+ return ''.padStart(num, ' ');
350
+ }
351
+
352
+ // TODO: think about moving to some common utils
353
+ 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 += `${pc.bold('\t--- BeforeSuite ---')}\n${suiteLogs}`;
362
+ }
363
+ if (testLogs) {
364
+ logs += `\n${pc.bold('\t--- Test ---')}\n${testLogs}`;
365
+ }
366
+ return logs;
367
+ }
368
+
369
+ export { CodeceptReporter };