@testomatio/reporter 2.3.6-beta.2-fix-beforesuite → 2.3.7-beta.-stack-artifacts

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.
@@ -110,6 +110,25 @@ function CodeceptReporter(config) {
110
110
  output.stepShift = 2;
111
111
  index_js_1.services.setContext(null);
112
112
  });
113
+ // mark as failed all tests inside the failed hook
114
+ event.dispatcher.on(event.hook.failed, hook => {
115
+ if (hook.name !== 'BeforeSuiteHook')
116
+ return;
117
+ const suite = hook.runnable.parent;
118
+ if (!suite)
119
+ return;
120
+ const error = hook?.ctx?.currentTest?.err;
121
+ for (const test of suite.tests) {
122
+ client.addTestRun('failed', {
123
+ ...stripExampleFromTitle(test.title),
124
+ rid: test.uid,
125
+ test_id: (0, utils_js_1.getTestomatIdFromTestTitle)(test.title),
126
+ suite_title: stripTagsFromTitle(suite.title),
127
+ error,
128
+ time: hook?.runnable?.duration,
129
+ });
130
+ }
131
+ });
113
132
  event.dispatcher.on(event.suite.before, suite => {
114
133
  data_storage_js_1.dataStorage.setContext(suite.fullTitle());
115
134
  });
