@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
package/src/client.js CHANGED
@@ -1,15 +1,17 @@
1
1
  import createDebugMessages from 'debug';
2
2
  import fs from 'fs';
3
3
  import pc from 'picocolors';
4
- import { APP_PREFIX, STATUS } from './constants.js';
4
+ import { APP_PREFIX, STATUS, SCREENSHOTS_ON_STEPS } from './constants.js';
5
5
  import { pipesFactory } from './pipe/index.js';
6
6
  import { glob } from 'glob';
7
7
  import path from 'path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
  import { S3Uploader } from './uploader.js';
10
- import { readLatestRunId, storeRunId, validateSuiteId, transformEnvVarToBoolean } from './utils/utils.js';
10
+ import { readLatestRunId, storeRunId, validateSuiteId, transformEnvVarToBoolean, isHttpUrl } from './utils/utils.js';
11
+ import { generateShortFilename } from './adapter/utils/step-formatter.js';
11
12
  import { filesize as prettyBytes } from 'filesize';
12
13
  import { formatLogs, formatError, stripColors } from './utils/log-formatter.js';
14
+ import { log } from './utils/log.js';
13
15
 
14
16
  const debug = createDebugMessages('@testomatio/reporter:client');
15
17
 
@@ -40,7 +42,7 @@ class Client {
40
42
  const pathToPackageJSON = path.join(__dirname, '../package.json');
41
43
  try {
42
44
  this.version = JSON.parse(fs.readFileSync(pathToPackageJSON).toString()).version;
43
- console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
45
+ log.info(`Testomatio Reporter v${this.version}`);
44
46
  } catch (e) {
45
47
  // do nothing
46
48
  }
@@ -71,7 +73,7 @@ class Client {
71
73
 
72
74
  // ❗ Validation: pipe is required
73
75
  if (!pipe || !pipeOptions) {
74
- console.warn(`❗ No valid pipe found in filter cmd. Expected format: <pipe>:<options>
76
+ log.warn(`❗ No valid pipe found in filter cmd. Expected format: <pipe>:<options>
75
77
  Examples:
76
78
  --filter "testomatio:tag-name=frontend"
77
79
  --filter "coverage:file=coverage.yml"
@@ -92,10 +94,7 @@ class Client {
92
94
  // const p = this.pipes.find(p => p.id === `${pipe.toLowerCase()}`); TODO: as future updates
93
95
 
94
96
  if (!p?.isEnabled) {
95
- console.warn(
96
- APP_PREFIX,
97
- "🚫 No active pipes were found in the system. Execution aborted!"
98
- );
97
+ log.warn('🚫 No active pipes were found in the system. Execution aborted!');
99
98
  return;
100
99
  }
101
100
 
@@ -107,7 +106,7 @@ class Client {
107
106
 
108
107
  return result;
109
108
  } catch (err) {
110
- console.error(APP_PREFIX, err);
109
+ log.error(err);
111
110
  }
112
111
  }
113
112
 
@@ -125,7 +124,7 @@ class Client {
125
124
 
126
125
  this.queue = this.queue
127
126
  .then(() => Promise.all(this.pipes.map(p => p.createRun(params))))
128
- .catch(err => console.log(APP_PREFIX, err))
127
+ .catch(err => log.info(err))
129
128
  .then(() => {
130
129
  const runId = this.pipeStore?.runId;
131
130
  if (runId) this.runId = runId;
@@ -137,6 +136,60 @@ class Client {
137
136
  return this.queue;
138
137
  }
139
138
 
139
+ /**
140
+ * Recursively uploads artifacts from steps
141
+ *
142
+ * @param {*} steps - Steps payload (validated inside function)
143
+ * @param {string} testRid - Test/result ID
144
+ * @returns {Promise<void>}
145
+ */
146
+ async uploadStepArtifacts(steps, testRid) {
147
+ if (!steps || !Array.isArray(steps)) return;
148
+ if (!this.uploader.isEnabled || !SCREENSHOTS_ON_STEPS) return;
149
+
150
+ try {
151
+ for (const step of steps) {
152
+ if (!(step.artifacts && Array.isArray(step.artifacts))) {
153
+ if (step.steps) {
154
+ await this.uploadStepArtifacts(step.steps, testRid);
155
+ }
156
+ continue;
157
+ }
158
+
159
+ const uploadedArtifacts = [];
160
+ for (const artifact of step.artifacts) {
161
+ if (typeof artifact === 'string' && !isHttpUrl(artifact)) {
162
+ const filename = generateShortFilename(artifact);
163
+ try {
164
+ const uploadResult = await this.uploader.uploadFileByPath(
165
+ artifact,
166
+ [this.runId, testRid, 'steps', filename]
167
+ );
168
+ if (uploadResult) {
169
+ uploadedArtifacts.push(uploadResult);
170
+ } else {
171
+ uploadedArtifacts.push(artifact);
172
+ }
173
+ } catch (uploadErr) {
174
+ uploadedArtifacts.push(artifact);
175
+ }
176
+ } else {
177
+ uploadedArtifacts.push(artifact);
178
+ }
179
+ }
180
+ step.artifacts = uploadedArtifacts;
181
+
182
+ if (step.steps) {
183
+ await this.uploadStepArtifacts(step.steps, testRid);
184
+ }
185
+ }
186
+
187
+ } catch (err) {
188
+ console.error(APP_PREFIX, 'Error in uploadStepArtifacts for testRid', testRid, ':', err);
189
+ throw err;
190
+ }
191
+ }
192
+
140
193
  /**
141
194
  * Updates test status and its data
142
195
  *
@@ -162,6 +215,13 @@ class Client {
162
215
  const { rid, error = null, steps: originalSteps, title, suite_title } = testData;
163
216
  let steps = originalSteps;
164
217
 
218
+ // Upload artifacts from steps
219
+ try {
220
+ await this.uploadStepArtifacts(steps, rid);
221
+ } catch (err) {
222
+ console.log(APP_PREFIX, 'Failed to upload step artifacts:', err);
223
+ }
224
+
165
225
  const uploadedFiles = [];
166
226
  const stackArtifactsEnabled = transformEnvVarToBoolean(process.env.TESTOMATIO_STACK_ARTIFACTS);
167
227
 
@@ -286,7 +346,7 @@ class Client {
286
346
  const result = await pipe.addTest(data);
287
347
  return { pipe: pipe.toString(), result };
288
348
  } catch (err) {
289
- console.log(APP_PREFIX, pipe.toString(), err);
349
+ log.info(pipe.toString(), err);
290
350
  }
291
351
  }),
292
352
  ),
@@ -341,10 +401,7 @@ class Client {
341
401
  }
342
402
 
343
403
  if (this.uploader.failedUploads.length) {
344
- console.log(
345
- APP_PREFIX,
346
- `🗄️ ${this.uploader.failedUploads.length} artifacts 🔴${pc.bold('failed')} to upload`,
347
- );
404
+ log.info(`🗄️ ${this.uploader.failedUploads.length} artifacts 🔴${pc.bold('failed')} to upload`);
348
405
  const failedUploads = this.uploader.failedUploads.map(file => ({
349
406
  relativePath: file.path.replace(process.cwd(), ''),
350
407
  sizePretty: file.size == null ? 'unknown' : prettyBytes(file.size, { round: 0 }).toString(),
@@ -362,11 +419,7 @@ class Client {
362
419
  }
363
420
 
364
421
  if (this.uploader.skippedUploads.length) {
365
- console.log(
366
- '\n',
367
- APP_PREFIX,
368
- `🗄️ ${pc.bold(this.uploader.skippedUploads.length)} artifacts uploading 🟡${pc.bold('skipped')}`,
369
- );
422
+ log.info(`🗄️ ${pc.bold(this.uploader.skippedUploads.length)} artifacts uploading 🟡${pc.bold('skipped')}`);
370
423
  const skippedUploads = this.uploader.skippedUploads.map(file => ({
371
424
  relativePath: file.path.replace(process.cwd(), ''),
372
425
  sizePretty: file.size === null ? 'unknown' : prettyBytes(file.size, { round: 0 }).toString(),
@@ -386,14 +439,11 @@ class Client {
386
439
  this.runId
387
440
  } npx @testomatio/reporter upload-artifacts`;
388
441
  const numberOfNotUploadedArtifacts = this.uploader.skippedUploads.length + this.uploader.failedUploads.length;
389
- console.log(
390
- APP_PREFIX,
391
- `${numberOfNotUploadedArtifacts} artifacts were not uploaded.
392
- Run "${pc.magenta(command)}" with valid S3 credentials to upload skipped & failed artifacts`,
393
- );
442
+ log.info(`${numberOfNotUploadedArtifacts} artifacts were not uploaded.
443
+ Run "${pc.magenta(command)}" with valid S3 credentials to upload skipped & failed artifacts`);
394
444
  }
395
445
  })
396
- .catch(err => console.log(APP_PREFIX, err));
446
+ .catch(err => log.info(err));
397
447
 
398
448
  return this.queue;
399
449
  }
package/src/constants.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import pc from 'picocolors';
2
2
  import os from 'os';
3
3
  import path from 'path';
4
+ import { transformEnvVarToBoolean } from './utils/utils.js';
4
5
 
5
6
  const APP_PREFIX = pc.gray('[TESTOMATIO]');
6
7
  const TESTOMATIO_REQUEST_TIMEOUT = parseInt(process.env.TESTOMATIO_REQUEST_TIMEOUT, 10);
@@ -8,6 +9,8 @@ if (TESTOMATIO_REQUEST_TIMEOUT) {
8
9
  console.log(`${APP_PREFIX} Request timeout is set to ${TESTOMATIO_REQUEST_TIMEOUT / 1000}s`);
9
10
  }
10
11
  const AXIOS_TIMEOUT = TESTOMATIO_REQUEST_TIMEOUT || 20 * 1000;
12
+ const SCREENSHOTS_ON_STEPS = process.env.TESTOMATIO_SCREENSHOTS_ON_STEPS == null
13
+ || transformEnvVarToBoolean(process.env.TESTOMATIO_SCREENSHOTS_ON_STEPS);
11
14
 
12
15
  const TESTOMAT_TMP_STORAGE_DIR = path.join(os.tmpdir(), 'testomatio_tmp');
13
16
 
@@ -50,4 +53,5 @@ export {
50
53
  AXIOS_TIMEOUT,
51
54
  testomatLogoURL,
52
55
  REPORTER_REQUEST_RETRIES,
56
+ SCREENSHOTS_ON_STEPS,
53
57
  };
@@ -7,6 +7,7 @@ import humanizeDuration from 'humanize-duration';
7
7
  import merge from 'lodash.merge';
8
8
  import path from 'path';
9
9
  import createDebugMessages from 'debug';
10
+ import { log } from '../utils/log.js';
10
11
 
11
12
  const debug = createDebugMessages('@testomatio/reporter:pipe:bitbucket');
12
13
 
@@ -193,7 +194,7 @@ export class BitbucketPipe {
193
194
  // eslint-disable-next-line max-len
194
195
  const commentURL = `https://bitbucket.org/${this.ENV.BITBUCKET_WORKSPACE}/${this.ENV.BITBUCKET_REPO_SLUG}/pull-requests/${this.ENV.BITBUCKET_PR_ID}#comment-${commentID}`;
195
196
 
196
- console.log(APP_PREFIX, pc.yellow('Bitbucket'), `Report created: ${pc.magenta(commentURL)}`);
197
+ log.info(pc.yellow('Bitbucket'), `Report created: ${pc.magenta(commentURL)}`);
197
198
  } catch (err) {
198
199
  console.error(
199
200
  APP_PREFIX,
@@ -9,6 +9,7 @@ import { generateFilterRequestParams } from '../utils/pipe_utils.js';
9
9
  import { parsePipeOptions } from '../utils/pipe_utils.js';
10
10
  import { config } from '../config.js';
11
11
  import createDebugMessages from 'debug';
12
+ import { log } from '../utils/log.js';
12
13
 
13
14
  const debug = createDebugMessages('@testomatio/reporter:pipe:csv');
14
15
 
@@ -136,11 +137,11 @@ class CoveragePipe { // or Changes for the future???
136
137
  // Step 2: Extract all available tests and compare with coverage file
137
138
  const lines = await this.extractRelevantTestsFromChanges();
138
139
  if (this.store?.filterList && lines.size > 0) {
139
- console.log(APP_PREFIX, `Matched files: ${[...lines].join(', ')}`);
140
+ log.info( `Matched files: ${[...lines].join(', ')}`);
140
141
  }
141
142
 
142
143
  if (lines.size === 0) {
143
- console.log(APP_PREFIX, 'ℹ️ No matching entries in coverage file for provided Git changes.');
144
+ log.info( 'ℹ️ No matching entries in coverage file for provided Git changes.');
144
145
  return [];
145
146
  }
146
147
 
@@ -164,7 +165,7 @@ class CoveragePipe { // or Changes for the future???
164
165
  }
165
166
 
166
167
  if (this.tests.size === 0 && this.suiteIds.size === 0) {
167
- console.log(APP_PREFIX, 'ℹ️ No tests found for execution based on Git changes.');
168
+ log.info( 'ℹ️ No tests found for execution based on Git changes.');
168
169
  return [];
169
170
  }
170
171
 
@@ -235,7 +236,7 @@ class CoveragePipe { // or Changes for the future???
235
236
  });
236
237
 
237
238
  if (!Array.isArray(resp.data?.tests) && resp.data?.tests?.length === 0) {
238
- console.log(APP_PREFIX, `🔍 No test by ${type}=${id} were found on the Testomat.io server side!`);
239
+ log.info( `🔍 No test by ${type}=${id} were found on the Testomat.io server side!`);
239
240
 
240
241
  return undefined;
241
242
  }
@@ -275,7 +276,7 @@ class CoveragePipe { // or Changes for the future???
275
276
  const errorMessage = err.message || '';
276
277
  // Git edge: Not a git repository or other error
277
278
  if (errorMessage.includes('Not a git repository')) {
278
- console.error(APP_PREFIX, '❌ Error: This folder is not a Git repository.');
279
+ log.error( '❌ Error: This folder is not a Git repository.');
279
280
  }
280
281
  else {
281
282
  throw new Error(`❌ Git command failed ("${cmd}"):\n`, errorMessage);
@@ -319,11 +320,11 @@ class CoveragePipe { // or Changes for the future???
319
320
  cmd = this.#buildGitCommand();
320
321
  }
321
322
  catch (err) {
322
- console.error(APP_PREFIX, err.message);
323
+ log.error( err.message);
323
324
  return undefined;
324
325
  }
325
326
 
326
- console.error(APP_PREFIX, `ℹ️ We will use '${cmd}' Git command.`);
327
+ log.error( `ℹ️ We will use '${cmd}' Git command.`);
327
328
 
328
329
  try {
329
330
  // For clear unit testing process -> Like test_defaultGitChangedFile = todomvc-tests/edit-todos_test.js
@@ -344,12 +345,12 @@ class CoveragePipe { // or Changes for the future???
344
345
  }
345
346
  }
346
347
  catch (err) {
347
- console.error(APP_PREFIX, err.message);
348
- console.error(APP_PREFIX, "🔍 Pls, check this Git command manually to understand the original problem.");
348
+ log.error( err.message);
349
+ log.error( "🔍 Pls, check this Git command manually to understand the original problem.");
349
350
  return undefined;
350
351
  }
351
352
 
352
- console.log(APP_PREFIX, `📑 GIT changed files:\n - ${this.changedFiles.join('\n - ')}`);
353
+ log.info( `📑 GIT changed files:\n - ${this.changedFiles.join('\n - ')}`);
353
354
  return this;
354
355
  }
355
356
 
@@ -369,20 +370,20 @@ class CoveragePipe { // or Changes for the future???
369
370
  validateCoverageFile() {
370
371
  // Validate the presence of the coverage filepath
371
372
  if (!fs.existsSync(this.coverageFilePath)) {
372
- console.log(APP_PREFIX, '❌ Coverage file not found:', this.coverageFilePath);
373
+ log.info( '❌ Coverage file not found:', this.coverageFilePath);
373
374
  return undefined;
374
375
  }
375
376
 
376
377
  // Ensure the given path is a file (not a directory or other type)
377
378
  const stat = fs.statSync(this.coverageFilePath);
378
379
  if (!stat.isFile()) {
379
- console.log(APP_PREFIX, '❌ Provided coverage path is not a file:', this.coverageFilePath);
380
+ log.info( '❌ Provided coverage path is not a file:', this.coverageFilePath);
380
381
  return undefined;
381
382
  }
382
383
 
383
384
  // Validate the file extension to be ".yml" to ensure it's a YAML file
384
385
  if (path.extname(this.coverageFilePath) !== ".yml") {
385
- console.log(APP_PREFIX, '❌ Coverage file must have a .yml extension:', this.coverageFilePath);
386
+ log.info( '❌ Coverage file must have a .yml extension:', this.coverageFilePath);
386
387
  return undefined;
387
388
  }
388
389
 
@@ -408,12 +409,12 @@ class CoveragePipe { // or Changes for the future???
408
409
  this.parsedCoverage = yaml.load(rawYml) || {};
409
410
 
410
411
  debug(`Coverage filepath = ${this.coverageFilePath})`);
411
- console.log(APP_PREFIX, `✅ Coverage file parsed successfully: ${this.coverageFilePath}`);
412
+ log.info( `✅ Coverage file parsed successfully: ${this.coverageFilePath}`);
412
413
 
413
414
  return this;
414
415
  }
415
416
  catch (err) {
416
- console.error(APP_PREFIX, '❌ Failed to parse YAML:', err.message);
417
+ log.error( '❌ Failed to parse YAML:', err.message);
417
418
  return undefined;
418
419
  }
419
420
  }
package/src/pipe/debug.js CHANGED
@@ -2,8 +2,8 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import os from 'os';
4
4
  import createDebugMessages from 'debug';
5
- import { APP_PREFIX } from '../constants.js';
6
5
  import prettyMs from 'pretty-ms';
6
+ import { log } from '../utils/log.js';
7
7
 
8
8
  const debug = createDebugMessages('@testomatio/reporter:pipe:debug');
9
9
 
@@ -40,7 +40,7 @@ export class DebugPipe {
40
40
  debug('Failed to create symlink:', err.message);
41
41
  }
42
42
 
43
- console.log(APP_PREFIX, '🪲 Debug file created');
43
+ log.info('🪲 Debug file created');
44
44
  this.testomatioEnvVars = Object.keys(process.env)
45
45
  .filter(key => key.startsWith('TESTOMATIO_'))
46
46
  .reduce((acc, key) => {
@@ -115,7 +115,7 @@ export class DebugPipe {
115
115
  await this.sync();
116
116
  if (this.batch.intervalFunction) clearInterval(this.batch.intervalFunction);
117
117
  this.logToFile({ action: 'finishRun', params });
118
- console.log(APP_PREFIX, '🪲 Debug Saved to', this.logFilePath);
118
+ log.info('🪲 Debug Saved to', this.logFilePath);
119
119
  }
120
120
 
121
121
  async sync() {
@@ -3,9 +3,10 @@ import path from 'path';
3
3
  import pc from 'picocolors';
4
4
  import humanizeDuration from 'humanize-duration';
5
5
  import merge from 'lodash.merge';
6
- import { APP_PREFIX, testomatLogoURL } from '../constants.js';
6
+ import { testomatLogoURL } from '../constants.js';
7
7
  import { ansiRegExp, isSameTest } from '../utils/utils.js';
8
8
  import { statusEmoji, fullName } from '../utils/pipe_utils.js';
9
+ import { log } from '../utils/log.js';
9
10
 
10
11
  const debug = createDebugMessages('@testomatio/reporter:pipe:github');
11
12
 
@@ -191,9 +192,9 @@ class GitHubPipe {
191
192
  debug('Comment URL:', url);
192
193
  this.store.githubUrl = url;
193
194
 
194
- console.log(APP_PREFIX, pc.yellow('GitHub'), `Report created: ${pc.magenta(url)}`);
195
+ log.info(pc.yellow('GitHub'), `Report created: ${pc.magenta(url)}`);
195
196
  } catch (err) {
196
- console.log(APP_PREFIX, pc.yellow('GitHub'), `Couldn't create GitHub report ${err}`);
197
+ log.info(pc.yellow('GitHub'), `Couldn't create GitHub report ${err}`);
197
198
  }
198
199
  }
199
200
 
@@ -7,6 +7,7 @@ import path from 'path';
7
7
  import { APP_PREFIX, testomatLogoURL } from '../constants.js';
8
8
  import { ansiRegExp, isSameTest } from '../utils/utils.js';
9
9
  import { statusEmoji, fullName } from '../utils/pipe_utils.js';
10
+ import { log } from '../utils/log.js';
10
11
 
11
12
  const debug = createDebugMessages('@testomatio/reporter:pipe:gitlab');
12
13
 
@@ -183,7 +184,7 @@ class GitLabPipe {
183
184
  // eslint-disable-next-line max-len
184
185
  const commentURL = `${this.ENV.CI_PROJECT_URL}/-/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}#note_${commentID}`;
185
186
 
186
- console.log(APP_PREFIX, pc.yellow('GitLab'), `Report created: ${pc.magenta(commentURL)}`);
187
+ log.info(pc.yellow('GitLab'), `Report created: ${pc.magenta(commentURL)}`);
187
188
  } catch (err) {
188
189
  console.error(
189
190
  APP_PREFIX,
package/src/pipe/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import pc from 'picocolors';
4
- import { APP_PREFIX } from '../constants.js';
5
4
  import TestomatioPipe from './testomatio.js';
6
5
  import GitHubPipe from './github.js';
7
6
  import GitLabPipe from './gitlab.js';
@@ -10,6 +9,7 @@ import HtmlPipe from './html.js';
10
9
  import CoveragePipe from './coverage.js';
11
10
  import { BitbucketPipe } from './bitbucket.js';
12
11
  import { DebugPipe } from './debug.js';
12
+ import { log } from '../utils/log.js';
13
13
 
14
14
  export async function pipesFactory(params, opts) {
15
15
  const extraPipes = [];
@@ -29,14 +29,14 @@ export async function pipesFactory(params, opts) {
29
29
  try {
30
30
  PipeClass = await import(pipeDef);
31
31
  } catch (err) {
32
- console.log(APP_PREFIX, `Can't load module Testomatio pipe module from ${pipeDef}`);
32
+ log.info(`Can't load module Testomatio pipe module from ${pipeDef}`);
33
33
  continue;
34
34
  }
35
35
 
36
36
  try {
37
37
  extraPipes.push(new PipeClass(params, opts));
38
38
  } catch (err) {
39
- console.log(APP_PREFIX, `Can't instantiate Testomatio for ${pipeDef}`, err);
39
+ log.info(`Can't instantiate Testomatio for ${pipeDef}`, err);
40
40
  continue;
41
41
  }
42
42
  }
@@ -56,15 +56,13 @@ export async function pipesFactory(params, opts) {
56
56
 
57
57
  const pipesEnabled = pipes.filter(p => p.isEnabled);
58
58
 
59
- console.log(
60
- APP_PREFIX,
59
+ log.info(
61
60
  pc.cyan('Pipes:'),
62
61
  pc.cyan(pipesEnabled.map(p => p.toString()).join(', ') || 'No pipes enabled'),
63
62
  );
64
63
 
65
64
  if (!pipesEnabled.length) {
66
- console.log(
67
- APP_PREFIX,
65
+ log.info(
68
66
  pc.dim('If you want to use Testomatio reporter, pass your token as TESTOMATIO env variable'),
69
67
  );
70
68
  }
@@ -12,6 +12,7 @@ import {
12
12
  } from '../utils/utils.js';
13
13
  import { parseFilterParams, generateFilterRequestParams, setS3Credentials } from '../utils/pipe_utils.js';
14
14
  import { config } from '../config.js';
15
+ import { log } from '../utils/log.js';
15
16
 
16
17
  const debug = createDebugMessages('@testomatio/reporter:pipe:testomatio');
17
18
 
@@ -65,10 +66,12 @@ class TestomatioPipe {
65
66
  const sha = getGitCommitSha();
66
67
  if (sha) {
67
68
  this.title = `Shared Run - ${sha}`;
68
- console.log(APP_PREFIX, `🔄 Auto-generated title for shared run: ${this.title}`);
69
+ log.info(`🔄 Auto-generated title for shared run: ${this.title}`);
69
70
  } else {
70
- console.log(APP_PREFIX, pc.red('Failed to resolve git commit SHA for shared run title.'));
71
- console.log(APP_PREFIX, 'Please run the tests inside a Git repository or set TESTOMATIO_TITLE explicitly.');
71
+ log.warn(
72
+ pc.red('Failed to resolve git commit SHA for shared run title.'),
73
+ 'Please run the tests inside a Git repository or set TESTOMATIO_TITLE explicitly.',
74
+ );
72
75
  }
73
76
  }
74
77
  this.groupTitle = params.groupTitle || process.env.TESTOMATIO_RUNGROUP_TITLE;
@@ -106,7 +109,7 @@ class TestomatioPipe {
106
109
 
107
110
  if (!isValidUrl(this.url.trim())) {
108
111
  this.isEnabled = false;
109
- console.error(APP_PREFIX, pc.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`));
112
+ log.error(pc.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`));
110
113
  }
111
114
  }
112
115
 
@@ -117,7 +120,7 @@ class TestomatioPipe {
117
120
  */
118
121
  #formatData(data) {
119
122
  data.api_key = this.apiKey;
120
- data.create = this.createNewTests;
123
+ if (data.create === undefined) data.create = this.createNewTests;
121
124
 
122
125
  // add test ID + run ID
123
126
  if (data.rid) data.rid = `${this.runId}-${data.rid}`;
@@ -177,9 +180,9 @@ class TestomatioPipe {
177
180
  return resp.data.tests;
178
181
  }
179
182
 
180
- console.log(APP_PREFIX, `⛔ No tests found for your --filter --> ${type}=${id}`);
183
+ log.warn(`⛔ No tests found for your --filter --> ${type}=${id}`);
181
184
  } catch (err) {
182
- console.error(APP_PREFIX, `🚩 Error getting Testomat.io test grepList: ${err}`);
185
+ log.error(`🚩 Error getting Testomat.io test grepList: ${err}`);
183
186
  }
184
187
  }
185
188
 
@@ -262,8 +265,8 @@ class TestomatioPipe {
262
265
  this.runPublicUrl = resp.data.public_url;
263
266
  this.store.runUrl = this.runUrl;
264
267
  this.store.runPublicUrl = this.runPublicUrl;
265
- console.log(APP_PREFIX, '📊 Using existing run. Report ID:', this.runId);
266
- console.log(APP_PREFIX, '📊 Report URL:', pc.magenta(this.runUrl));
268
+ log.info('📊 Using existing run. Report ID:', this.runId);
269
+ log.info('📊 Report URL:', pc.magenta(this.runUrl));
267
270
  }
268
271
  return;
269
272
  }
@@ -287,7 +290,7 @@ class TestomatioPipe {
287
290
  this.store.runUrl = this.runUrl;
288
291
  this.store.runPublicUrl = this.runPublicUrl;
289
292
  this.store.runId = this.runId;
290
- console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId);
293
+ log.info('📊 Report created. Report ID:', this.runId);
291
294
  process.env.runId = this.runId;
292
295
  debug('Run created', this.runId);
293
296
  } catch (err) {
@@ -355,7 +358,7 @@ class TestomatioPipe {
355
358
  this.#logFailedResponse(err);
356
359
  printCreateIssue();
357
360
  } else {
358
- console.log(APP_PREFIX, pc.blue(data?.title || ''), "Report couldn't be processed", err);
361
+ log.info(pc.blue(data?.title || ''), "Report couldn't be processed", err);
359
362
  }
360
363
  });
361
364
  };
@@ -406,7 +409,7 @@ class TestomatioPipe {
406
409
  this.#logFailedResponse(err);
407
410
  printCreateIssue();
408
411
  } else {
409
- console.log(APP_PREFIX, "Report couldn't be processed", err);
412
+ log.info("Report couldn't be processed", err);
410
413
  }
411
414
  });
