@testomatio/reporter 2.7.1 → 2.7.2-beta.1

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 (49) hide show
  1. package/README.md +2 -1
  2. package/lib/adapter/codecept.js +81 -26
  3. package/lib/adapter/playwright.d.ts +1 -1
  4. package/lib/adapter/playwright.js +54 -34
  5. package/lib/adapter/utils/step-formatter.d.ts +134 -0
  6. package/lib/adapter/utils/step-formatter.js +237 -0
  7. package/lib/bin/cli.js +28 -31
  8. package/lib/bin/reportXml.js +5 -6
  9. package/lib/bin/uploadArtifacts.js +6 -6
  10. package/lib/client.d.ts +8 -0
  11. package/lib/client.js +71 -10
  12. package/lib/constants.d.ts +1 -0
  13. package/lib/constants.js +7 -1
  14. package/lib/pipe/bitbucket.js +2 -1
  15. package/lib/pipe/coverage.js +16 -15
  16. package/lib/pipe/debug.js +3 -3
  17. package/lib/pipe/github.js +3 -2
  18. package/lib/pipe/gitlab.js +2 -1
  19. package/lib/pipe/index.js +5 -5
  20. package/lib/pipe/testomatio.js +21 -24
  21. package/lib/uploader.js +3 -2
  22. package/lib/utils/log.d.ts +45 -0
  23. package/lib/utils/log.js +98 -0
  24. package/lib/utils/pipe_utils.js +5 -5
  25. package/lib/utils/utils.d.ts +10 -0
  26. package/lib/utils/utils.js +16 -1
  27. package/lib/xmlReader.js +5 -4
  28. package/package.json +1 -1
  29. package/src/adapter/codecept.js +99 -29
  30. package/src/adapter/playwright.js +64 -39
  31. package/src/adapter/utils/step-formatter.js +232 -0
  32. package/src/bin/cli.js +34 -31
  33. package/src/bin/reportXml.js +5 -6
  34. package/src/bin/uploadArtifacts.js +6 -6
  35. package/src/client.js +76 -26
  36. package/src/constants.js +4 -0
  37. package/src/pipe/bitbucket.js +2 -1
  38. package/src/pipe/coverage.js +16 -15
  39. package/src/pipe/debug.js +3 -3
  40. package/src/pipe/github.js +4 -3
  41. package/src/pipe/gitlab.js +2 -1
  42. package/src/pipe/index.js +5 -7
  43. package/src/pipe/testomatio.js +32 -25
  44. package/src/uploader.js +3 -2
  45. package/src/utils/log.js +87 -0
  46. package/src/utils/pipe_utils.js +5 -5
  47. package/src/utils/utils.js +14 -0
  48. package/src/xmlReader.js +5 -4
  49. package/types/types.d.ts +3 -0
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateShortFilename = generateShortFilename;
7
+ exports.formatStep = formatStep;
8
+ exports.addStatusToStep = addStatusToStep;
9
+ exports.addArtifactsToStep = addArtifactsToStep;
10
+ exports.addArtifactPathToStep = addArtifactPathToStep;
11
+ const utils_js_1 = require("../../utils/utils.js");
12
+ const path_1 = __importDefault(require("path"));
13
+ const crypto_1 = __importDefault(require("crypto"));
14
+ const fs_1 = __importDefault(require("fs"));
15
+ /**
16
+ * Generates a short unique filename from screenshot path
17
+ * If original filename is too long, uses hash-based name
18
+ *
19
+ * @param {string} screenshotPath - Path to screenshot file
20
+ * @returns {string} Short filename (max 80 chars)
21
+ */
22
+ function generateShortFilename(screenshotPath) {
23
+ const originalFilename = path_1.default.basename(screenshotPath);
24
+ const stepPrefix = originalFilename.match(/^(\d{3,4}_)/)?.[1] || '';
25
+ if (originalFilename.length < 40) {
26
+ return originalFilename;
27
+ }
28
+ const ext = path_1.default.extname(screenshotPath);
29
+ const hash = crypto_1.default
30
+ .createHash('sha256')
31
+ .update(screenshotPath)
32
+ .digest('hex')
33
+ .slice(0, 16);
34
+ return `${stepPrefix}screenshot_${hash}${ext}`;
35
+ }
36
+ /**
37
+ * Formats a step object according to Testomat.io Step Schema
38
+ *
39
+ * This function transforms a raw step object from test frameworks (CodeceptJS, Playwright, etc.)
40
+ * into a standardized format compatible with Testomat.io API. It ensures all text fields are
41
+ * truncated to 250 characters as defined in testomat-api-definition.yml.
42
+ *
43
+ * Processed fields:
44
+ * - category: step type (framework, user, hook) - defaults to 'user'
45
+ * - title: step name/description, truncated to 250 chars
46
+ * - duration: step execution time in seconds
47
+ * - log: optional log output, truncated to 250 chars
48
+ * - artifacts: optional array of artifact URLs (screenshots), each truncated to 250 chars
49
+ * - error: error details (message + stack) if step failed, each truncated to 250 chars
50
+ * - steps: recursively formats nested steps
51
+ *
52
+ * Schema reference: testomat-api-definition.yml (Step object)
53
+ *
54
+ * @param {Object} step - Raw step object from test framework
55
+ * @param {string} [step.category] - Step category: 'user', 'framework', or 'hook'
56
+ * @param {string} [step.title] - Step title/name
57
+ * @param {number} [step.duration] - Step duration in seconds
58
+ * @param {string} [step.log] - Log output for this step
59
+ * @param {string[]} [step.artifacts] - Array of artifact URLs (screenshots)
60
+ * @param {string|Object} [step.error] - Error details - can be string or object with message/stack
61
+ * @param {Object[]} [step.steps] - Array of nested child steps
62
+ * @returns {Object} Formatted step object matching Testomat.io Step Schema with:
63
+ * category, title, duration, and optional log, artifacts, error, and steps fields
64
+ *
65
+ * @example
66
+ * const rawStep = {
67
+ * category: 'user',
68
+ * title: 'I click on button',
69
+ * duration: 1.5,
70
+ * error: { message: 'Element not found', stack: 'at test.js:10:5' }
71
+ * };
72
+ * const formatted = formatStep(rawStep);
73
+ * // Returns: { category: 'user', title: 'I click on button', duration: 1.5, error: {...} }
74
+ */
75
+ function formatStep(step) {
76
+ const formattedStep = {
77
+ category: step.category || 'user',
78
+ title: (0, utils_js_1.truncate)(String(step.title || ''), 250),
79
+ duration: step.duration || 0,
80
+ };
81
+ if (step.log) {
82
+ formattedStep.log = (0, utils_js_1.truncate)(String(step.log), 250);
83
+ }
84
+ if (step.artifacts && Array.isArray(step.artifacts)) {
85
+ formattedStep.artifacts = step.artifacts.map(artifact => (0, utils_js_1.truncate)(String(artifact), 250));
86
+ }
87
+ if (step.error) {
88
+ if (typeof step.error === 'object') {
89
+ formattedStep.error = {
90
+ message: (0, utils_js_1.truncate)(String(step.error.message || 'Step failed'), 250),
91
+ stack: (0, utils_js_1.truncate)(String(step.error.stack || ''), 250),
92
+ };
93
+ }
94
+ else {
95
+ formattedStep.error = (0, utils_js_1.truncate)(String(step.error), 250);
96
+ }
97
+ }
98
+ if (step.steps && Array.isArray(step.steps)) {
99
+ formattedStep.steps = step.steps.map(s => formatStep(s));
100
+ }
101
+ return formattedStep;
102
+ }
103
+ /**
104
+ * Adds status field to step
105
+ *
106
+ * Normalizes step status from test frameworks to Testomat.io standard format.
107
+ * Maps framework-specific statuses ('success', 'failed', 'passed') to Testomat.io
108
+ * standard values ('passed', 'failed').
109
+ *
110
+ * Status mapping:
111
+ * - 'success' → 'passed'
112
+ * - 'passed' → 'passed'
113
+ * - 'failed' → 'failed'
114
+ * - Any other value → 'passed' (default)
115
+ *
116
+ * If step already has a status, it won't be overwritten. If error is provided
117
+ * and step doesn't have status, it will be set to 'failed'.
118
+ *
119
+ * Schema reference: testomat-api-definition.yml (Step.status enum)
120
+ *
121
+ * @param {Object} step - Step object to add status to (modified in place)
122
+ * @param {string} [step.status] - Existing status (won't be overwritten if present)
123
+ * @param {string} status - Status from test framework: 'success', 'failed', or 'passed'
124
+ * @param {Error|Object|null} err - Error object if step failed
125
+ * @returns {Object} The same step object with added status field
126
+ *
127
+ * @example
128
+ * const step = { title: 'Click button' };
129
+ * addStatusToStep(step, 'success', null);
130
+ * // step.status === 'passed'
131
+ *
132
+ * @example
133
+ * const step2 = { title: 'Find element' };
134
+ * addStatusToStep(step2, 'failed', new Error('Not found'));
135
+ * // step2.status === 'failed'
136
+ */
137
+ function addStatusToStep(step, status, err) {
138
+ if (step.status)
139
+ return step;
140
+ const statusMap = {
141
+ 'success': 'passed',
142
+ 'failed': 'failed',
143
+ 'passed': 'passed',
144
+ };
145
+ step.status = statusMap[status] || 'passed';
146
+ if (err && !step.status) {
147
+ step.status = 'failed';
148
+ }
149
+ return step;
150
+ }
151
+ /**
152
+ * Adds screenshot to step as artifacts array
153
+ *
154
+ * Extracts screenshot path from artifacts and adds it to the step's artifacts array.
155
+ * The actual upload will happen in the client's addTestRun method.
156
+ *
157
+ * Artifact format supports:
158
+ * - Array format: [{ screenshot: '/path/to/screenshot.png' }]
159
+ * - Object format: { screenshot: '/path/to/screenshot.png' }
160
+ *
161
+ * Screenshot path can be specified as:
162
+ * - Object with path property: { screenshot: { path: '/path/to/file.png' } }
163
+ * - Object with screenshot property: { screenshot: { screenshot: '/path/to/file.png' } }
164
+ * - Direct string path: { screenshot: '/path/to/file.png' }
165
+ *
166
+ * @param {Object} step - Step object to add artifacts to (modified in place)
167
+ * @param {string[]} [step.artifacts] - Existing artifacts array (won't be overwritten if present)
168
+ * @param {Object|Object[]|null} artifacts - Artifacts from test framework
169
+ * @returns {Object} The same step object with artifacts array added
170
+ *
171
+ * @example
172
+ * const step = { title: 'Click button' };
173
+ * const artifacts = { screenshot: '/tmp/screenshot.png' };
174
+ * addArtifactsToStep(step, artifacts);
175
+ * // step.artifacts === ['/tmp/screenshot.png']
176
+ */
177
+ function addArtifactsToStep(step, artifacts) {
178
+ if (!artifacts)
179
+ return step;
180
+ let screenshotPath = null;
181
+ if (Array.isArray(artifacts)) {
182
+ const screenshotArtifact = artifacts.find(a => a.screenshot);
183
+ if (screenshotArtifact && screenshotArtifact.path) {
184
+ screenshotPath = screenshotArtifact.path;
185
+ }
186
+ else if (screenshotArtifact && screenshotArtifact.screenshot) {
187
+ screenshotPath = screenshotArtifact.screenshot;
188
+ }
189
+ }
190
+ else if (artifacts.screenshot) {
191
+ screenshotPath = artifacts.screenshot;
192
+ }
193
+ if (screenshotPath && fs_1.default.existsSync(screenshotPath)) {
194
+ const truncatedPath = (0, utils_js_1.truncate)(String(screenshotPath), 250);
195
+ if (step.artifacts && Array.isArray(step.artifacts)) {
196
+ step.artifacts.push(truncatedPath);
197
+ }
198
+ else {
199
+ step.artifacts = [truncatedPath];
200
+ }
201
+ }
202
+ return step;
203
+ }
204
+ /**
205
+ * Appends one artifact path to a step.
206
+ *
207
+ * Unlike addArtifactsToStep, this helper accepts a direct path (or URL-like string)
208
+ * and does not check file existence, so callers can attach fallback artifacts
209
+ * collected from logs or async trace outputs.
210
+ *
211
+ * @param {Object} step - Step object to update (modified in place)
212
+ * @param {string} artifactPath - Artifact path to append
213
+ * @returns {Object} The same step object with updated artifacts
214
+ */
215
+ function addArtifactPathToStep(step, artifactPath) {
216
+ if (!step || !artifactPath)
217
+ return step;
218
+ const truncatedPath = (0, utils_js_1.truncate)(String(artifactPath), 250);
219
+ if (step.artifacts && Array.isArray(step.artifacts)) {
220
+ if (!step.artifacts.includes(truncatedPath))
221
+ step.artifacts.push(truncatedPath);
222
+ }
223
+ else {
224
+ step.artifacts = [truncatedPath];
225
+ }
226
+ return step;
227
+ }
228
+
229
+ module.exports.generateShortFilename = generateShortFilename;
230
+
231
+ module.exports.formatStep = formatStep;
232
+
233
+ module.exports.addStatusToStep = addStatusToStep;
234
+
235
+ module.exports.addArtifactsToStep = addArtifactsToStep;
236
+
237
+ module.exports.addArtifactPathToStep = addArtifactPathToStep;
package/lib/bin/cli.js CHANGED
@@ -18,6 +18,7 @@ const picocolors_1 = __importDefault(require("picocolors"));
18
18
  const filesize_1 = require("filesize");