@@ -379,7 +398,7 @@ function formatCodeceptStep(step) {
379
398
  if (!step)
380
399
  return null;
381
400
  const category = step.constructor.name === 'HelperStep' ? 'framework' : 'user';
382
- const title = step.toString(); // Use built-in toString
401
+ const title = (0, utils_js_1.truncate)(step); // Use built-in toString
383
402
  const duration = step.duration || 0; // Use built-in duration
384
403
  const formattedStep = {
385
404
  category,
@@ -403,10 +422,11 @@ function formatHookStep(step) {
403
422
  if (step.actor && step.name) {
404
423
  title = `${step.actor} ${step.name}`;
405
424
  if (step.args && step.args.length > 0) {
406
- const argsStr = step.args.map(arg => JSON.stringify(arg)).join(', ');
425
+ const argsStr = step.args.map(arg => (0, utils_js_1.truncate)(JSON.stringify(arg))).join(', ');
407
426
  title += ` ${argsStr}`;
408
427
  }
409
428
  }
429
+ title = (0, utils_js_1.truncate)(title);
410
430
  return {
411
431
  category: 'hook',
412
432
  title,
package/lib/bin/cli.js CHANGED
File without changes
File without changes
File without changes
File without changes
package/lib/client.js CHANGED
@@ -51,7 +51,9 @@ const node_url_1 = require("node:url");
51
51
  const uploader_js_1 = require("./uploader.js");
52
52
  const utils_js_1 = require("./utils/utils.js");
53
53
  const filesize_1 = require("filesize");
54
+ const util_1 = require("util");
54
55
  const debug = (0, debug_1.default)('@testomatio/reporter:client');
56
+ const stripColors = util_1.stripVTControlCharacters || ((str) => str?.replace(/\x1b\[[0-9;]*m/g, '') || '');
55
57
  // removed __dirname usage, because:
56
58
  // 1. replaced with ESM syntax (import.meta.url), but it throws an error on tsc compilation;
57
59
  // 2. got error "__dirname already defined" in compiles js code (cjs dir)
@@ -158,17 +160,6 @@ class Client {
158
160
  * @returns {Promise<PipeResult[]>}
159
161
  */
160
162
  async addTestRun(status, testData) {
161
- if (!this.pipes || !this.pipes.length)
162
- this.pipes = await (0, index_js_1.pipesFactory)(this.paramsForPipesFactory || {}, this.pipeStore);
163
- // all pipes disabled, skipping
164
- if (!this.pipes?.filter(p => p.isEnabled).length)
165
- return [];
166
- if (isTestShouldBeExculedFromReport(testData))
167
- return [];
168
- if (status === constants_js_1.STATUS.SKIPPED && process.env.TESTOMATIO_EXCLUDE_SKIPPED) {
169
- debug('Skipping test from report', testData?.title);
170
- return []; // do not log skipped tests
171
- }
172
163
  if (!testData)
173
164
  testData = {
174
165
  title: 'Unknown test',
@@ -181,9 +172,12 @@ class Client {
181
172
  /**
182
173
  * @type {TestData}
183
174
  */
184
- const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, timestamp, links, manuallyAttachedArtifacts, overwrite, tags, } = testData;
175
+ const { rid, error = null, steps: originalSteps, title, suite_title, } = testData;
176
+ const steps = originalSteps;
177
+ const uploadedFiles = [];
178
+ const stackArtifactsEnabled = (0, utils_js_1.transformEnvVarToBoolean)(process.env.TESTOMATIO_STACK_ARTIFACTS);
179
+ const { time = 0, example = null, files = [], filesBuffers = [], code = null, file, suite_id, test_id, timestamp, links, manuallyAttachedArtifacts, overwrite, tags, } = testData;
185
180
  let { message = '', meta = {} } = testData;
186
- // stringify meta values and limit keys and values length to 255
187
181
  meta = Object.entries(meta)
188
182
  .filter(([, value]) => value !== null && value !== undefined)
189
183
  .reduce((acc, [key, value]) => {
@@ -191,19 +185,34 @@ class Client {
191
185
  acc[key] = value;
192
186
  return acc;
193
187
  }, {});
194
- // Get links from storage using the test context
195
188
  const testContext = suite_title ? `${suite_title} ${title}` : title;
196
189
  let errorFormatted = '';
197
190
  if (error) {
198
191
  errorFormatted += this.formatError(error) || '';
199
192
  message = error?.message;
200
193
  }
201
- // Attach logs
202
- const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
203
- // add artifacts
194
+ let fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
195
+ if (stackArtifactsEnabled) {
196
+ const timestamp = +new Date;
197
+ uploadedFiles.push(this.uploader.uploadFileAsBuffer(Buffer.from(stripColors(fullLogs), 'utf8'), [this.runId, rid, `logs_${timestamp}.log`]));
198
+ fullLogs = '';
199
+ }
200
+ if (!this.pipes || !this.pipes.length)
201
+ this.pipes = await (0, index_js_1.pipesFactory)(this.paramsForPipesFactory || {}, this.pipeStore);
202
+ if (!this.pipes?.filter(p => p.isEnabled).length) {
203
+ if (uploadedFiles.length > 0) {
204
+ await Promise.all(uploadedFiles);
205
+ }
206
+ return [];
207
+ }
208
+ if (isTestShouldBeExculedFromReport(testData))
209
+ return [];
210
+ if (status === constants_js_1.STATUS.SKIPPED && process.env.TESTOMATIO_EXCLUDE_SKIPPED) {
211
+ debug('Skipping test from report', testData?.title);
212
+ return [];
213
+ }
204
214
  if (manuallyAttachedArtifacts?.length)
205
215
  files.push(...manuallyAttachedArtifacts);
206
- const uploadedFiles = [];
207
216
  for (let f of files) {
208
217
  if (!f)
209
218
  continue; // f === null
@@ -329,7 +338,7 @@ class Client {
329
338
  */
330
339
  formatLogs({ error, steps, logs }) {
331
340
  error = error?.trim();
332
- logs = logs?.trim();
341
+ logs = logs?.trim().split('\n').map(l => (0, utils_js_1.truncate)(l)).join('\n');
333
342
  if (Array.isArray(steps)) {
334
343
  steps = steps
335
344
  .map(step => (0, utils_js_1.formatStep)(step))
@@ -410,7 +410,6 @@ class TestomatioPipe {
410
410
  tests: params.tests,
411
411
  }
412
412
  });
413
- console.log(constants_js_1.APP_PREFIX, '✅ Testrun finished');
414
413
  if (this.runUrl) {
415
414
  console.log(constants_js_1.APP_PREFIX, '📊 Report Saved. Report URL:', picocolors_1.default.magenta(this.runUrl));
416
415
  }
package/lib/reporter.d.ts CHANGED
@@ -1,3 +1,10 @@
1
+ export { Client };
2
+ export const STATUS: {
3
+ PASSED: string;
4
+ FAILED: string;
5
+ SKIPPED: string;
6
+ FINISHED: string;
7
+ };
1
8
  export const artifact: (data: string | {
2
9
  path: string;
3
10
  type: string;
@@ -80,7 +87,7 @@ export const label: (key: string, value?: string | null) => void;
80
87
  export const linkTest: (...testIds: string[]) => void;
81
88
  export const linkJira: (...jiraIds: string[]) => void;
82
89
  declare namespace _default {
83
- let testomatioLogger: {
90
+ export let testomatioLogger: {
84
91
  "__#13@#originalUserLogger": {
85
92
  assert(condition?: boolean, ...data: any[]): void;
86
93
  assert(value: any, message?: string, ...optionalParams: any[]): void;
@@ -148,13 +155,13 @@ declare namespace _default {
148
155
  }): void;
149
156
  prettyObjects: boolean;
150
157
  };
151
- let artifact: (data: string | {
158
+ export let artifact: (data: string | {
152
159
  path: string;
153
160
  type: string;
154
161
  name: string;
155
162
  }, context?: any) => void;
156
- let log: (...args: any[]) => void;
157
- let logger: {
163
+ export let log: (...args: any[]) => void;
164
+ export let logger: {
158
165
  "__#13@#originalUserLogger": {
159
166
  assert(condition?: boolean, ...data: any[]): void;
160
167
  assert(value: any, message?: string, ...optionalParams: any[]): void;
@@ -222,13 +229,15 @@ declare namespace _default {
222
229
  }): void;
223
230
  prettyObjects: boolean;
224
231
  };
225
- let meta: (keyValue: {
232
+ export let meta: (keyValue: {
226
233
  [key: string]: string;
227
234
  } | string, value?: string | null) => void;
228
- let step: (message: string) => void;
229
- let label: (key: string, value?: string | null) => void;
230
- let linkTest: (...testIds: string[]) => void;
231
- let linkJira: (...jiraIds: string[]) => void;
235
+ export let step: (message: string) => void;
236
+ export let label: (key: string, value?: string | null) => void;
237
+ export let linkTest: (...testIds: string[]) => void;
238
+ export let linkJira: (...jiraIds: string[]) => void;
239
+ export { Client as TestomatioClient };
240
+ export { STATUS };
232
241
  }
233
242
  export default _default;
234
243
  export type ArtifactFunction = typeof import("./reporter-functions.js").default.artifact;
@@ -237,3 +246,4 @@ export type LoggerService = typeof import("./services/index.js").services.logger
237
246
  export type MetaFunction = typeof import("./reporter-functions.js").default.keyValue;
238
247
  export type StepFunction = typeof import("./reporter-functions.js").default.step;
239
248
  export type LabelFunction = typeof import("./reporter-functions.js").default.label;
249
+ import Client from './client.js';
package/lib/reporter.js CHANGED
@@ -1,13 +1,48 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.linkJira = exports.linkTest = exports.label = exports.step = exports.meta = exports.logger = exports.log = exports.artifact = void 0;
7
- // import TestomatClient from './client.js';
8
- // import * as TRConstants from './constants.js';
39
+ exports.linkJira = exports.linkTest = exports.label = exports.step = exports.meta = exports.logger = exports.log = exports.artifact = exports.STATUS = exports.Client = void 0;
40
+ const client_js_1 = __importDefault(require("./client.js"));
41
+ exports.Client = client_js_1.default;
42
+ const TestomatioConstants = __importStar(require("./constants.js"));
9
43
  const index_js_1 = require("./services/index.js");
10
44
  const reporter_functions_js_1 = __importDefault(require("./reporter-functions.js"));
45
+ exports.STATUS = TestomatioConstants.STATUS;
11
46
  exports.artifact = reporter_functions_js_1.default.artifact;
12
47
  exports.log = reporter_functions_js_1.default.log;
13
48
  exports.logger = index_js_1.services.logger;
@@ -37,6 +72,6 @@ module.exports = {
37
72
  label: reporter_functions_js_1.default.label,
38
73
  linkTest: reporter_functions_js_1.default.linkTest,
39
74
  linkJira: reporter_functions_js_1.default.linkJira,
40
- // TestomatClient,
41
- // TRConstants,
75
+ TestomatioClient: client_js_1.default,
76
+ STATUS: exports.STATUS,
42
77
  };
@@ -2,6 +2,7 @@ export function getPackageVersion(): any;
2
2
  export const TEST_ID_REGEX: RegExp;
3
3
  export const SUITE_ID_REGEX: RegExp;
4
4
  export function ansiRegExp(): RegExp;
5
+ export function truncate(s: any, size?: number): any;
5
6
  export function cleanLatestRunId(): any;
6
7
  export function isSameTest(test: any, t: any): boolean;
7
8
  export function fetchSourceCode(contents: any, opts?: {}): string;
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.validateSuiteId = exports.testRunnerHelper = exports.specificTestInfo = exports.parseSuite = exports.isValidUrl = exports.humanize = exports.getTestomatIdFromTestTitle = exports.getCurrentDateTime = exports.foundedTestLog = exports.fileSystem = exports.fetchFilesFromStackTrace = exports.fetchIdFromOutput = exports.fetchIdFromCode = exports.fetchSourceCodeFromStackTrace = exports.fetchSourceCode = exports.isSameTest = exports.ansiRegExp = exports.SUITE_ID_REGEX = exports.TEST_ID_REGEX = void 0;
40
40
  exports.getPackageVersion = getPackageVersion;
41
+ exports.truncate = truncate;
41
42
  exports.cleanLatestRunId = cleanLatestRunId;
42
43
  exports.formatStep = formatStep;
43
44
  exports.readLatestRunId = readLatestRunId;
@@ -469,9 +470,17 @@ function transformEnvVarToBoolean(value) {
469
470
  // if not recognized, return truthy if any value is set
470
471
  return Boolean(value);
471
472
  }
473
+ function truncate(s, size = 255) {
474
+ if (s.toString().trim().length < size) {
475
+ return s.toString();
476
+ }
477
+ return `${s.toString().substring(0, size)}...`;
478
+ }
472
479
 
473
480
  module.exports.getPackageVersion = getPackageVersion;
474
481
 
482
+ module.exports.truncate = truncate;
483
+
475
484
  module.exports.cleanLatestRunId = cleanLatestRunId;
476
485
 
477
486
  module.exports.formatStep = formatStep;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "2.3.6-beta.2-fix-beforesuite",
3
+ "version": "2.3.7-beta.-stack-artifacts",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -2,7 +2,7 @@ import createDebugMessages from 'debug';
2
2
  import pc from 'picocolors';
3
3
  import TestomatClient from '../client.js';
4
4
  import { STATUS, APP_PREFIX, TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
5
- import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
5
+ import { getTestomatIdFromTestTitle, truncate, fileSystem } from '../utils/utils.js';
6
6
  import { services } from '../services/index.js';
7
7
  import { dataStorage } from '../data-storage.js';
8
8
  import codeceptjs from 'codeceptjs';
@@ -127,6 +127,28 @@ function CodeceptReporter(config) {
127
127
  });
128
128
 
129
129
 
130
+ // mark as failed all tests inside the failed hook
131
+ event.dispatcher.on(event.hook.failed, hook => {
132
+ if (hook.name !== 'BeforeSuiteHook') return;
133
+ const suite = hook.runnable.parent;
134
+
135
+ if (!suite) return;
136
+
137
+ const error = hook?.ctx?.currentTest?.err;
138
+
139
+ for (const test of suite.tests) {
140
+ client.addTestRun('failed', {
141
+ ...stripExampleFromTitle(test.title),
142
+ rid: test.uid,
143
+ test_id: getTestomatIdFromTestTitle(test.title),
144
+ suite_title: stripTagsFromTitle(suite.title),
145
+ error,
146
+ time: hook?.runnable?.duration,
147
+ });
148
+ }
149
+ });
150
+
151
+
130
152
  event.dispatcher.on(event.suite.before, suite => {
131
153
  dataStorage.setContext(suite.fullTitle());
132
154
  });
@@ -441,7 +463,7 @@ function formatCodeceptStep(step) {
441
463
  if (!step) return null;
442
464
 
443
465
  const category = step.constructor.name === 'HelperStep' ? 'framework' : 'user';
444
- const title = step.toString(); // Use built-in toString
466
+ const title = truncate(step); // Use built-in toString
445
467
  const duration = step.duration || 0; // Use built-in duration
446
468
 
447
469
  const formattedStep = {
@@ -469,10 +491,11 @@ function formatHookStep(step) {
469
491
  if (step.actor && step.name) {
470
492
  title = `${step.actor} ${step.name}`;
471
493
  if (step.args && step.args.length > 0) {
472
- const argsStr = step.args.map(arg => JSON.stringify(arg)).join(', ');
494
+ const argsStr = step.args.map(arg => truncate(JSON.stringify(arg))).join(', ');
473
495
  title += ` ${argsStr}`;
474
496
  }
475
497
  }
498
+ title = truncate(title);
476
499
 
477
500
  return {
478
501
  category: 'hook',
@@ -481,5 +504,6 @@ function formatHookStep(step) {
481
504
  };
482
505
  }
483
506
 
507
+
484
508
  export { CodeceptReporter };
485
509
  export default CodeceptReporter;
package/src/client.js CHANGED
@@ -10,11 +10,21 @@ import { glob } from 'glob';
10
10
  import path, { sep } from 'path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import { S3Uploader } from './uploader.js';
13
- import { formatStep, readLatestRunId, storeRunId, validateSuiteId } from './utils/utils.js';
13
+ import {
14
+ formatStep,
15
+ truncate,
16
+ readLatestRunId,
17
+ storeRunId,
18
+ validateSuiteId,
19
+ transformEnvVarToBoolean
20
+ } from './utils/utils.js';
14
21
  import { filesize as prettyBytes } from 'filesize';
22
+ import { stripVTControlCharacters } from 'util';
15
23
 
16
24
  const debug = createDebugMessages('@testomatio/reporter:client');
17
25
 
26
+ const stripColors = stripVTControlCharacters || ((str) => str?.replace(/\x1b\[[0-9;]*m/g, '') || '');
27
+
18
28
  // removed __dirname usage, because:
19
29
  // 1. replaced with ESM syntax (import.meta.url), but it throws an error on tsc compilation;
20
30
  // 2. got error "__dirname already defined" in compiles js code (cjs dir)
@@ -139,19 +149,6 @@ class Client {
139
149
  * @returns {Promise<PipeResult[]>}
140
150
  */
141
151
  async addTestRun(status, testData) {
142
- if (!this.pipes || !this.pipes.length)
143
- this.pipes = await pipesFactory(this.paramsForPipesFactory || {}, this.pipeStore);
144
-
145
- // all pipes disabled, skipping
146
- if (!this.pipes?.filter(p => p.isEnabled).length) return [];
147
-
148
- if (isTestShouldBeExculedFromReport(testData)) return [];
149
-
150
- if (status === STATUS.SKIPPED && process.env.TESTOMATIO_EXCLUDE_SKIPPED) {
151
- debug('Skipping test from report', testData?.title);
152
- return []; // do not log skipped tests
153
- }
154
-
155
152
  if (!testData)
156
153
  testData = {
157
154
  title: 'Unknown test',
@@ -169,15 +166,23 @@ class Client {
169
166
  const {
170
167
  rid,
171
168
  error = null,
169
+ steps: originalSteps,
170
+ title,
171
+ suite_title,
172
+ } = testData;
173
+ const steps = originalSteps;
174
+
175
+ const uploadedFiles = [];
176
+ const stackArtifactsEnabled = transformEnvVarToBoolean(process.env.TESTOMATIO_STACK_ARTIFACTS);
177
+
178
+
179
+ const {
172
180
  time = 0,
173
181
  example = null,
174
182
  files = [],
175
183
  filesBuffers = [],
176
- steps,
177
184
  code = null,
178
- title,
179
185
  file,
180
- suite_title,
181
186
  suite_id,
182
187
  test_id,
183
188
  timestamp,
@@ -188,7 +193,6 @@ class Client {
188
193
  } = testData;
189
194
  let { message = '', meta = {} } = testData;
190
195
 
191
- // stringify meta values and limit keys and values length to 255
192
196
  meta = Object.entries(meta)
193
197
  .filter(([, value]) => value !== null && value !== undefined)
194
198
  .reduce((acc, [key, value]) => {
@@ -196,7 +200,6 @@ class Client {
196
200
  return acc;
197
201
  }, {});
198
202
 
199
- // Get links from storage using the test context
200
203
  const testContext = suite_title ? `${suite_title} ${title}` : title;
201
204
 
202
205
  let errorFormatted = '';
@@ -205,13 +208,38 @@ class Client {
205
208
  message = error?.message;
206
209
  }
207
210
 
208
- // Attach logs
209
- const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
211
+ let fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
210
212
 
211
- // add artifacts
212
- if (manuallyAttachedArtifacts?.length) files.push(...manuallyAttachedArtifacts);
213
+ if (stackArtifactsEnabled) {
214
+ const timestamp = +new Date;
215
+ uploadedFiles.push(
216
+ this.uploader.uploadFileAsBuffer(
217
+ Buffer.from(stripColors(fullLogs), 'utf8'),
218
+ [this.runId, rid, `logs_${timestamp}.log`]
219
+ )
220
+ );
221
+ fullLogs = '';
222
+ }
213
223
 
214
- const uploadedFiles = [];
224
+
225
+ if (!this.pipes || !this.pipes.length)
226
+ this.pipes = await pipesFactory(this.paramsForPipesFactory || {}, this.pipeStore);
227
+
228
+ if (!this.pipes?.filter(p => p.isEnabled).length) {
229
+ if (uploadedFiles.length > 0) {
230
+ await Promise.all(uploadedFiles);
231
+ }
232
+ return [];
233
+ }
234
+
235
+ if (isTestShouldBeExculedFromReport(testData)) return [];
236
+
237
+ if (status === STATUS.SKIPPED && process.env.TESTOMATIO_EXCLUDE_SKIPPED) {
238
+ debug('Skipping test from report', testData?.title);
239
+ return [];
240
+ }
241
+
242
+ if (manuallyAttachedArtifacts?.length) files.push(...manuallyAttachedArtifacts);
215
243
 
216
244
  for (let f of files) {
217
245
  if (!f) continue; // f === null
@@ -387,7 +415,7 @@ class Client {
387
415
  */
388
416
  formatLogs({ error, steps, logs }) {
389
417
  error = error?.trim();
390
- logs = logs?.trim();
418
+ logs = logs?.trim().split('\n').map(l => truncate(l)).join('\n');
391
419
 
392
420
  if (Array.isArray(steps)) {
393
421
  steps = steps
@@ -462,8 +462,6 @@ class TestomatioPipe {
462
462
  }
463
463
  });
464
464
 
465
- console.log(APP_PREFIX, '✅ Testrun finished');
466
-
467
465
  if (this.runUrl) {
468
466
  console.log(APP_PREFIX, '📊 Report Saved. Report URL:', pc.magenta(this.runUrl));
469
467
  }
package/src/reporter.js CHANGED
@@ -1,8 +1,10 @@
1
- // import TestomatClient from './client.js';
2
- // import * as TRConstants from './constants.js';
1
+ import Client from './client.js';
2
+ import * as TestomatioConstants from './constants.js';
3
3
  import { services } from './services/index.js';
4
4
  import reporterFunctions from './reporter-functions.js';
5
5
 
6
+ export { Client };
7
+ export const STATUS = TestomatioConstants.STATUS;
6
8
  export const artifact = reporterFunctions.artifact;
7
9
  export const log = reporterFunctions.log;
8
10
  export const logger = services.logger;
@@ -35,6 +37,7 @@ export default {
35
37
  linkTest: reporterFunctions.linkTest,
36
38
  linkJira: reporterFunctions.linkJira,
37
39
 
38
- // TestomatClient,
39
- // TRConstants,
40
+ TestomatioClient: Client,
41
+ STATUS,
42
+
40
43
  };
@@ -428,8 +428,16 @@ function transformEnvVarToBoolean(value) {
428
428
  return Boolean(value);
429
429
  }
430
430
 
431
+ function truncate(s, size = 255) {
432
+ if (s.toString().trim().length < size) {
433
+ return s.toString();
434
+ }
435
+ return `${s.toString().substring(0, size)}...`;
436
+ }
437
+
431
438
  export {
432
439
  ansiRegExp,
440
+ truncate,
433
441
  cleanLatestRunId,
434
442
  isSameTest,
435
443
  fetchSourceCode,