412
415
  };
@@ -420,7 +423,7 @@ class TestomatioPipe {
420
423
 
421
424
  this.runId = this.runId || process.env.runId || this.store.runId || readLatestRunId();
422
425
  if (!this.runId) {
423
- console.warn(APP_PREFIX, pc.red('Run ID is not set, skipping test reporting'));
426
+ log.warn(pc.red('Run ID is not set, skipping test reporting'));
424
427
  return;
425
428
  }
426
429
 
@@ -495,21 +498,21 @@ class TestomatioPipe {
495
498
  });
496
499
 
497
500
  if (this.runUrl) {
498
- console.log(APP_PREFIX, '📊 Report Saved. Report URL:', pc.magenta(this.runUrl));
501
+ log.warn('📊 Report URL:', pc.magenta(this.runUrl));
499
502
  }
500
503
  if (this.runPublicUrl) {
501
- console.log(APP_PREFIX, '🌟 Public URL:', pc.magenta(this.runPublicUrl));
504
+ log.info('🌟 Public URL:', pc.magenta(this.runPublicUrl));
502
505
  }
503
506
  }
504
507
  if (this.runUrl && this.proceed) {
505
508
  const notFinishedMessage = pc.yellow(pc.bold('Run was not finished because of $TESTOMATIO_PROCEED'));
506
- console.log(APP_PREFIX, `📊 ${notFinishedMessage}. Report URL: ${pc.magenta(this.runUrl)}`);
507
- console.log(APP_PREFIX, `🛬 Run to finish it: TESTOMATIO_RUN=${this.runId} npx @testomatio/reporter finish`);
509
+ log.warn(`📊 ${notFinishedMessage}. Report URL: ${pc.magenta(this.runUrl)}`);
510
+ log.warn(`🛬 Run to finish it: TESTOMATIO_RUN=${this.runId} npx @testomatio/reporter finish`);
508
511
  }