19
19
  const dotenv_1 = __importDefault(require("dotenv"));
20
20
  const replay_js_1 = __importDefault(require("../replay.js"));
21
+ const log_js_1 = require("../utils/log.js");
21
22
  const debug = (0, debug_1.default)('@testomatio/reporter:cli');
22
23
  const version = (0, utils_js_1.getPackageVersion)();
23
24
  console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
@@ -82,7 +83,7 @@ program
82
83
  const title = process.env.TESTOMATIO_TITLE;
83
84
  const client = new client_js_1.default({ apiKey, title });
84
85
  if (opts.filter || opts.filterList) {
85
- console.log(constants_js_1.APP_PREFIX, 'Filtering tests...');
86
+ log_js_1.log.info('Filtering tests...');
86
87
  // Example of use: npx @testomatio/reporter run "npx jest" --filter "testomatio:tag-name=frontend"
87
88
  // Example of use: npx @testomatio/reporter run "npx jest" --filter "coverage:file=coverage.yml"
88
89
  // Example of use: npx @testomatio/reporter run "npx jest" --filter-list "coverage:file=coverage.yml"
@@ -95,16 +96,16 @@ program
95
96
  try {
96
97
  const tests = await client.prepareRun(prepareRunParams);
97
98
  if (!tests || tests.length === 0) {
98
- console.log(constants_js_1.APP_PREFIX, picocolors_1.default.yellow('No tests found.'));
99
+ log_js_1.log.info(picocolors_1.default.yellow('No tests found.'));
99
100
  return;
100
101
  }
101
102
  const pattern = `(${tests.join('|')})`;
102
103
  const filteredCommand = (0, utils_js_1.applyFilter)(command, tests);
103
104
  debug(`Execution pattern: "${pattern}"`);
104
105
  if (opts.filterList) {
105
- console.log(constants_js_1.APP_PREFIX, picocolors_1.default.blue(`Matched test/suite IDs: ${tests.join(', ')}`));
106
+ log_js_1.log.info(picocolors_1.default.blue(`Matched test/suite IDs: ${tests.join(', ')}`));
106
107
  if (command)
107
- console.log(constants_js_1.APP_PREFIX, picocolors_1.default.green(`Full Running Command: ${filteredCommand}`));
108
+ log_js_1.log.info(picocolors_1.default.green(`Full Running Command: ${filteredCommand}`));
108
109
  return;
109
110
  }
110
111
  if (command && command.split) {
@@ -112,7 +113,7 @@ program
112
113
  }
113
114
  }
114
115
  catch (err) {
115
- console.log(constants_js_1.APP_PREFIX, err.message || err);
116
+ log_js_1.log.info(err.message || err);
116
117
  return;
117
118
  }
118
119
  }
