@testomatio/reporter 2.0.0-beta-esm → 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 (115) hide show
  1. package/lib/adapter/codecept.d.ts +2 -0
  2. package/lib/adapter/codecept.js +31 -24
  3. package/lib/adapter/cucumber/current.d.ts +14 -0
  4. package/lib/adapter/cucumber/legacy.d.ts +0 -0
  5. package/lib/adapter/cucumber.d.ts +2 -0
  6. package/lib/adapter/cypress-plugin/index.d.ts +2 -0
  7. package/lib/adapter/cypress-plugin/index.js +11 -9
  8. package/lib/adapter/jasmine.d.ts +11 -0
  9. package/lib/adapter/jest.d.ts +13 -0
  10. package/lib/adapter/mocha.d.ts +2 -0
  11. package/lib/adapter/mocha.js +4 -3
  12. package/lib/adapter/playwright.d.ts +14 -0
  13. package/lib/adapter/playwright.js +58 -33
  14. package/lib/adapter/vitest.d.ts +35 -0
  15. package/lib/adapter/vitest.js +6 -6
  16. package/lib/adapter/webdriver.d.ts +24 -0
  17. package/lib/adapter/webdriver.js +34 -6
  18. package/lib/bin/cli.d.ts +2 -0
  19. package/lib/bin/cli.js +228 -0
  20. package/lib/bin/reportXml.d.ts +2 -0
  21. package/lib/bin/reportXml.js +11 -9
  22. package/lib/bin/startTest.d.ts +2 -0
  23. package/lib/bin/startTest.js +9 -5
  24. package/lib/bin/uploadArtifacts.d.ts +2 -0
  25. package/lib/bin/uploadArtifacts.js +81 -0
  26. package/lib/client.d.ts +76 -0
  27. package/lib/client.js +111 -45
  28. package/lib/config.d.ts +1 -0
  29. package/lib/constants.d.ts +25 -0
  30. package/lib/constants.js +5 -1
  31. package/lib/data-storage.d.ts +34 -0
  32. package/lib/data-storage.js +2 -2
  33. package/lib/junit-adapter/adapter.d.ts +9 -0
  34. package/lib/junit-adapter/csharp.d.ts +4 -0
  35. package/lib/junit-adapter/index.d.ts +3 -0
  36. package/lib/junit-adapter/java.d.ts +5 -0
  37. package/lib/junit-adapter/javascript.d.ts +4 -0
  38. package/lib/junit-adapter/python.d.ts +5 -0
  39. package/lib/junit-adapter/ruby.d.ts +4 -0
  40. package/lib/output.d.ts +11 -0
  41. package/lib/package.json +3 -1
  42. package/lib/pipe/bitbucket.d.ts +23 -0
  43. package/lib/pipe/bitbucket.js +2 -2
  44. package/lib/pipe/csv.d.ts +47 -0
  45. package/lib/pipe/csv.js +2 -2
  46. package/lib/pipe/debug.d.ts +29 -0
  47. package/lib/pipe/debug.js +108 -0
  48. package/lib/pipe/github.d.ts +30 -0
  49. package/lib/pipe/github.js +2 -2
  50. package/lib/pipe/gitlab.d.ts +23 -0
  51. package/lib/pipe/gitlab.js +2 -2
  52. package/lib/pipe/html.d.ts +34 -0
  53. package/lib/pipe/html.js +8 -1
  54. package/lib/pipe/index.d.ts +1 -0
  55. package/lib/pipe/index.js +3 -3
  56. package/lib/pipe/testomatio.d.ts +70 -0
  57. package/lib/pipe/testomatio.js +50 -30
  58. package/lib/reporter-functions.d.ts +34 -0
  59. package/lib/reporter-functions.js +17 -7
  60. package/lib/reporter.d.ts +232 -0
  61. package/lib/reporter.js +19 -33
  62. package/lib/services/artifacts.d.ts +33 -0
  63. package/lib/services/index.d.ts +9 -0
  64. package/lib/services/key-values.d.ts +27 -0
  65. package/lib/services/key-values.js +1 -1
  66. package/lib/services/logger.d.ts +64 -0
  67. package/lib/template/testomatio.hbs +651 -1366
  68. package/lib/uploader.d.ts +60 -0
  69. package/lib/uploader.js +312 -0
  70. package/lib/utils/pipe_utils.d.ts +41 -0
  71. package/lib/utils/pipe_utils.js +3 -5
  72. package/lib/utils/utils.d.ts +45 -0
  73. package/lib/utils/utils.js +69 -2
  74. package/lib/xmlReader.d.ts +92 -0
  75. package/lib/xmlReader.js +22 -12
  76. package/package.json +15 -9
  77. package/src/adapter/codecept.js +30 -24
  78. package/src/adapter/cypress-plugin/index.js +5 -3
  79. package/src/adapter/mocha.cjs +1 -1
  80. package/src/adapter/mocha.js +4 -3
  81. package/src/adapter/playwright.js +59 -31
  82. package/src/adapter/vitest.js +6 -6
  83. package/src/adapter/webdriver.js +41 -10
  84. package/src/bin/cli.js +280 -0
  85. package/src/bin/reportXml.js +15 -8
  86. package/src/bin/startTest.js +7 -3
  87. package/src/bin/uploadArtifacts.js +90 -0
  88. package/src/client.js +137 -56
  89. package/src/constants.js +5 -1
  90. package/src/data-storage.js +2 -2
  91. package/src/pipe/bitbucket.js +2 -2
  92. package/src/pipe/csv.js +3 -3
  93. package/src/pipe/debug.js +104 -0
  94. package/src/pipe/github.js +2 -3
  95. package/src/pipe/gitlab.js +6 -6
  96. package/src/pipe/html.js +11 -3
  97. package/src/pipe/index.js +5 -7
  98. package/src/pipe/testomatio.js +72 -67
  99. package/src/reporter-functions.js +18 -7
  100. package/src/reporter.cjs_decprecated +21 -0
  101. package/src/reporter.js +20 -11
  102. package/src/services/key-values.js +1 -1
  103. package/src/services/logger.js +4 -2
  104. package/src/template/testomatio.hbs +651 -1366
  105. package/src/uploader.js +371 -0
  106. package/src/utils/pipe_utils.js +4 -12
  107. package/src/utils/utils.js +48 -6
  108. package/src/xmlReader.js +26 -15
  109. package/lib/adapter/jasmine/jasmine.js +0 -63
  110. package/lib/adapter/mocha/mocha.js +0 -125
  111. package/lib/fileUploader.js +0 -245
  112. package/lib/utils/chalk.js +0 -10
  113. package/src/fileUploader.js +0 -307
  114. package/src/reporter.cjs +0 -22
  115. package/src/utils/chalk.js +0 -13