509
512
 
510
513
  if (this.hasUnmatchedTests) {
511
514
  console.log('');
512
- console.log(APP_PREFIX, pc.yellow(pc.bold('⚠️ Some reported tests were not found in Testomat.io project')));
515
+ log.warn(pc.yellow(pc.bold('⚠️ Some reported tests were not found in Testomat.io project')));
513
516
  console.log(
514
517
  APP_PREFIX,
515
518
  `If you use Testomat.io as a reporter only, please re-run tests using ${pc.bold('TESTOMATIO_CREATE=1')}`,
@@ -518,14 +521,18 @@ class TestomatioPipe {
518
521
  APP_PREFIX,
519
522
  `But to keep your tests consistent it is recommended to ${pc.bold('import tests first')}`,
520
523
  );
521
- console.log(APP_PREFIX, 'If tests were imported but still not matched, assign test IDs to your tests.');
522
- console.log(APP_PREFIX, 'You can do that automatically via command line tools:');
523
- console.log(APP_PREFIX, pc.bold('npx check-tests ... --update-ids'), 'See: https://bit.ly/js-update-ids');
524
- console.log(APP_PREFIX, 'or for Cucumber:');
525
- console.log(APP_PREFIX, pc.bold('npx check-cucumber ... --update-ids'), 'See: https://bit.ly/bdd-update-ids');
524
+ log.info(
525
+ 'If tests were imported but still not matched, assign test IDs to your tests.',
526
+ 'You can do that automatically via command line tools:',
527
+ pc.bold('npx check-tests ... --update-ids'),
528
+ 'See: https://bit.ly/js-update-ids',
529
+ 'or for Cucumber:',
530
+ pc.bold('npx check-cucumber ... --update-ids'),
531
+ 'See: https://bit.ly/bdd-update-ids',
532
+ );
526
533
  }
527
534
  } catch (err) {
528
- console.log(APP_PREFIX, 'Error updating status, skipping...', err);
535
+ log.info('Error updating status, skipping...', err);
529
536
  if (process.env.DEBUG || process.env.TESTOMATIO_DEBUG) this.#logFailedResponse(err);
530
537
  printCreateIssue();
531
538
  }