@@ -129,19 +130,19 @@ program
129
130
  await client.createRun(createRunParams);
130
131
  const runId = process.env.TESTOMATIO_RUN || process.env.runId;
131
132
  if (client.pipeStore.runUrl)
132
- console.log(constants_js_1.APP_PREFIX, `📊 Report URL: ${picocolors_1.default.magenta(client.pipeStore.runUrl)}`);
133
+ log_js_1.log.info(`📊 Report URL: ${picocolors_1.default.magenta(client.pipeStore.runUrl)}`);
133
134
  if (opts.kind !== 'manual') {
134
- console.log(constants_js_1.APP_PREFIX, `No command passed, so you need to run tests yourself:`);
135
- console.log(constants_js_1.APP_PREFIX, `TESTOMATIO_RUN=${runId} <command>`);
135
+ log_js_1.log.info(`No command passed, so you need to run tests yourself:`);
136
+ log_js_1.log.info(`TESTOMATIO_RUN=${runId} <command>`);
136
137
  }
137
138
  }
138
139
  else {
139
- console.log(constants_js_1.APP_PREFIX, '⚠️ No API key provided. Cannot create run without TESTOMATIO key.');
140
+ log_js_1.log.info('⚠️ No API key provided. Cannot create run without TESTOMATIO key.');
140
141
  process.exit(1);
141
142
  }