package/lib/xmlReader.js CHANGED
@@ -15,12 +15,12 @@ const utils_js_1 = require("./utils/utils.js");
15
15
  const index_js_1 = require("./pipe/index.js");
16
16
  const index_js_2 = __importDefault(require("./junit-adapter/index.js"));
17
17
  const config_js_1 = require("./config.js");
18
- const fileUploader_js_1 = require("./fileUploader.js");
18
+ const uploader_js_1 = require("./uploader.js");
19
19
  // @ts-ignore this line will be removed in compiled code, because __dirname is defined in commonjs
20
20
  const debug = (0, debug_1.default)('@testomatio/reporter:xml');
21
21
  const ridRunId = (0, crypto_1.randomUUID)();
22
22
  const TESTOMATIO_URL = process.env.TESTOMATIO_URL || 'https://app.testomat.io';
23
- const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } = process.env;
23
+ const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN, TESTOMATIO_MARK_DETACHED } = process.env;
24
24
  const options = {
25
25
  ignoreDeclaration: true,
26
26
  ignoreAttributes: false,
@@ -37,6 +37,7 @@ class XmlReader {
37
37
  title: TESTOMATIO_TITLE,
38
38
  env: TESTOMATIO_ENV,
39
39
  group_title: TESTOMATIO_RUNGROUP_TITLE,
40
+ detach: TESTOMATIO_MARK_DETACHED,
40
41
  // batch uploading is implemented for xml already
41
42
  isBatchEnabled: false,
42
43
  };
@@ -51,7 +52,7 @@ class XmlReader {
51
52
  this.tests = [];
52
53
  this.stats = {};
53
54
  this.stats.language = opts.lang?.toLowerCase();
54
- this.filesToUpload = {};
55
+ this.uploader = new uploader_js_1.S3Uploader();
55
56
  // @ts-ignore
56
57
  const packageJsonPath = path_1.default.resolve(__dirname, '..', 'package.json');
57
58
  this.version = JSON.parse(fs_1.default.readFileSync(packageJsonPath).toString()).version;
@@ -105,16 +106,24 @@ class XmlReader {
105
106
  const resultTests = processTestSuite(testsuite);
106
107
  const hasFailures = resultTests.filter(t => t.status === 'failed').length > 0;
107
108
  const status = failures > 0 || errors > 0 || hasFailures ? 'failed' : 'passed';
109
+ const time = testsuite.time || 0;
110
+ // debug('time', jsonSuite, time)
111
+ if (time) {
112
+ if (!this.stats.duration)
113
+ this.stats.duration = 0;
114
+ this.stats.duration += parseFloat(time);
115
+ }
108
116
  this.tests = this.tests.concat(resultTests);
109
117
  return {
110
- status,
111
118
  create_tests: true,
119
+ duration: parseFloat(time),
120
+ failed_count: parseInt(failures, 10),
112
121
  name,
113
- tests_count: parseInt(tests, 10),
114
122
  passed_count: parseInt(tests, 10) - parseInt(failures, 10),
115
- failed_count: parseInt(failures, 10),
116
123
  skipped_count: 0,
124
+ status,
117
125
  tests: resultTests,
126
+ tests_count: parseInt(tests, 10),
118
127
  };
119
128
  }
120
129
  processNUnit(jsonSuite) {
@@ -266,6 +275,7 @@ class XmlReader {
266
275
  calculateStats() {
267
276
  this.stats = {
268
277
  ...this.stats,
278
+ detach: this.requestParams.detach,
269
279
  status: 'passed',
270
280
  create_tests: true,
271
281
  tests_count: 0,
@@ -355,7 +365,7 @@ class XmlReader {
355
365
  if (!files.length)
356
366
  continue;
357
367
  const runId = this.runId || this.store.runId || Date.now().toString();
358
- test.artifacts = await Promise.all(files.map(f => fileUploader_js_1.upload.uploadFileByPath(f, runId)));
368
+ test.artifacts = await Promise.all(files.map(f => this.uploader.uploadFileByPath(f, [runId])));
359
369
  console.log(constants_js_1.APP_PREFIX, `🗄️ Uploaded ${picocolors_1.default.bold(`${files.length} artifacts`)} for test ${test.title}`);
360
370
  }
361
371
  }
@@ -369,7 +379,9 @@ class XmlReader {
369
379
  };
370
380
  debug('Run', runParams);
371
381
  this.pipes = this.pipes || (await this.pipesPromise);
372
- return Promise.all(this.pipes.map(p => p.createRun(runParams)));
382
+ const run = await Promise.all(this.pipes.map(p => p.createRun(runParams)));
383
+ this.uploader.checkEnabled();
384
+ return run;
373
385
  }
374
386
  async uploadData() {
375
387
  await this.uploadArtifacts();
@@ -378,16 +390,14 @@ class XmlReader {
378
390
  this.fetchSourceCode();
379
391
  this.formatErrors();
380
392
  this.formatTests();
381
- debug('Uploading data', {
382
- ...this.stats,
383
- tests: this.tests,
384
- });
385
393
  const dataString = {
386
394
  ...this.stats,
387
395
  api_key: this.requestParams.apiKey,
388
396
  status: 'finished',
397
+ duration: this.stats.duration,
389
398
  tests: this.tests,
390
399
  };
400
+ debug('Uploading data', dataString);
391
401
  this.pipes = this.pipes || (await this.pipesPromise);
392
402
  return Promise.all(this.pipes.map(p => p.finishRun(dataString)));
393
403
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "2.0.0-beta-esm",
3
+ "version": "2.0.1-beta-esm",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -19,14 +19,14 @@
19
19
  "axios": "^1.6.2",
20
20
  "axios-retry": "^3.9.1",
21
21
  "callsite-record": "^4.1.4",
22
- "chalk": "^5.3.0",
23
- "commander": "^4.1.1",
22
+ "commander": "^12",
24
23
  "cross-spawn": "^7.0.3",
25
24
  "csv-writer": "^1.6.0",
26
25
  "debug": "^4.3.4",
27
26
  "dotenv": "^16.0.1",
28
27
  "fast-xml-parser": "^4.4.1",
29
28
  "file-url": "3.0.0",
29
+ "filesize": "^10.1.6",
30
30
  "glob": "^10.3",
31
31
  "handlebars": "^4.7.8",
32
32
  "has-flag": "^5.0.1",
@@ -37,6 +37,7 @@
37
37
  "lodash.merge": "^4.6.2",
38
38
  "minimatch": "^9.0.3",
39
39
  "picocolors": "^1.0.1",
40
+ "pretty-ms": "^7.0.1",
40
41
  "promise-retry": "^2.0.1",
41
42
  "strip-ansi": "^7.1.0",
42
43
  "uuid": "^9.0.0"
@@ -67,10 +68,11 @@
67
68
  "test:adapter:playwright:example": "npx playwright test --config='./tests/adapter/examples/playwright/playwright.config.ts'",
68
69
  "test:adapter:vitest:example": "npx vitest --config='./tests/adapter/examples/vitest/vitest.config.ts'",
69
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",
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"
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"
71
73
  },
72
74
  "devDependencies": {
73
- "@playwright/test": "^1.46.1",
75
+ "@playwright/test": "^1.49.1",
74
76
  "@redocly/cli": "^1.0.0-beta.125",
75
77
  "@types/cross-spawn": "^6.0.6",
76
78
  "@types/cucumber": "^7.0.0",
@@ -95,14 +97,16 @@
95
97
  "vitest": "^1.6.0"
96
98
  },
97
99
  "bin": {
100
+ "@testomatio/reporter": "./lib/bin/cli.js",
98
101
  "report-xml": "./lib/bin/reportXml.js",
99
- "start-test-run": "./lib/bin/startTest.js"
102
+ "start-test-run": "./lib/bin/startTest.js",
103
+ "upload-artifacts": "./lib/bin/uploadArtifacts.js"
100
104
  },
101
105
  "exports": {
102
106
  ".": {
103
107
  "import": "./src/reporter.js",
104
108
  "require": "./lib/reporter.js",
105
- "types": "./index.d.ts"
109
+ "types": "./types/types.d.ts"
106
110
  },
107
111
  "./lib/adapter/codecept/codecept.js": "./lib/adapter/codecept.js",
108
112
  "./lib/adapter/codecept": "./lib/adapter/codecept.js",
@@ -111,6 +115,7 @@
111
115
  "./cucumber": "./lib/adapter/cucumber/current.js",
112
116
  "./lib/adapter/cypress-plugin": "./lib/adapter/cypress-plugin/index.js",
113
117
  "./cypress-plugin": "./lib/adapter/cypress-plugin/index.js",
118
+ "./cypress": "./lib/adapter/cypress-plugin/index.js",
114
119
  "./lib/adapter/jasmine.js": "./lib/adapter/jasmine.js",
115
120
  "./jasmine": "./lib/adapter/jasmine.js",
116
121
  "./lib/adapter/jest.js": "./lib/adapter/jest.js",
@@ -119,9 +124,10 @@
119
124
  "./mocha": "./lib/adapter/mocha.js",
120
125
  "./lib/adapter/playwright.js": "./lib/adapter/playwright.js",
121
126
  "./playwright": "./lib/adapter/playwright.js",
122
- "./vitest": "./src/adapter/vitest.js",
127
+ "./vitest": "./lib/adapter/vitest.js",
123
128
  "./lib/adapter/webdriver.js": "./lib/adapter/webdriver.js",
124
129
  "./lib/adapter/webdriver": "./lib/adapter/webdriver.js",
125
- "./webdriver": "./lib/adapter/webdriver.js"
130
+ "./webdriver": "./lib/adapter/webdriver.js",
131
+ "./wdio": "./lib/adapter/webdriver.js"
126
132
  }
127
133
  }
@@ -4,7 +4,6 @@ import TestomatClient from '../client.js';
4
4
  import { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
5
5
  import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
6
6
  import { services } from '../services/index.js';
7
- import { upload } from '../fileUploader.js';
8
7
  // eslint-disable-next-line
9
8
  import codeceptjs from 'codeceptjs';
10
9
 
@@ -46,8 +45,9 @@ function CodeceptReporter(config) {
46
45
  const { apiKey } = config;
47
46
 
48
47
  const getDuration = test => {
49
- if (testTimeMap[test.id]) {
50
- return Date.now() - testTimeMap[test.id];
48
+ if (!test.uid) return 0;
49
+ if (testTimeMap[test.uid]) {
50
+ return Date.now() - testTimeMap[test.uid];
51
51
  }
52
52
 
53
53
  return 0;
@@ -125,7 +125,8 @@ function CodeceptReporter(config) {
125
125
  services.setContext(test.fullTitle());
126
126
 
127
127
  testTimeMap[test.id] = Date.now();
128
- // start logging
128
+ if (!test.uid) return;
129
+ testTimeMap[test.uid] = Date.now();
129
130
  });
130
131
 
131
132
  event.dispatcher.on(event.all.result, async () => {
@@ -133,10 +134,8 @@ function CodeceptReporter(config) {
133
134
  // all tests were reported and we can upload videos
134
135
  await Promise.all(reportTestPromises);
135
136
 
136
- if (upload.isArtifactsEnabled()) {
137
- await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
138
- await uploadAttachments(client, traces, '📁 Uploading', 'trace');
139
- }
137
+ await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
138
+ await uploadAttachments(client, traces, '📁 Uploading', 'trace');
140
139
 
141
140
  const status = failedTests.length === 0 ? STATUS.PASSED : STATUS.FAILED;
142
141
  // @ts-ignore
@@ -144,9 +143,9 @@ function CodeceptReporter(config) {
144
143
  });
145
144
 
146
145
  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);
146
+ const { uid, tags, title } = test;
147
+ if (uid && failedTests.includes(uid)) {
148
+ failedTests = failedTests.filter(failed => uid !== failed);
150
149
  }
151
150
  const testObj = getTestAndMessage(title);
152
151
 
@@ -157,7 +156,7 @@ function CodeceptReporter(config) {
157
156
 
158
157
  client.addTestRun(STATUS.PASSED, {
159
158
  ...stripExampleFromTitle(title),
160
- rid: id,
159
+ rid: uid,
161
160
  suite_title: test.parent && test.parent.title,
162
161
  message: testObj.message,
163
162
  time: getDuration(test),
@@ -180,12 +179,12 @@ function CodeceptReporter(config) {
180
179
  if (!suite) return;
181
180
  if (!suite.tests) return;
182
181
  for (const test of suite.tests) {
183
- const { id, tags, title } = test;
184
- failedTests.push(id || title);
182
+ const { uid, tags, title } = test;
183
+ failedTests.push(uid || title);
185
184
  const testId = getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`);
186
185
 
187
186
  client.addTestRun(STATUS.FAILED, {
188
- rid: id,
187
+ rid: uid,
189
188
  ...stripExampleFromTitle(title),
190
189
  suite_title: suite.title,
191
190
  test_id: testId,
@@ -199,8 +198,8 @@ function CodeceptReporter(config) {
199
198
  event.dispatcher.on(event.test.after, test => {
200
199
  if (test.state && test.state !== STATUS.FAILED) return;
201
200
  if (test.err) error = test.err;
202
- const { id, tags, title, artifacts } = test;
203
- failedTests.push(id || title);
201
+ const { uid, tags, title, artifacts } = test;
202
+ failedTests.push(uid || title);
204
203
  const testObj = getTestAndMessage(title);
205
204
 
206
205
  const files = [];
@@ -214,7 +213,7 @@ function CodeceptReporter(config) {
214
213
 
215
214
  client.addTestRun(STATUS.FAILED, {
216
215
  ...stripExampleFromTitle(title),
217
- rid: id,
216
+ rid: uid,
218
217
  test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
219
218
  suite_title: test.parent && test.parent.title,
220
219
  error,
@@ -230,20 +229,20 @@ function CodeceptReporter(config) {
230
229
  debug('artifacts', artifacts);
231
230
 
232
231
  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' });
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' });
235
234
  }
236
235
 
237
236
  // output.stop();
238
237
  });
239
238
 
240
239
  event.dispatcher.on(event.test.skipped, test => {
241
- const { id, tags, title } = test;
242
- if (failedTests.includes(id || title)) return;
240
+ const { uid, tags, title } = test;
241
+ if (failedTests.includes(uid || title)) return;
243
242
 
244
243
  const testObj = getTestAndMessage(title);
245
244
  client.addTestRun(STATUS.SKIPPED, {
246
- rid: id,
245
+ rid: uid,
247
246
  ...stripExampleFromTitle(title),
248
247
  test_id: getTestomatIdFromTestTitle(`${title} ${tags?.join(' ')}`),
249
248
  suite_title: test.parent && test.parent.title,
@@ -312,11 +311,17 @@ function CodeceptReporter(config) {
312
311
  async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
313
312
  if (!attachments?.length) return;
314
313
 
315
- console.log(APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
314
+ if (client.uploader.isEnabled) {
315
+ console.log(APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
316
+ }
316
317
 
317
318
  const promises = attachments.map(async attachment => {
318
319
  const { rid, title, path, type } = attachment;
319
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
+
320
325
  return client.addTestRun(undefined, {
321
326
  ...stripExampleFromTitle(title),
322
327
  rid,
@@ -367,3 +372,4 @@ function getTestLogs(test) {
367
372
  }
368
373
 
369
374
  export { CodeceptReporter };
375
+ export default CodeceptReporter;
@@ -1,7 +1,7 @@
1
1
  import { STATUS } from '../../constants.js';
2
2
  import { getTestomatIdFromTestTitle, parseSuite } from '../../utils/utils.js';
3
3
  import TestomatClient from '../../client.js';
4
- import {config} from '../../config.js';
4
+ import { config } from '../../config.js';
5
5
 
6
6
  const testomatioReporter = on => {
7
7
  if (!config.TESTOMATIO) {
@@ -50,7 +50,8 @@ const testomatioReporter = on => {
50
50
  };
51
51
  }
52
52
 
53
- const formattedError = error ? {
53
+ const formattedError = error
54
+ ? {
54
55
  message: error.message,
55
56
  name: error.name,
56
57
  inspect:
@@ -59,7 +60,8 @@ const testomatioReporter = on => {
59
60
  function () {
60
61
  return this.message;
61
62
  },
62
- } : undefined;
63
+ }
64
+ : undefined;
63
65
 
64
66
  const screenshots = Array.isArray(results.screenshots)
65
67
  ? results.screenshots
@@ -1,2 +1,2 @@
1
- const MochaReporter = require('../../../lib/adapter/mocha/mocha.js');
1
+ const MochaReporter = require('../../../lib/adapter/mocha.js');
2
2
  module.exports = MochaReporter;
@@ -33,6 +33,7 @@ function MochaReporter(runner, opts) {
33
33
  runner.on(EVENT_RUN_BEGIN, () => {
34
34
  client.createRun();
35
35
 
36
+ // clear dir with artifacts/logs
36
37
  fileSystem.clearDir(TESTOMAT_TMP_STORAGE_DIR);
37
38
  });
38
39
 
@@ -66,7 +67,7 @@ function MochaReporter(runner, opts) {
66
67
  test_id: testId,
67
68
  suite_title: getSuiteTitle(test),
68
69
  title: getTestName(test),
69
- code: test.body.toString(),
70
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
70
71
  file: getFile(test),
71
72
  time: test.duration,
72
73
  logs,
@@ -82,7 +83,7 @@ function MochaReporter(runner, opts) {
82
83
  client.addTestRun(STATUS.SKIPPED, {
83
84
  title: getTestName(test),
84
85
  suite_title: getSuiteTitle(test),
85
- code: test.body.toString(),
86
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
86
87
  file: getFile(test),
87
88
  test_id: testId,
88
89
  time: test.duration,
@@ -102,7 +103,7 @@ function MochaReporter(runner, opts) {
102
103
  file: getFile(test),
103
104
  test_id: testId,
104
105
  title: getTestName(test),
105
- code: test.body.toString(),
106
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
106
107
  time: test.duration,
107
108
  logs,
108
109
  });
@@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid';
6
6
  import fs from 'fs';
7
7
  import { APP_PREFIX, STATUS as Status, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
8
8
  import TestomatioClient from '../client.js';
9
- import { upload } from '../fileUploader.js';
10
9
  import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
11
10
  import { services } from '../services/index.js';
12
11
  import { dataStorage } from '../data-storage.js';
@@ -57,11 +56,37 @@ class PlaywrightReporter {
57
56
  logs = `\n\n${pc.bold('Logs:')}\n${pc.red(result.stderr.join(''))}\n${result.stdout.join('')}`;
58
57
  }
59
58
  const manuallyAttachedArtifacts = services.artifacts.get(fullTestTitle);
60
- const keyValues = services.keyValues.get(fullTestTitle);
59
+ const testMeta = services.keyValues.get(fullTestTitle);
61
60
  const rid = test.id || test.testId || uuidv4();
62
61
 
63
- const reportTestPromise = this.client.addTestRun(checkStatus(result.status), {
64
- rid,
62
+ /**
63
+ * @type {{
64
+ * browser?: string,
65
+ * dependencies: string[],
66
+ * isMobile?: boolean
67
+ * metadata: Record<string, any>,
68
+ * name: string,
69
+ * }}
70
+ */
71
+ const project = {
72
+ browser: test.parent.project().use.defaultBrowserType,
73
+ dependencies: test.parent.project().dependencies,
74
+ isMobile: test.parent.project().use.isMobile,
75
+ metadata: test.parent.project().metadata,
76
+ name: test.parent.project().name,
77
+ };
78
+
79
+ let status = result.status;
80
+ // process test.fail() annotation
81
+ if (test.expectedStatus === 'failed') {
82
+ // actual status = expected
83
+ if (result.status === 'failed') status = 'passed';
84
+ // actual status != expected
85
+ if (result.status === 'passed') status = 'failed';
86
+ }
87
+
88
+ const reportTestPromise = this.client.addTestRun(checkStatus(status), {
89
+ rid: `${rid}-${project.name}`,
65
90
  error,
66
91
  test_id: getTestomatIdFromTestTitle(`${title} ${test.tags?.join(' ')}`),
67
92
  suite_title,
@@ -70,12 +95,19 @@ class PlaywrightReporter {
70
95
  time: duration,
71
96
  logs,
72
97
  manuallyAttachedArtifacts,
73
- meta: keyValues,
98
+ meta: {
99
+ browser: project.browser,
100
+ isMobile: project.isMobile,
101
+ project: project.name,
102
+ projectDependencies: project.dependencies?.length ? project.dependencies : null,
103
+ ...testMeta,
104
+ ...project.metadata, // metadata has any type (in playwright), but we will stringify it in client.js
105
+ },
74
106
  file: test.location?.file,
75
107
  });
76
108
 
77
109
  this.uploads.push({
78
- rid,
110
+ rid: `${rid}-${project.name}`,
79
111
  title: test.title,
80
112
  files: result.attachments.filter(a => a.body || a.path),
81
113
  file: test.location?.file,
@@ -94,9 +126,13 @@ class PlaywrightReporter {
94
126
  }
95
127
 
96
128
  if (artifact.body) {
97
- const fileName = tmpFile();
98
- fs.writeFileSync(fileName, artifact.body);
99
- return fileName;
129
+ let filePath = generateTmpFilepath(artifact.name);
130
+
131
+ const extension = artifact.contentType?.split('/')[1]?.replace('jpeg', 'jpg');
132
+ if (extension) filePath += `.${extension}`;
133
+
134
+ fs.writeFileSync(filePath, artifact.body);
135
+ return filePath;
100
136
  }
101
137
 
102
138
  return null;
@@ -107,20 +143,26 @@ class PlaywrightReporter {
107
143
 
108
144
  await Promise.all(reportTestPromises);
109
145
 
110
- if (this.uploads.length && upload.isArtifactsEnabled()) {
111
- console.log(APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
146
+ if (this.uploads.length) {
147
+ if (this.client.uploader.isEnabled) console.log(APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
112
148
 
113
149
  const promises = [];
114
150
 
115
- for (const anUpload of this.uploads) {
116
- const { rid, file, title } = anUpload;
151
+ // ? possible move to addTestRun (needs investigation if files are ready)
152
+ for (const upload of this.uploads) {
153
+ const { rid, file, title } = upload;
117
154
 
118
- const files = anUpload.files.map(attachment => ({
155
+ const files = upload.files.map(attachment => ({
119
156
  path: this.#getArtifactPath(attachment),
120
157
  title,
121
158
  type: attachment.contentType,
122
159
  }));
123
160
 
161
+ if (!this.client.uploader.isEnabled) {
162
+ files.forEach(f => this.client.uploader.storeUploadedFile(f, this.client.runId, rid, false));
163
+ continue;
164
+ }
165
+
124
166
  promises.push(
125
167
  this.client.addTestRun(undefined, {
126
168
  rid,
@@ -190,9 +232,10 @@ function appendStep(step, shift = 0) {
190
232
  return resultStep;
191
233
  }
192
234
 
193
- function tmpFile(prefix = 'tmp.') {
235
+ function generateTmpFilepath(filename = '') {
236
+ filename = filename || `tmp.${crypto.randomBytes(16).toString('hex')}`;
194
237
  const tmpdir = os.tmpdir();
195
- return path.join(tmpdir, prefix + crypto.randomBytes(16).toString('hex'));
238
+ return path.join(tmpdir, filename);
196
239
  }
197
240
 
198
241
  /**
@@ -204,19 +247,4 @@ function getTestContextName(test) {
204
247
  return `${test._requireFile || ''}_${test.title}`;
205
248
  }
206
249
 
207
- function initPlaywrightForStorage() {
208
- try {
209
- // @ts-ignore-next-line
210
- // eslint-disable-next-line import/no-extraneous-dependencies
211
- const { test } = require('@playwright/test');
212
- // eslint-disable-next-line no-empty-pattern
213
- test.beforeEach(async ({}, testInfo) => {
214
- global.testomatioTestTitle = `${testInfo.file || ''}_${testInfo.title}`;
215
- });
216
- } catch (e) {
217
- // ignore
218
- }
219
- }
220
-
221
250
  export default PlaywrightReporter;
222
- export { initPlaywrightForStorage };
@@ -7,13 +7,13 @@ import createDebugMessages from 'debug';
7
7
  const debug = createDebugMessages('@testomatio/reporter:adapter-jest');
8
8
 
9
9
  /**
10
- * @typedef {import('../../types').VitestTest} VitestTest
11
- * @typedef {import('../../types').VitestTestFile} VitestTestFile
12
- * @typedef {import('../../types').VitestSuite} VitestSuite
13
- * @typedef {import('../../types').VitestTestLogs} VitestTestLogs
14
- * @typedef {import('../../vitest.types').ErrorWithDiff} ErrorWithDiff
10
+ * @typedef {import('../../types/types.js').VitestTest} VitestTest
11
+ * @typedef {import('../../types/types.js').VitestTestFile} VitestTestFile
12
+ * @typedef {import('../../types/types.js').VitestSuite} VitestSuite
13
+ * @typedef {import('../../types/types.js').VitestTestLogs} VitestTestLogs
14
+ * @typedef {import('../../types/vitest.types.js').ErrorWithDiff} ErrorWithDiff
15
15
  * @typedef {typeof import('../constants.js').STATUS} STATUS
16
- * @typedef {import('../../types').TestData} TestData
16
+ * @typedef {import('../../types/types.js').TestData} TestData
17
17
  */
18
18
 
19
19
  class VitestReporter {