@@ -541,7 +548,7 @@ class TestomatioPipe {
541
548
  clearInterval(this.batch.intervalFunction);
542
549
  this.batch.intervalFunction = null;
543
550
  this.batch.isEnabled = false;
544
- }
551
+ }
545
552
  this.batch.tests = [];
546
553
  }
547
554
 
package/src/uploader.js CHANGED
@@ -8,6 +8,7 @@ import promiseRetry from 'promise-retry';
8
8
  import pc from 'picocolors';
9
9
  import { APP_PREFIX } from './constants.js';
10
10
  import { filesize as prettyBytes } from 'filesize';
11
+ import { log } from './utils/log.js';
11
12
 
12
13
  const debug = createDebugMessages('@testomatio/reporter:file-uploader');
13
14
 
@@ -133,7 +134,7 @@ export class S3Uploader {
133
134
  } catch (e) {
134
135
  this.failedUploads.push({ path: file.path, size: file.size });
135
136
  debug('S3 uploading error:', e);
136
- console.log(APP_PREFIX, 'Upload failed:', e.message, '\nConfig:\n', this.getMaskedConfig());
137
+ log.info('Upload failed:', e.message, '\nConfig:\n', this.getMaskedConfig());
137
138
  }
138
139
  }
139
140
 
@@ -160,7 +161,7 @@ export class S3Uploader {
160
161
  const diffHours = diff / 1000 / 60 / 60;
161
162
  debug('Diff hours:', diffHours);
162
163
  if (diffHours > 3) {
163
- console.log(APP_PREFIX, "Artifacts file is too old, can't process artifacts. Please re-run the tests.");
164
+ log.info("Artifacts file is too old, can't process artifacts. Please re-run the tests.");
164
165
  return [];
165
166
  }
166
167