142
143
  return process.exit(0);
143
144
  }
144
- console.log(constants_js_1.APP_PREFIX, `🚀 Running`, picocolors_1.default.green(command));
145
+ log_js_1.log.info(`🚀 Running`, picocolors_1.default.green(command));
145
146
  const runTests = async () => {
146
147
  const testCmds = command.split(' ');
147
148
  const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), {
@@ -150,7 +151,7 @@ program
150
151
  });
151
152
  cmd.on('close', async (code) => {
152
153
  const emoji = code === 0 ? '🟢' : '🔴';
153
- console.log(constants_js_1.APP_PREFIX, emoji, `Runner exited with ${picocolors_1.default.bold(code)}`);
154
+ log_js_1.log.info(emoji, `Runner exited with ${picocolors_1.default.bold(code)}`);
154
155
  if (apiKey) {
155
156
  const status = code === 0 ? 'passed' : 'failed';
156
157
  await client.updateRunStatus(status);
@@ -190,7 +191,7 @@ program
190
191
  // const runReader = new XmlReader({ javaTests, lang });
191
192
  // const files = glob.sync(pattern, { cwd: opts.dir || process.cwd() });
192
193
  // if (!files.length) {
193
- // console.log(APP_PREFIX, `Report can't be created. No XML files found 😥`);
194
+ // log.info( `Report can't be created. No XML files found 😥`);
194
195
  // process.exit(1);
195
196
  // }
196
197
  program
@@ -212,11 +213,11 @@ program
212
213
  const runReader = new xmlReader_js_1.default({ javaTests, lang });
213
214
  const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
214
215
  if (!files.length) {
215
- console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found 😥`);
216
+ log_js_1.log.info(`Report can't be created. No XML files found 😥`);
216
217
  process.exit(1);
217
218
  }
218
219
  for (const file of files) {
219
- console.log(constants_js_1.APP_PREFIX, `Parsed ${file}`);
220
+ log_js_1.log.info(`Parsed ${file}`);
220
221
  runReader.parse(file);
221
222
  }
222
223
  let timeoutTimer;
@@ -231,7 +232,7 @@ program
231
232
  await runReader.uploadData();
232
233
  }
233
234
  catch (err) {
234
- console.log(constants_js_1.APP_PREFIX, 'Error updating status, skipping...', err);
235
+ log_js_1.log.info('Error updating status, skipping...', err);
235
236
  }
236
237
  if (timeoutTimer)
237
238
  clearTimeout(timeoutTimer);
@@ -259,10 +260,10 @@ program
259
260
  if (!opts.force)
260
261
  testruns = testruns.filter(tr => !tr.uploaded);
261
262
  if (!testruns.length) {
262
- console.log(constants_js_1.APP_PREFIX, '🗄️ Total artifacts:', numTotalArtifacts);
263
+ log_js_1.log.info('🗄️ Total artifacts:', numTotalArtifacts);
263
264
  if (numTotalArtifacts) {
264
- console.log(constants_js_1.APP_PREFIX, 'No new artifacts to upload');
265
- console.log(constants_js_1.APP_PREFIX, 'To re-upload artifacts run this command with --force flag');
265
+ log_js_1.log.info('No new artifacts to upload');
266
+ log_js_1.log.info('To re-upload artifacts run this command with --force flag');
266
267
  }
267
268
  process.exit(0);
268
269
  }
@@ -281,7 +282,7 @@ program
281
282
  const files = testrunsByRid[rid];
282
283
  await client.addTestRun(undefined, { rid, files });
283
284
  }
284
- console.log(constants_js_1.APP_PREFIX, '🗄️', client.uploader.successfulUploads.length, 'artifacts 🟢uploaded');
285
+ log_js_1.log.info('🗄️', client.uploader.successfulUploads.length, 'artifacts 🟢uploaded');
285
286
  if (client.uploader.successfulUploads.length) {
286
287
  debug('\n', constants_js_1.APP_PREFIX, `🗄️ ${client.uploader.successfulUploads.length} artifacts uploaded to S3 bucket`);
287
288
  const uploadedArtifacts = client.uploader.successfulUploads.map(file => ({
@@ -316,34 +317,30 @@ program
316
317
  const replayService = new replay_js_1.default({
317
318
  apiKey: config_js_1.config.TESTOMATIO,
318
319
  dryRun: opts.dryRun,
319
- onLog: message => console.log(constants_js_1.APP_PREFIX, message),
320
- onError: message => console.error(constants_js_1.APP_PREFIX, '⚠️ ', message),
320
+ onLog: message => log_js_1.log.info(message),
321
+ onError: message => log_js_1.log.error('⚠️ ', message),
321
322
  onProgress: ({ current, total }) => {
322
323
  if (current % 10 === 0 || current === total) {
323
- console.log(constants_js_1.APP_PREFIX, `📊 Progress: ${current}/${total} tests processed`);
324
+ log_js_1.log.info(`📊 Progress: ${current}/${total} tests processed`);
324
325
  }
325
326
  },
326
327
  });
327
328
  const result = await replayService.replay(debugFile);
328
329
  if (result.dryRun) {
329
- console.log(constants_js_1.APP_PREFIX, '🔍 Dry run completed:');
330
- console.log(constants_js_1.APP_PREFIX, ` - Tests found: ${result.testsCount}`);
331
- console.log(constants_js_1.APP_PREFIX, ` - Environment variables: ${Object.keys(result.envVars).length}`);
332
- console.log(constants_js_1.APP_PREFIX, ` - Run parameters:`, result.runParams);
333
- console.log(constants_js_1.APP_PREFIX, ' Use without --dry-run to actually send the data');
330
+ log_js_1.log.info('🔍 Dry run completed:\n', ` - Tests found: ${result.testsCount}\n`, ` - Environment variables: ${Object.keys(result.envVars).length}\n`, ' - Run parameters:', result.runParams, '\n', ' Use without --dry-run to actually send the data');
334
331
  }
335
332
  else {
336
- console.log(constants_js_1.APP_PREFIX, `✅ Successfully replayed ${result.successCount}/${result.testsCount} tests`);
333
+ log_js_1.log.info(`✅ Successfully replayed ${result.successCount}/${result.testsCount} tests`);
337
334
  if (result.failureCount > 0) {
338
- console.log(constants_js_1.APP_PREFIX, `⚠️ ${result.failureCount} tests failed to upload`);
335
+ log_js_1.log.info(`⚠️ ${result.failureCount} tests failed to upload`);
339
336
  }
340
337
  }
341
338
  process.exit(0);
342
339
  }
343
340
  catch (err) {
344
- console.error(constants_js_1.APP_PREFIX, '❌ Error replaying debug data:', err.message);
341
+ log_js_1.log.error('❌ Error replaying debug data:', err.message);
345
342
  if (err.message.includes('Debug file not found')) {
346
- console.error(constants_js_1.APP_PREFIX, '💡 Hint: Run tests with TESTOMATIO_DEBUG=1 to generate debug files');
343
+ log_js_1.log.error('💡 Hint: Run tests with TESTOMATIO_DEBUG=1 to generate debug files');
347
344
  }
348
345
  process.exit(1);
349
346
  }
@@ -8,11 +8,10 @@ const commander_1 = require("commander");
8
8
  const picocolors_1 = __importDefault(require("picocolors"));
9
9
  const glob_1 = require("glob");
10
10
  const debug_1 = __importDefault(require("debug"));
11
- const constants_js_1 = require("../constants.js");
12
11
  const xmlReader_js_1 = __importDefault(require("../xmlReader.js"));
13
12
  const utils_js_1 = require("../utils/utils.js");
14
13
  const dotenv_1 = __importDefault(require("dotenv"));
15
- const path_1 = __importDefault(require("path"));
14
+ const log_js_1 = require("../utils/log.js");
16
15
  const version = (0, utils_js_1.getPackageVersion)();
17
16
  const debug = (0, debug_1.default)('@testomatio/reporter:xml-cli');
18
17
  console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io XML Reporter v${version}`)));
@@ -30,7 +29,7 @@ program
30
29
  }
31
30
  let { javaTests, lang } = opts;
32
31
  if (opts.envFile) {
33
- console.log(constants_js_1.APP_PREFIX, 'Loading env file:', opts.envFile);
32
+ log_js_1.log.info('Loading env file:', opts.envFile);
34
33
  debug('Loading env file: %s', opts.envFile);
35
34
  dotenv_1.default.config({ path: opts.envFile });
36
35
  }
@@ -43,12 +42,12 @@ program
43
42
  });
44
43
  const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
45
44
  if (!files.length) {
46
- console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found 😥`);
45
+ log_js_1.log.info(`Report can't be created. No XML files found 😥`);
47
46
  process.exitCode = 1;
48
47
  return;
49
48
  }
50
49
  for (const file of files) {
51
- console.log(constants_js_1.APP_PREFIX, `Parsed ${file}`);
50
+ log_js_1.log.info(`Parsed ${file}`);
52
51
  runReader.parse(file);
53
52
  }
54
53
  let timeoutTimer;
@@ -63,7 +62,7 @@ program
63
62
  await runReader.uploadData();
64
63
  }
65
64
  catch (err) {
66
- console.log(constants_js_1.APP_PREFIX, 'Error updating status, skipping...', err);
65
+ log_js_1.log.info('Error updating status, skipping...', err);
67
66
  }
68
67
  if (timeoutTimer)
69
68
  clearTimeout(timeoutTimer);
@@ -8,11 +8,11 @@ const commander_1 = require("commander");
8
8
  const picocolors_1 = __importDefault(require("picocolors"));
9
9
  const debug_1 = __importDefault(require("debug"));
10
10
  const client_js_1 = __importDefault(require("../client.js"));
11
- const constants_js_1 = require("../constants.js");
12
11
  const utils_js_1 = require("../utils/utils.js");
13
12
  const config_js_1 = require("../config.js");
14
13
  const utils_js_2 = require("../utils/utils.js");
15
14
  const dotenv_1 = __importDefault(require("dotenv"));
15
+ const log_js_1 = require("../utils/log.js");
16
16
  const debug = (0, debug_1.default)('@testomatio/reporter:upload-cli');
17
17
  const version = (0, utils_js_1.getPackageVersion)();
18
18
  console.log(picocolors_1.default.cyan(picocolors_1.default.bold(` 🤩 Testomat.io Reporter v${version}`)));
@@ -45,10 +45,10 @@ program
45
45
  if (!opts.force)
46
46
  testruns = testruns.filter(tr => !tr.uploaded);
47
47
  if (!testruns.length) {
48
- console.log(constants_js_1.APP_PREFIX, 'Total artifacts:', numTotalArtifacts);
48
+ log_js_1.log.info('Total artifacts:', numTotalArtifacts);
49
49
  if (numTotalArtifacts) {
50
- console.log(constants_js_1.APP_PREFIX, 'No new artifacts to upload');
51
- console.log(constants_js_1.APP_PREFIX, 'To re-upload artifacts run this command with --force flag');
50
+ log_js_1.log.info('No new artifacts to upload');
51
+ log_js_1.log.info('To re-upload artifacts run this command with --force flag');
52
52
  }
53
53
  process.exit(0);
54
54
  }
@@ -71,9 +71,9 @@ program
71
71
  files,
72
72
  });
