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