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

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