73
73
  }
74
- console.log(constants_js_1.APP_PREFIX, client.uploader.successfulUploads.length, 'artifacts uploaded');
74
+ log_js_1.log.info(client.uploader.successfulUploads.length, 'artifacts uploaded');
75
75
  if (client.uploader.failedUploads.length) {
76
- console.log(constants_js_1.APP_PREFIX, client.uploader.failedUploads.length, 'artifacts failed to upload');
76
+ log_js_1.log.info(client.uploader.failedUploads.length, 'artifacts failed to upload');
77
77
  }
78
78
  });
79
79
  if (process.argv.length <= 1) {
package/lib/client.d.ts CHANGED
@@ -45,6 +45,14 @@ export class Client {
45
45
  * @returns {Promise<any>} - resolves to Run id which should be used to update / add test
46
46
  */
47
47
  createRun(params?: {}): Promise<any>;
48
+ /**
49
+ * Recursively uploads artifacts from steps
50
+ *
51
+ * @param {*} steps - Steps payload (validated inside function)
52
+ * @param {string} testRid - Test/result ID
53
+ * @returns {Promise<void>}
54
+ */
55
+ uploadStepArtifacts(steps: any, testRid: string): Promise<void>;
48
56
  /**
49
57
  * Updates test status and its data
50
58
  *