@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
@@ -0,0 +1,2 @@
1
+ export default CodeceptReporter;
2
+ export function CodeceptReporter(config: any): void;
@@ -10,7 +10,6 @@ const client_js_1 = __importDefault(require("../client.js"));
10
10
  const constants_js_1 = require("../constants.js");
11
11
  const utils_js_1 = require("../utils/utils.js");
12
12
  const index_js_1 = require("../services/index.js");
13
- const fileUploader_js_1 = require("../fileUploader.js");
14
13
  // eslint-disable-next-line
15
14
  const codeceptjs_1 = __importDefault(require("codeceptjs"));
16
15
  const debug = (0, debug_1.default)('@testomatio/reporter:adapter:codeceptjs');
@@ -41,8 +40,10 @@ function CodeceptReporter(config) {
41
40
  const testTimeMap = {};
42
41
  const { apiKey } = config;
43
42
  const getDuration = test => {
44
- if (testTimeMap[test.id]) {
45
- return Date.now() - testTimeMap[test.id];
43
+ if (!test.uid)
44
+ return 0;
45
+ if (testTimeMap[test.uid]) {
46
+ return Date.now() - testTimeMap[test.uid];
46
47
  }
47
48
  return 0;
48
49
  };
@@ -103,24 +104,24 @@ function CodeceptReporter(config) {
103
104
  event.dispatcher.on(event.test.started, test => {
104
105
  index_js_1.services.setContext(test.fullTitle());
105
106
  testTimeMap[test.id] = Date.now();
106
- // start logging
107
+ if (!test.uid)
108
+ return;
109
+ testTimeMap[test.uid] = Date.now();
107
110
  });
108
111
  event.dispatcher.on(event.all.result, async () => {
109
112
  debug('waiting for all tests to be reported');
110
113
  // all tests were reported and we can upload videos
111
114
  await Promise.all(reportTestPromises);
112
- if (fileUploader_js_1.upload.isArtifactsEnabled()) {
113
- await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
114
- await uploadAttachments(client, traces, '📁 Uploading', 'trace');
115
- }
115
+ await uploadAttachments(client, videos, '🎞️ Uploading', 'video');
116
+ await uploadAttachments(client, traces, '📁 Uploading', 'trace');
116
117
  const status = failedTests.length === 0 ? constants_js_1.STATUS.PASSED : constants_js_1.STATUS.FAILED;
117
118
  // @ts-ignore
118
119
  client.updateRunStatus(status);
119
120
  });
120
121
  event.dispatcher.on(event.test.passed, test => {
121
- const { id, tags, title } = test;
122
- if (id && failedTests.includes(id)) {
123
- failedTests = failedTests.filter(failed => id !== failed);
122
+ const { uid, tags, title } = test;
123
+ if (uid && failedTests.includes(uid)) {
124
+ failedTests = failedTests.filter(failed => uid !== failed);
124
125
  }
125
126
  const testObj = getTestAndMessage(title);
126
127
  const logs = getTestLogs(test);
@@ -129,7 +130,7 @@ function CodeceptReporter(config) {
129
130
  index_js_1.services.setContext(null);
130
131
  client.addTestRun(constants_js_1.STATUS.PASSED, {
131
132
  ...stripExampleFromTitle(title),
132
- rid: id,
133
+ rid: uid,
133
134
  suite_title: test.parent && test.parent.title,
134
135
  message: testObj.message,
135
136
  time: getDuration(test),
@@ -151,11 +152,11 @@ function CodeceptReporter(config) {
151
152
  if (!suite.tests)
152
153
  return;
153
154
  for (const test of suite.tests) {
154
- const { id, tags, title } = test;
155
- failedTests.push(id || title);
155
+ const { uid, tags, title } = test;
156
+ failedTests.push(uid || title);
156
157
  const testId = (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`);
157
158
  client.addTestRun(constants_js_1.STATUS.FAILED, {
158
- rid: id,
159
+ rid: uid,
159
160
  ...stripExampleFromTitle(title),
160
161
  suite_title: suite.title,
161
162
  test_id: testId,
@@ -170,8 +171,8 @@ function CodeceptReporter(config) {
170
171
  return;
171
172
  if (test.err)
172
173
  error = test.err;
173
- const { id, tags, title, artifacts } = test;
174
- failedTests.push(id || title);
174
+ const { uid, tags, title, artifacts } = test;
175
+ failedTests.push(uid || title);
175
176
  const testObj = getTestAndMessage(title);
176
177
  const files = [];
177
178
  if (artifacts.screenshot)
@@ -183,7 +184,7 @@ function CodeceptReporter(config) {
183
184
  index_js_1.services.setContext(null);
184
185
  client.addTestRun(constants_js_1.STATUS.FAILED, {
185
186
  ...stripExampleFromTitle(title),
186
- rid: id,
187
+ rid: uid,
187
188
  test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
188
189
  suite_title: test.parent && test.parent.title,
189
190
  error,
@@ -198,19 +199,19 @@ function CodeceptReporter(config) {
198
199
  debug('artifacts', artifacts);
199
200
  for (const aid in artifacts) {
200
201
  if (aid.startsWith('video'))
201
- videos.push({ rid: id, title, path: artifacts[aid], type: 'video/webm' });
202
+ videos.push({ rid: uid, title, path: artifacts[aid], type: 'video/webm' });
202
203
  if (aid.startsWith('trace'))
203
- traces.push({ rid: id, title, path: artifacts[aid], type: 'application/zip' });
204
+ traces.push({ rid: uid, title, path: artifacts[aid], type: 'application/zip' });
204
205
  }
205
206
  // output.stop();
206
207
  });
207
208
  event.dispatcher.on(event.test.skipped, test => {
208
- const { id, tags, title } = test;
209
- if (failedTests.includes(id || title))
209
+ const { uid, tags, title } = test;
210
+ if (failedTests.includes(uid || title))
210
211
  return;
211
212
  const testObj = getTestAndMessage(title);
212
213
  client.addTestRun(constants_js_1.STATUS.SKIPPED, {
213
- rid: id,
214
+ rid: uid,
214
215
  ...stripExampleFromTitle(title),
215
216
  test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${tags?.join(' ')}`),
216
217
  suite_title: test.parent && test.parent.title,
@@ -274,10 +275,15 @@ function CodeceptReporter(config) {
274
275
  async function uploadAttachments(client, attachments, messagePrefix, attachmentType) {
275
276
  if (!attachments?.length)
276
277
  return;
277
- console.log(constants_js_1.APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
278
+ if (client.uploader.isEnabled) {
279
+ console.log(constants_js_1.APP_PREFIX, `Attachments: ${messagePrefix} ${attachments.length} ${attachmentType} ...`);
280
+ }
278
281
  const promises = attachments.map(async (attachment) => {
279
282
  const { rid, title, path, type } = attachment;
280
283
  const file = { path, type, title };
284
+ // we are storing file if upload is disabled
285
+ if (!client.uploader.isEnabled)
286
+ return client.uploader.storeUploadedFile(path, client.runId, rid, false);
281
287
  return client.addTestRun(undefined, {
282
288
  ...stripExampleFromTitle(title),
283
289
  rid,
@@ -318,5 +324,6 @@ function getTestLogs(test) {
318
324
  }
319
325
  return logs;
320
326
  }
327
+ module.exports = CodeceptReporter;
321
328
 
322
329
  module.exports.CodeceptReporter = CodeceptReporter;
@@ -0,0 +1,14 @@
1
+ export default CucumberReporter;
2
+ export class CucumberReporter extends Formatter {
3
+ constructor(options: any);
4
+ failures: any[];
5
+ cases: any[];
6
+ client: TestomatClient;
7
+ status: string;
8
+ parseEnvelope(envelope: any): void;
9
+ onTestCaseStarted(testCaseStarted: any): void;
10
+ onTestCaseFinished(testCaseFinished: any): void;
11
+ onTestRunFinished(envelope: any): void;
12
+ }
13
+ import { Formatter } from '@cucumber/cucumber';
14
+ import TestomatClient from '../../client.js';
File without changes
@@ -0,0 +1,2 @@
1
+ export default CucumberReporter;
2
+ import { CucumberReporter } from './cucumber/current.js';
@@ -0,0 +1,2 @@
1
+ export default testomatioReporter;
2
+ declare function testomatioReporter(on: any): void;
@@ -45,15 +45,17 @@ const testomatioReporter = on => {
45
45
  return this.message;
46
46
  };
47
47
  }
48
- const formattedError = error ? {
49
- message: error.message,
50
- name: error.name,
51
- inspect: error.inspect ||
52
- // eslint-disable-next-line
53
- function () {
54
- return this.message;
55
- },
56
- } : undefined;
48
+ const formattedError = error
49
+ ? {
50
+ message: error.message,
51
+ name: error.name,
52
+ inspect: error.inspect ||
53
+ // eslint-disable-next-line
54
+ function () {
55
+ return this.message;
56
+ },
57
+ }
58
+ : undefined;
57
59
  const screenshots = Array.isArray(results.screenshots)
58
60
  ? results.screenshots
59
61
  .filter(screenshot => screenshot?.path && screenshot?.path.includes(title) && screenshot?.takenAt)
@@ -0,0 +1,11 @@
1
+ export default JasmineReporter;
2
+ export class JasmineReporter {
3
+ constructor(options: any);
4
+ testTimeMap: {};
5
+ client: TestomatClient;
6
+ getDuration(test: any): number;
7
+ specStarted(result: any): void;
8
+ specDone(result: any): void;
9
+ jasmineDone(suiteInfo: any, done: any): void;
10
+ }
11
+ import TestomatClient from '../client.js';
@@ -0,0 +1,13 @@
1
+ export class JestReporter {
2
+ constructor(globalConfig: any, options: any);
3
+ _globalConfig: any;
4
+ _options: any;
5
+ client: TestomatClient;
6
+ onRunStart(): void;
7
+ onTestStart(testFile: any): void;
8
+ onTestCaseStart(test: any, testCase: any): void;
9
+ onTestResult(test: any, testResult: any): void;
10
+ onRunComplete(contexts: any, results: any): void;
11
+ }
12
+ export default JestReporter;
13
+ import TestomatClient from '../client.js';
@@ -0,0 +1,2 @@
1
+ export default MochaReporter;
2
+ declare function MochaReporter(runner: any, opts: any): void;
@@ -22,6 +22,7 @@ function MochaReporter(runner, opts) {
22
22
  const client = new client_js_1.default({ apiKey });
23
23
  runner.on(EVENT_RUN_BEGIN, () => {
24
24
  client.createRun();
25
+ // clear dir with artifacts/logs
25
26
  utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
26
27
  });
27
28
  runner.on(EVENT_SUITE_BEGIN, async (suite) => {
@@ -47,7 +48,7 @@ function MochaReporter(runner, opts) {
47
48
  test_id: testId,
48
49
  suite_title: getSuiteTitle(test),
49
50
  title: getTestName(test),
50
- code: test.body.toString(),
51
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
51
52
  file: getFile(test),
52
53
  time: test.duration,
53
54
  logs,
@@ -62,7 +63,7 @@ function MochaReporter(runner, opts) {
62
63
  client.addTestRun(constants_js_1.STATUS.SKIPPED, {
63
64
  title: getTestName(test),
64
65
  suite_title: getSuiteTitle(test),
65
- code: test.body.toString(),
66
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
66
67
  file: getFile(test),
67
68
  test_id: testId,
68
69
  time: test.duration,
@@ -79,7 +80,7 @@ function MochaReporter(runner, opts) {
79
80
  file: getFile(test),
80
81
  test_id: testId,
81
82
  title: getTestName(test),
82
- code: test.body.toString(),
83
+ code: process.env.TESTOMATIO_UPDATE_CODE ? test.body.toString() : '',
83
84
  time: test.duration,
84
85
  logs,
85
86
  });
@@ -0,0 +1,14 @@
1
+ export default PlaywrightReporter;
2
+ declare class PlaywrightReporter {
3
+ constructor(config?: {});
4
+ client: TestomatioClient;
5
+ uploads: any[];
6
+ onBegin(config: any, suite: any): void;
7
+ suite: any;
8
+ config: any;
9
+ onTestBegin(testInfo: any): void;
10
+ onTestEnd(test: any, result: any): void;
11
+ onEnd(result: any): Promise<void>;
12
+ #private;
13
+ }
14
+ import TestomatioClient from '../client.js';
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.initPlaywrightForStorage = initPlaywrightForStorage;
7
6
  const picocolors_1 = __importDefault(require("picocolors"));
8
7
  const crypto_1 = __importDefault(require("crypto"));
9
8
  const os_1 = __importDefault(require("os"));
@@ -12,7 +11,6 @@ const uuid_1 = require("uuid");
12
11
  const fs_1 = __importDefault(require("fs"));
13
12
  const constants_js_1 = require("../constants.js");
14
13
  const client_js_1 = __importDefault(require("../client.js"));
15
- const fileUploader_js_1 = require("../fileUploader.js");
16
14
  const utils_js_1 = require("../utils/utils.js");
17
15
  const index_js_1 = require("../services/index.js");
18
16
  const data_storage_js_1 = require("../data-storage.js");
@@ -55,10 +53,36 @@ class PlaywrightReporter {
55
53
  logs = `\n\n${picocolors_1.default.bold('Logs:')}\n${picocolors_1.default.red(result.stderr.join(''))}\n${result.stdout.join('')}`;
56
54
  }
57
55
  const manuallyAttachedArtifacts = index_js_1.services.artifacts.get(fullTestTitle);
58
- const keyValues = index_js_1.services.keyValues.get(fullTestTitle);
56
+ const testMeta = index_js_1.services.keyValues.get(fullTestTitle);
59
57
  const rid = test.id || test.testId || (0, uuid_1.v4)();
60
- const reportTestPromise = this.client.addTestRun(checkStatus(result.status), {
61
- rid,
58
+ /**
59
+ * @type {{
60
+ * browser?: string,
61
+ * dependencies: string[],
62
+ * isMobile?: boolean
63
+ * metadata: Record<string, any>,
64
+ * name: string,
65
+ * }}
66
+ */
67
+ const project = {
68
+ browser: test.parent.project().use.defaultBrowserType,
69
+ dependencies: test.parent.project().dependencies,
70
+ isMobile: test.parent.project().use.isMobile,
71
+ metadata: test.parent.project().metadata,
72
+ name: test.parent.project().name,
73
+ };
74
+ let status = result.status;
75
+ // process test.fail() annotation
76
+ if (test.expectedStatus === 'failed') {
77
+ // actual status = expected
78
+ if (result.status === 'failed')
79
+ status = 'passed';
80
+ // actual status != expected
81
+ if (result.status === 'passed')
82
+ status = 'failed';
83
+ }
84
+ const reportTestPromise = this.client.addTestRun(checkStatus(status), {
85
+ rid: `${rid}-${project.name}`,
62
86
  error,
63
87
  test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(`${title} ${test.tags?.join(' ')}`),
64
88
  suite_title,
@@ -67,11 +91,18 @@ class PlaywrightReporter {
67
91
  time: duration,
68
92
  logs,
69
93
  manuallyAttachedArtifacts,
70
- meta: keyValues,
94
+ meta: {
95
+ browser: project.browser,
96
+ isMobile: project.isMobile,
97
+ project: project.name,
98
+ projectDependencies: project.dependencies?.length ? project.dependencies : null,
99
+ ...testMeta,
100
+ ...project.metadata, // metadata has any type (in playwright), but we will stringify it in client.js
101
+ },
71
102
  file: test.location?.file,
72
103
  });
73
104
  this.uploads.push({
74
- rid,
105
+ rid: `${rid}-${project.name}`,
75
106
  title: test.title,
76
107
  files: result.attachments.filter(a => a.body || a.path),
77
108
  file: test.location?.file,
@@ -87,9 +118,12 @@ class PlaywrightReporter {
87
118
  return path_1.default.join(this.config.outputDir || this.config.projects[0].outputDir, artifact.path);
88
119
  }
89
120
  if (artifact.body) {
90
- const fileName = tmpFile();
91
- fs_1.default.writeFileSync(fileName, artifact.body);
92
- return fileName;
121
+ let filePath = generateTmpFilepath(artifact.name);
122
+ const extension = artifact.contentType?.split('/')[1]?.replace('jpeg', 'jpg');
123
+ if (extension)
124
+ filePath += `.${extension}`;
125
+ fs_1.default.writeFileSync(filePath, artifact.body);
126
+ return filePath;
93
127
  }
94
128
  return null;
95
129
  }
@@ -97,16 +131,22 @@ class PlaywrightReporter {
97
131
  if (!this.client)
98
132
  return;
99
133
  await Promise.all(reportTestPromises);
100
- if (this.uploads.length && fileUploader_js_1.upload.isArtifactsEnabled()) {
101
- console.log(constants_js_1.APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
134
+ if (this.uploads.length) {
135
+ if (this.client.uploader.isEnabled)
136
+ console.log(constants_js_1.APP_PREFIX, `🎞️ Uploading ${this.uploads.length} files...`);
102
137
  const promises = [];
103
- for (const anUpload of this.uploads) {
104
- const { rid, file, title } = anUpload;
105
- const files = anUpload.files.map(attachment => ({
138
+ // ? possible move to addTestRun (needs investigation if files are ready)
139
+ for (const upload of this.uploads) {
140
+ const { rid, file, title } = upload;
141
+ const files = upload.files.map(attachment => ({
106
142
  path: this.#getArtifactPath(attachment),
107
143
  title,
108
144
  type: attachment.contentType,
109
145
  }));
146
+ if (!this.client.uploader.isEnabled) {
147
+ files.forEach(f => this.client.uploader.storeUploadedFile(f, this.client.runId, rid, false));
148
+ continue;
149
+ }
110
150
  promises.push(this.client.addTestRun(undefined, {
111
151
  rid,
112
152
  title,
@@ -163,9 +203,10 @@ function appendStep(step, shift = 0) {
163
203
  }
164
204
  return resultStep;
165
205
  }
166
- function tmpFile(prefix = 'tmp.') {
206
+ function generateTmpFilepath(filename = '') {
207
+ filename = filename || `tmp.${crypto_1.default.randomBytes(16).toString('hex')}`;
167
208
  const tmpdir = os_1.default.tmpdir();
168
- return path_1.default.join(tmpdir, prefix + crypto_1.default.randomBytes(16).toString('hex'));
209
+ return path_1.default.join(tmpdir, filename);
169
210
  }
170
211
  /**
171
212
  * Returns filename + test title
@@ -175,20 +216,4 @@ function tmpFile(prefix = 'tmp.') {
175
216
  function getTestContextName(test) {
176
217
  return `${test._requireFile || ''}_${test.title}`;
177
218
  }
178
- function initPlaywrightForStorage() {
179
- try {
180
- // @ts-ignore-next-line
181
- // eslint-disable-next-line import/no-extraneous-dependencies
182
- const { test } = require('@playwright/test');
183
- // eslint-disable-next-line no-empty-pattern
184
- test.beforeEach(async ({}, testInfo) => {
185
- global.testomatioTestTitle = `${testInfo.file || ''}_${testInfo.title}`;
186
- });
187
- }
188
- catch (e) {
189
- // ignore
190
- }
191
- }
192
219
  module.exports = PlaywrightReporter;
193
-
194
- module.exports.initPlaywrightForStorage = initPlaywrightForStorage;
@@ -0,0 +1,35 @@
1
+ export default VitestReporter;
2
+ export type VitestTest = import("../../types/types.js").VitestTest;
3
+ export type VitestTestFile = import("../../types/types.js").VitestTestFile;
4
+ export type VitestSuite = import("../../types/types.js").VitestSuite;
5
+ export type VitestTestLogs = import("../../types/types.js").VitestTestLogs;
6
+ export type ErrorWithDiff = import("../../types/vitest.types.js").ErrorWithDiff;
7
+ export type STATUS = typeof import("../constants.js").STATUS;
8
+ export type TestData = import("../../types/types.js").TestData;
9
+ /**
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
+ * @typedef {typeof import('../constants.js').STATUS} STATUS
16
+ * @typedef {import('../../types/types.js').TestData} TestData
17
+ */
18
+ export class VitestReporter {
19
+ constructor(config?: {});
20
+ client: TestomatioClient;
21
+ /**
22
+ * @type {(TestData & {status: string})[]} tests
23
+ */
24
+ tests: (TestData & {
25
+ status: string;
26
+ })[];
27
+ onInit(): void;
28
+ /**
29
+ * @param {VitestTestFile[] | undefined} files // array with results;
30
+ * @param {unknown[] | undefined} errors // errors does not contain errors from tests; probably its testrunner errors
31
+ */
32
+ onFinished(files: VitestTestFile[] | undefined, errors: unknown[] | undefined): Promise<void>;
33
+ #private;
34
+ }
35
+ import { Client as TestomatioClient } from '../client.js';
@@ -11,13 +11,13 @@ const utils_js_1 = require("../utils/utils.js");
11
11
  const debug_1 = __importDefault(require("debug"));
12
12
  const debug = (0, debug_1.default)('@testomatio/reporter:adapter-jest');
13
13
  /**
14
- * @typedef {import('../../types').VitestTest} VitestTest
15
- * @typedef {import('../../types').VitestTestFile} VitestTestFile
16
- * @typedef {import('../../types').VitestSuite} VitestSuite
17
- * @typedef {import('../../types').VitestTestLogs} VitestTestLogs
18
- * @typedef {import('../../vitest.types').ErrorWithDiff} ErrorWithDiff
14
+ * @typedef {import('../../types/types.js').VitestTest} VitestTest
15
+ * @typedef {import('../../types/types.js').VitestTestFile} VitestTestFile
16
+ * @typedef {import('../../types/types.js').VitestSuite} VitestSuite
17
+ * @typedef {import('../../types/types.js').VitestTestLogs} VitestTestLogs
18
+ * @typedef {import('../../types/vitest.types.js').ErrorWithDiff} ErrorWithDiff
19
19
  * @typedef {typeof import('../constants.js').STATUS} STATUS
20
- * @typedef {import('../../types').TestData} TestData
20
+ * @typedef {import('../../types/types.js').TestData} TestData
21
21
  */
22
22
  class VitestReporter {
23
23
  constructor(config = {}) {
@@ -0,0 +1,24 @@
1
+ export default WebdriverReporter;
2
+ declare class WebdriverReporter extends WDIOReporter {
3
+ constructor(options: any);
4
+ client: TestomatClient;
5
+ _addTestPromises: any[];
6
+ _isSynchronising: boolean;
7
+ /**
8
+ *
9
+ * @param {RunnerStats} runData
10
+ */
11
+ onRunnerEnd(runData: RunnerStats): Promise<void>;
12
+ onRunnerStart(): void;
13
+ onTestStart(test: any): void;
14
+ onTestEnd(test: any): void;
15
+ onSuiteEnd(scerario: any): void;
16
+ addTest(test: any): Promise<void>;
17
+ /**
18
+ * @param {import('../../types/types.js').WebdriverIOScenario} scenario
19
+ */
20
+ addBddScenario(scenario: import("../../types/types.js").WebdriverIOScenario): Promise<import("../../types/types.js").PipeResult[]>;
21
+ }
22
+ import WDIOReporter from '@wdio/reporter';
23
+ import TestomatClient from '../client.js';
24
+ import { RunnerStats } from '@wdio/reporter';
@@ -30,6 +30,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
30
30
  const reporter_1 = __importStar(require("@wdio/reporter"));
31
31
  const client_js_1 = __importDefault(require("../client.js"));
32
32
  const utils_js_1 = require("../utils/utils.js");
33
+ const index_js_1 = require("../services/index.js");
34
+ const constants_js_1 = require("../constants.js");
33
35
  class WebdriverReporter extends reporter_1.default {
34
36
  constructor(options) {
35
37
  super(options);
@@ -51,18 +53,30 @@ class WebdriverReporter extends reporter_1.default {
51
53
  this._isSynchronising = true;
52
54
  await Promise.all(this._addTestPromises);
53
55
  this._isSynchronising = false;
54
- // NOTE: new functionality; may break everything
56
+ // NOTE: new functionality; may break everything
55
57
  // also this may require additional status mapping
56
58
  await this.client.updateRunStatus(runData.failures ? 'failed' : 'passed');
57
59
  }
60
+ onRunnerStart() {
61
+ // clear dir with artifacts/logs
62
+ //
63
+ utils_js_1.fileSystem.clearDir(constants_js_1.TESTOMAT_TMP_STORAGE_DIR);
64
+ }
65
+ onTestStart(test) {
66
+ index_js_1.services.setContext(test.fullTitle);
67
+ }
58
68
  onTestEnd(test) {
69
+ test.suite = test.parent;
70
+ const logs = getTestLogs(test.fullTitle);
71
+ // TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
72
+ // const artifacts = services.artifacts.get(test.fullTitle);
73
+ // const keyValues = services.keyValues.get(test.fullTitle);
74
+ test.logs = logs;
75
+ // test.artifacts = artifacts;
76
+ // test.meta = keyValues;
59
77
  this._addTestPromises.push(this.addTest(test));
60
78
  }
61
79
  // wdio-cucumber does not trigger onTestEnd hook, thus, using this one
62
- /**
63
- *
64
- * @returns
65
- */
66
80
  onSuiteEnd(scerario) {
67
81
  if (scerario.type === 'scenario') {
68
82
  this._addTestPromises.push(this.addBddScenario(scerario));
@@ -78,7 +92,10 @@ class WebdriverReporter extends reporter_1.default {
78
92
  .filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
79
93
  .map(el => Buffer.from(el.result.value, 'base64'));
80
94
  await this.client.addTestRun(state, {
95
+ manuallyAttachedArtifacts: test.artifacts,
81
96
  error,
97
+ logs: test.logs,
98
+ meta: test.meta,
82
99
  title,
83
100
  test_id: testId,
84
101
  time: duration,
@@ -86,7 +103,7 @@ class WebdriverReporter extends reporter_1.default {
86
103
  });
87
104
  }
88
105
  /**
89
- * @param {import('../../types').WebdriverIOScenario} scenario
106
+ * @param {import('../../types/types.js').WebdriverIOScenario} scenario
90
107
  */
91
108
  addBddScenario(scenario) {
92
109
  if (!this.client)
@@ -114,4 +131,15 @@ class WebdriverReporter extends reporter_1.default {
114
131
  });
115
132
  }
116
133
  }
134
+ /**
135
+ *
136
+ * @param {*} fullTestTitle
137
+ * @returns string
138
+ */
139
+ function getTestLogs(fullTestTitle) {
140
+ const logsArr = index_js_1.services.logger.getLogs(fullTestTitle);
141
+ // remove duplicates (for some reason, logs are duplicated several times)
142
+ const logs = logsArr ? Array.from(new Set(logsArr)).join('\n').trim() : '';
143
+ return logs;
144
+ }
117
145
  module.exports = WebdriverReporter;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};