@testomatio/reporter 2.0.0-beta-esm → 2.0.1-beta-esm

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/lib/adapter/codecept.d.ts +2 -0
  2. package/lib/adapter/codecept.js +31 -24
  3. package/lib/adapter/cucumber/current.d.ts +14 -0
  4. package/lib/adapter/cucumber/legacy.d.ts +0 -0
  5. package/lib/adapter/cucumber.d.ts +2 -0
  6. package/lib/adapter/cypress-plugin/index.d.ts +2 -0
  7. package/lib/adapter/cypress-plugin/index.js +11 -9
  8. package/lib/adapter/jasmine.d.ts +11 -0
  9. package/lib/adapter/jest.d.ts +13 -0
  10. package/lib/adapter/mocha.d.ts +2 -0
  11. package/lib/adapter/mocha.js +4 -3
  12. package/lib/adapter/playwright.d.ts +14 -0
  13. package/lib/adapter/playwright.js +58 -33
  14. package/lib/adapter/vitest.d.ts +35 -0
  15. package/lib/adapter/vitest.js +6 -6
  16. package/lib/adapter/webdriver.d.ts +24 -0
  17. package/lib/adapter/webdriver.js +34 -6
  18. package/lib/bin/cli.d.ts +2 -0
  19. package/lib/bin/cli.js +228 -0
  20. package/lib/bin/reportXml.d.ts +2 -0
  21. package/lib/bin/reportXml.js +11 -9
  22. package/lib/bin/startTest.d.ts +2 -0
  23. package/lib/bin/startTest.js +9 -5
  24. package/lib/bin/uploadArtifacts.d.ts +2 -0
  25. package/lib/bin/uploadArtifacts.js +81 -0
  26. package/lib/client.d.ts +76 -0
  27. package/lib/client.js +111 -45
  28. package/lib/config.d.ts +1 -0
  29. package/lib/constants.d.ts +25 -0
  30. package/lib/constants.js +5 -1
  31. package/lib/data-storage.d.ts +34 -0
  32. package/lib/data-storage.js +2 -2
  33. package/lib/junit-adapter/adapter.d.ts +9 -0
  34. package/lib/junit-adapter/csharp.d.ts +4 -0
  35. package/lib/junit-adapter/index.d.ts +3 -0
  36. package/lib/junit-adapter/java.d.ts +5 -0
  37. package/lib/junit-adapter/javascript.d.ts +4 -0
  38. package/lib/junit-adapter/python.d.ts +5 -0
  39. package/lib/junit-adapter/ruby.d.ts +4 -0
  40. package/lib/output.d.ts +11 -0
  41. package/lib/package.json +3 -1
  42. package/lib/pipe/bitbucket.d.ts +23 -0
  43. package/lib/pipe/bitbucket.js +2 -2
  44. package/lib/pipe/csv.d.ts +47 -0
  45. package/lib/pipe/csv.js +2 -2
  46. package/lib/pipe/debug.d.ts +29 -0
  47. package/lib/pipe/debug.js +108 -0
  48. package/lib/pipe/github.d.ts +30 -0
  49. package/lib/pipe/github.js +2 -2
  50. package/lib/pipe/gitlab.d.ts +23 -0
  51. package/lib/pipe/gitlab.js +2 -2
  52. package/lib/pipe/html.d.ts +34 -0
  53. package/lib/pipe/html.js +8 -1
  54. package/lib/pipe/index.d.ts +1 -0
  55. package/lib/pipe/index.js +3 -3
  56. package/lib/pipe/testomatio.d.ts +70 -0
  57. package/lib/pipe/testomatio.js +50 -30
  58. package/lib/reporter-functions.d.ts +34 -0
  59. package/lib/reporter-functions.js +17 -7
  60. package/lib/reporter.d.ts +232 -0
  61. package/lib/reporter.js +19 -33
  62. package/lib/services/artifacts.d.ts +33 -0
  63. package/lib/services/index.d.ts +9 -0
  64. package/lib/services/key-values.d.ts +27 -0
  65. package/lib/services/key-values.js +1 -1
  66. package/lib/services/logger.d.ts +64 -0
  67. package/lib/template/testomatio.hbs +651 -1366
  68. package/lib/uploader.d.ts +60 -0
  69. package/lib/uploader.js +312 -0
  70. package/lib/utils/pipe_utils.d.ts +41 -0
  71. package/lib/utils/pipe_utils.js +3 -5
  72. package/lib/utils/utils.d.ts +45 -0
  73. package/lib/utils/utils.js +69 -2
  74. package/lib/xmlReader.d.ts +92 -0
  75. package/lib/xmlReader.js +22 -12
  76. package/package.json +15 -9
  77. package/src/adapter/codecept.js +30 -24
  78. package/src/adapter/cypress-plugin/index.js +5 -3
  79. package/src/adapter/mocha.cjs +1 -1
  80. package/src/adapter/mocha.js +4 -3
  81. package/src/adapter/playwright.js +59 -31
  82. package/src/adapter/vitest.js +6 -6
  83. package/src/adapter/webdriver.js +41 -10
  84. package/src/bin/cli.js +280 -0
  85. package/src/bin/reportXml.js +15 -8
  86. package/src/bin/startTest.js +7 -3
  87. package/src/bin/uploadArtifacts.js +90 -0
  88. package/src/client.js +137 -56
  89. package/src/constants.js +5 -1
  90. package/src/data-storage.js +2 -2
  91. package/src/pipe/bitbucket.js +2 -2
  92. package/src/pipe/csv.js +3 -3
  93. package/src/pipe/debug.js +104 -0
  94. package/src/pipe/github.js +2 -3
  95. package/src/pipe/gitlab.js +6 -6
  96. package/src/pipe/html.js +11 -3
  97. package/src/pipe/index.js +5 -7
  98. package/src/pipe/testomatio.js +72 -67
  99. package/src/reporter-functions.js +18 -7
  100. package/src/reporter.cjs_decprecated +21 -0
  101. package/src/reporter.js +20 -11
  102. package/src/services/key-values.js +1 -1
  103. package/src/services/logger.js +4 -2
  104. package/src/template/testomatio.hbs +651 -1366
  105. package/src/uploader.js +371 -0
  106. package/src/utils/pipe_utils.js +4 -12
  107. package/src/utils/utils.js +48 -6
  108. package/src/xmlReader.js +26 -15
  109. package/lib/adapter/jasmine/jasmine.js +0 -63
  110. package/lib/adapter/mocha/mocha.js +0 -125
  111. package/lib/fileUploader.js +0 -245
  112. package/lib/utils/chalk.js +0 -10
  113. package/src/fileUploader.js +0 -307
  114. package/src/reporter.cjs +0 -22
  115. package/src/utils/chalk.js +0 -13
package/lib/client.js CHANGED
@@ -33,32 +33,34 @@ const minimatch_1 = require("minimatch");
33
33
  const fs_1 = __importDefault(require("fs"));
34
34
  const picocolors_1 = __importDefault(require("picocolors"));
35
35
  const crypto_1 = require("crypto");
36
- const fileUploader_js_1 = require("./fileUploader.js");
37
36
  const constants_js_1 = require("./constants.js");
38
37
  const index_js_1 = require("./pipe/index.js");
39
38
  const glob_1 = require("glob");
40
39
  const path_1 = __importStar(require("path"));
41
40
  const node_url_1 = require("node:url");
41
+ const uploader_js_1 = require("./uploader.js");
42
+ const utils_js_1 = require("./utils/utils.js");
43
+ const filesize_1 = require("filesize");
42
44
  const debug = (0, debug_1.default)('@testomatio/reporter:client');
43
45
  // removed __dirname usage, because:
44
46
  // 1. replaced with ESM syntax (import.meta.url), but it throws an error on tsc compilation;
45
- // 2. got error "__dirname already defined" in compiles js code (cjs dir)
47
+ // 2. got error "__dirname already defined" in compiles js code (cjs dir)
46
48
  let listOfTestFilesToExcludeFromReport = null;
47
49
  /**
48
- * @typedef {import('../types').TestData} TestData
49
- * @typedef {import('../types').PipeResult} PipeResult
50
+ * @typedef {import('../types/types.js').TestData} TestData
51
+ * @typedef {import('../types/types.js').PipeResult} PipeResult
50
52
  */
51
53
  class Client {
52
54
  /**
53
55
  * Create a Testomat client instance
54
56
  * @returns
55
57
  */
56
- // eslint-disable-next-line
58
+ // eslint-disable-next-line
57
59
  constructor(params = {}) {
58
- this.uuid = (0, crypto_1.randomUUID)();
60
+ this.paramsForPipesFactory = params;
61
+ this.pipeStore = {};
62
+ this.runId = (0, crypto_1.randomUUID)(); // will be replaced by real run id
59
63
  this.queue = Promise.resolve();
60
- this.totalUploaded = 0;
61
- this.failedToUpload = 0;
62
64
  // @ts-ignore this line will be removed in compiled code, because __dirname is defined in commonjs
63
65
  const pathToPackageJSON = path_1.default.join(__dirname, '../package.json');
64
66
  try {
@@ -69,6 +71,7 @@ class Client {
69
71
  // do nothing
70
72
  }
71
73
  this.executionList = Promise.resolve();
74
+ this.uploader = new uploader_js_1.S3Uploader();
72
75
  }
73
76
  /**
74
77
  * Asynchronously prepares the execution list for running tests through various pipes.
@@ -87,8 +90,7 @@ class Client {
87
90
  * or resolves to undefined if no valid results are found or if all pipes are disabled.
88
91
  */
89
92
  async prepareRun(params) {
90
- const store = {};
91
- this.pipes = await (0, index_js_1.pipesFactory)(params, store);
93
+ this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
92
94
  const { pipe, pipeOptions } = params;
93
95
  // all pipes disabled, skipping
94
96
  if (!this.pipes.some(p => p.isEnabled)) {
@@ -120,7 +122,7 @@ class Client {
120
122
  */
121
123
  async createRun(params) {
122
124
  if (!this.pipes || !this.pipes.length)
123
- this.pipes = await (0, index_js_1.pipesFactory)(params || {}, {});
125
+ this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
124
126
  debug('Creating run...');
125
127
  // all pipes disabled, skipping
126
128
  if (!this.pipes?.filter(p => p.isEnabled).length)
@@ -128,6 +130,13 @@ class Client {
128
130
  this.queue = this.queue
129
131
  .then(() => Promise.all(this.pipes.map(p => p.createRun())))
130
132
  .catch(err => console.log(constants_js_1.APP_PREFIX, err))
133
+ .then(() => {
134
+ const runId = this.pipeStore?.runId;
135
+ if (runId)
136
+ this.runId = runId;
137
+ (0, utils_js_1.storeRunId)(this.runId);
138
+ })
139
+ .then(() => this.uploader.checkEnabled())
131
140
  .then(() => undefined); // fixes return type
132
141
  // debug('Run', this.queue);
133
142
  return this.queue;
@@ -157,8 +166,45 @@ class Client {
157
166
  /**
158
167
  * @type {TestData}
159
168
  */
160
- const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, manuallyAttachedArtifacts, meta, } = testData;
161
- let { message = '' } = testData;
169
+ const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, manuallyAttachedArtifacts, } = testData;
170
+ let { message = '', meta = {} } = testData;
171
+ // stringify meta values and limit keys and values length to 255
172
+ meta = Object.entries(meta)
173
+ .filter(([, value]) => value !== null && value !== undefined)
174
+ .map(([key, value]) => {
175
+ try {
176
+ if (typeof value === 'object') {
177
+ value = JSON.stringify(value);
178
+ }
179
+ else if (typeof value !== 'string') {
180
+ try {
181
+ value = value.toString();
182
+ }
183
+ catch (err) {
184
+ console.warn(constants_js_1.APP_PREFIX, `Can't convert meta value to string`, err);
185
+ }
186
+ }
187
+ if (value?.length > 255) {
188
+ value = value.substring(0, 255);
189
+ debug(constants_js_1.APP_PREFIX, `Meta info value "${value}" is too long, trimmed to 255 characters`);
190
+ }
191
+ if (key?.length > 255) {
192
+ const newKey = key.substring(0, 255);
193
+ debug(constants_js_1.APP_PREFIX, `Meta info key "${key}" is too long, trimmed to 255 characters`);
194
+ return [newKey, value];
195
+ }
196
+ return [key, value];
197
+ }
198
+ catch (err) {
199
+ debug(constants_js_1.APP_PREFIX, `Error while processing meta info key ${key}`, err);
200
+ return [null, null];
201
+ }
202
+ })
203
+ .reduce((acc, [key, value]) => {
204
+ if (key)
205
+ acc[key] = value;
206
+ return acc;
207
+ }, {});
162
208
  let errorFormatted = '';
163
209
  if (error) {
164
210
  errorFormatted += this.formatError(error) || '';
@@ -170,19 +216,21 @@ class Client {
170
216
  if (manuallyAttachedArtifacts?.length)
171
217
  files.push(...manuallyAttachedArtifacts);
172
218
  const uploadedFiles = [];
173
- for (const f of files) {
174
- uploadedFiles.push(fileUploader_js_1.upload.uploadFileByPath(f, this.uuid));
219
+ for (let f of files) {
220
+ if (!f)
221
+ continue; // f === null
222
+ if (typeof f === 'object') {
223
+ if (!f.path)
224
+ continue;
225
+ f = f.path;
226
+ }
227
+ uploadedFiles.push(this.uploader.uploadFileByPath(f, [this.runId, rid, path_1.default.basename(f)]));
175
228
  }
176
229
  for (const [idx, buffer] of filesBuffers.entries()) {
177
230
  const fileName = `${idx + 1}-${title.replace(/\s+/g, '-')}`;
178
- uploadedFiles.push(fileUploader_js_1.upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
231
+ uploadedFiles.push(this.uploader.uploadFileAsBuffer(buffer, [this.runId, rid, fileName]));
179
232
  }
180
233
  const artifacts = (await Promise.all(uploadedFiles)).filter(n => !!n);
181
- if (artifacts.length < uploadedFiles.length) {
182
- const failedUploading = uploadedFiles.length - artifacts.length;
183
- this.failedToUpload += failedUploading;
184
- }
185
- this.totalUploaded += artifacts.length;
186
234
  const data = {
187
235
  rid,
188
236
  files,
@@ -232,15 +280,47 @@ class Client {
232
280
  this.queue = this.queue
233
281
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
234
282
  .then(() => {
235
- debug('TOTAL artifacts', this.totalUploaded);
236
- if (this.totalUploaded && !fileUploader_js_1.upload.isArtifactsEnabled())
237
- debug(`${this.totalUploaded} artifacts are not uploaded, because artifacts uploading is not enabled`);
238
- if (this.totalUploaded && fileUploader_js_1.upload.isArtifactsEnabled()) {
239
- console.log(constants_js_1.APP_PREFIX, `🗄️ ${this.totalUploaded} artifacts ${process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : picocolors_1.default.bold('publicly')} uploaded to S3 bucket`);
240
- if (this.failedToUpload > 0) {
241
- console.log(constants_js_1.APP_PREFIX, picocolors_1.default.yellow(`Some artifacts were not uploaded. ${this.failedToUpload} artifacts could not be uploaded.
242
- Run tests with DEBUG="@testomatio/reporter:file-uploader" to see details"`));
243
- }
283
+ if (!this.uploader.isEnabled)
284
+ return;
285
+ const filesizeStrMaxLength = 7;
286
+ if (this.uploader.successfulUploads.length) {
287
+ debug('\n', constants_js_1.APP_PREFIX, `🗄️ ${this.uploader.successfulUploads.length} artifacts uploaded to S3 bucket`);
288
+ const uploadedArtifacts = this.uploader.successfulUploads.map(file => ({
289
+ relativePath: file.path.replace(process.cwd(), ''),
290
+ link: file.link,
291
+ sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
292
+ }));
293
+ uploadedArtifacts.forEach(upload => {
294
+ debug(`🟢Uploaded artifact`, `${upload.relativePath},`, 'size:', `${upload.sizePretty},`, 'link:', `${upload.link}`);
295
+ });
296
+ }
297
+ if (this.uploader.failedUploads.length) {
298
+ console.log(constants_js_1.APP_PREFIX, `🗄️ ${this.uploader.failedUploads.length} artifacts 🔴${picocolors_1.default.bold('failed')} to upload`);
299
+ const failedUploads = this.uploader.failedUploads.map(file => ({
300
+ relativePath: file.path.replace(process.cwd(), ''),
301
+ sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
302
+ }));
303
+ const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
304
+ failedUploads.forEach(upload => {
305
+ console.log(` ${picocolors_1.default.gray('|')} 🔴 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
306
+ });
307
+ }
308
+ if (this.uploader.skippedUploads.length) {
309
+ console.log('\n', constants_js_1.APP_PREFIX, `🗄️ ${picocolors_1.default.bold(this.uploader.skippedUploads.length)} artifacts uploading 🟡${picocolors_1.default.bold('skipped')}`);
310
+ const skippedUploads = this.uploader.skippedUploads.map(file => ({
311
+ relativePath: file.path.replace(process.cwd(), ''),
312
+ sizePretty: file.size === null ? 'unknown' : (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
313
+ }));
314
+ const pathPadding = Math.max(...skippedUploads.map(upload => upload.relativePath.length)) + 1;
315
+ skippedUploads.forEach(upload => {
316
+ console.log(` ${picocolors_1.default.gray('|')} 🟡 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
317
+ });
318
+ }
319
+ if (this.uploader.skippedUploads.length || this.uploader.failedUploads.length) {
320
+ const command = `TESTOMATIO=<your_api_key> TESTOMATIO_RUN=${this.runId} npx @testomatio/reporter upload-artifacts`;
321
+ const numberOfNotUploadedArtifacts = this.uploader.skippedUploads.length + this.uploader.failedUploads.length;
322
+ console.log(constants_js_1.APP_PREFIX, `${numberOfNotUploadedArtifacts} artifacts were not uploaded.
323
+ Run "${picocolors_1.default.magenta(command)}" with valid S3 credentials to upload skipped & failed artifacts`);
244
324
  }
245
325
  })
246
326
  .catch(err => console.log(constants_js_1.APP_PREFIX, err));
@@ -255,7 +335,7 @@ class Client {
255
335
  logs = logs?.trim();
256
336
  if (Array.isArray(steps)) {
257
337
  steps = steps
258
- .map(step => formatStep(step))
338
+ .map(step => (0, utils_js_1.formatStep)(step))
259
339
  .flat()
260
340
  .join('\n');
261
341
  }
@@ -327,20 +407,6 @@ function isNotInternalFrame(frame) {
327
407
  !frame.getFileName().includes('node_modules') &&
328
408
  !frame.getFileName().includes('internal'));
329
409
  }
330
- function formatStep(step, shift = 0) {
331
- const prefix = ' '.repeat(shift);
332
- const lines = [];
333
- if (step.error) {
334
- lines.push(`${prefix}${picocolors_1.default.red(step.title)} ${picocolors_1.default.gray(`${step.duration}ms`)}`);
335
- }
336
- else {
337
- lines.push(`${prefix}${step.title} ${picocolors_1.default.gray(`${step.duration}ms`)}`);
338
- }
339
- for (const child of step.steps || []) {
340
- lines.push(...formatStep(child, shift + 2));
341
- }
342
- return lines;
343
- }
344
410
  /**
345
411
  *
346
412
  * @param {TestData} testData
@@ -0,0 +1 @@
1
+ export const config: NodeJS.ProcessEnv;
@@ -0,0 +1,25 @@
1
+ export const APP_PREFIX: string;
2
+ export const TESTOMAT_TMP_STORAGE_DIR: string;
3
+ export const CSV_HEADERS: {
4
+ id: string;
5
+ title: string;
6
+ }[];
7
+ export namespace STATUS {
8
+ let PASSED: string;
9
+ let FAILED: string;
10
+ let SKIPPED: string;
11
+ let FINISHED: string;
12
+ }
13
+ export namespace HTML_REPORT {
14
+ let FOLDER: string;
15
+ let REPORT_DEFAULT_NAME: string;
16
+ let TEMPLATE_NAME: string;
17
+ }
18
+ export const AXIOS_TIMEOUT: number;
19
+ export const testomatLogoURL: "https://avatars.githubusercontent.com/u/59105116?s=36&v=4";
20
+ export namespace REPORTER_REQUEST_RETRIES {
21
+ let retryTimeout: number;
22
+ let retriesPerRequest: number;
23
+ let maxTotalRetries: number;
24
+ let withinTimeSeconds: number;
25
+ }
package/lib/constants.js CHANGED
@@ -9,7 +9,11 @@ const os_1 = __importDefault(require("os"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const APP_PREFIX = picocolors_1.default.gray('[TESTOMATIO]');
11
11
  exports.APP_PREFIX = APP_PREFIX;
12
- const AXIOS_TIMEOUT = 20 * 1000; // sum = 20sec
12
+ const TESTOMATIO_REQUEST_TIMEOUT = parseInt(process.env.TESTOMATIO_REQUEST_TIMEOUT, 10);
13
+ if (TESTOMATIO_REQUEST_TIMEOUT) {
14
+ console.log(`${APP_PREFIX} Request timeout is set to ${TESTOMATIO_REQUEST_TIMEOUT / 1000}s`);
15
+ }
16
+ const AXIOS_TIMEOUT = TESTOMATIO_REQUEST_TIMEOUT || 20 * 1000;
13
17
  exports.AXIOS_TIMEOUT = AXIOS_TIMEOUT;
14
18
  const TESTOMAT_TMP_STORAGE_DIR = path_1.default.join(os_1.default.tmpdir(), 'testomatio_tmp');
15
19
  exports.TESTOMAT_TMP_STORAGE_DIR = TESTOMAT_TMP_STORAGE_DIR;
@@ -0,0 +1,34 @@
1
+ export const dataStorage: DataStorage;
2
+ declare class DataStorage {
3
+ static "__#11@#instance": any;
4
+ /**
5
+ *
6
+ * @returns {DataStorage}
7
+ */
8
+ static getInstance(): DataStorage;
9
+ context: any;
10
+ setContext(context: any): void;
11
+ isFileStorage: boolean;
12
+ /**
13
+ * Puts any data to storage (file or global variable).
14
+ * If file: stores data as text, if global variable – stores as array of data.
15
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
16
+ * @param {*} data anything you want to store (string, object, array, etc)
17
+ * @param {*} context could be testId or any context (test name, suite name, including their IDs etc)
18
+ * suite name + test name is used by default
19
+ * @returns
20
+ */
21
+ putData(dataType: "log" | "artifact" | "keyvalue", data: any, context?: any): void;
22
+ /**
23
+ * Returns data, stored for specific test/context (or data which was stored without test id specified).
24
+ * This method will get data from global variable and/or from from file (previosly saved with put method).
25
+ *
26
+ * @param {'log' | 'artifact' | 'keyvalue'} dataType
27
+ * @param {string} context
28
+ * @returns {any []} array of data (any type), null (if no data found for context) or string (if data type is log)
29
+ */
30
+ getData(dataType: "log" | "artifact" | "keyvalue", context: string): any[];
31
+ #private;
32
+ }
33
+ export function stringToMD5Hash(str: any): string;
34
+ export {};
@@ -76,7 +76,7 @@ class DataStorage {
76
76
  return;
77
77
  context = context || this.context || utils_js_1.testRunnerHelper.getNameOfCurrentlyRunningTest();
78
78
  if (!context) {
79
- debug(`No context provided for "${dataType}" data:`, data);
79
+ // debug(`No context provided for "${dataType}" data:`, data);
80
80
  return;
81
81
  }
82
82
  const contextHash = stringToMD5Hash(context);
@@ -119,7 +119,7 @@ class DataStorage {
119
119
  if (testDataFromFile.length) {
120
120
  return testDataFromFile;
121
121
  }
122
- debug(`No "${dataType}" data for context "${contextHash}" in both file and global variable`);
122
+ // debug(`No "${dataType}" data for context "${contextHash}" in both file and global variable`);
123
123
  // in case no data found for context
124
124
  return null;
125
125
  }
@@ -0,0 +1,9 @@
1
+ export default Adapter;
2
+ declare class Adapter {
3
+ constructor(opts: any);
4
+ opts: any;
5
+ getFilePath(t: any): any;
6
+ formatTest(t: any): any;
7
+ formatStack(t: any): any;
8
+ formatMessage(t: any): any;
9
+ }
@@ -0,0 +1,4 @@
1
+ export default CSharpAdapter;
2
+ declare class CSharpAdapter extends Adapter {
3
+ }
4
+ import Adapter from './adapter.js';
@@ -0,0 +1,3 @@
1
+ export default AdapterFactory;
2
+ declare function AdapterFactory(lang: any, opts: any): Adapter;
3
+ import Adapter from './adapter.js';
@@ -0,0 +1,5 @@
1
+ export default JavaAdapter;
2
+ declare class JavaAdapter extends Adapter {
3
+ getFilePath(t: any): string;
4
+ }
5
+ import Adapter from './adapter.js';
@@ -0,0 +1,4 @@
1
+ export default JavaScriptAdapter;
2
+ declare class JavaScriptAdapter extends Adapter {
3
+ }
4
+ import Adapter from './adapter.js';
@@ -0,0 +1,5 @@
1
+ export default PythonAdapter;
2
+ declare class PythonAdapter extends Adapter {
3
+ getFilePath(t: any): string;
4
+ }
5
+ import Adapter from './adapter.js';
@@ -0,0 +1,4 @@
1
+ export default RubyAdapter;
2
+ declare class RubyAdapter extends Adapter {
3
+ }
4
+ import Adapter from './adapter.js';
@@ -0,0 +1,11 @@
1
+ export default Output;
2
+ declare class Output {
3
+ constructor(opts?: {});
4
+ filterFn: any;
5
+ reset(): void;
6
+ log: any[];
7
+ start(): void;
8
+ push(line: any): void;
9
+ text(): string;
10
+ stop(): void;
11
+ }
package/lib/package.json CHANGED
@@ -1 +1,3 @@
1
- {}
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @class BitbucketPipe
3
+ * @typedef {import('../../types/types.js').Pipe} Pipe
4
+ * @typedef {import('../../types/types.js').TestData} TestData
5
+ */
6
+ export class BitbucketPipe {
7
+ constructor(params: any, store?: {});
8
+ isEnabled: boolean;
9
+ ENV: NodeJS.ProcessEnv;
10
+ store: {};
11
+ tests: any[];
12
+ token: any;
13
+ hiddenCommentData: string;
14
+ cleanLog(log: any): Promise<string>;
15
+ prepareRun(): Promise<void>;
16
+ createRun(): Promise<void>;
17
+ addTest(test: any): void;
18
+ finishRun(runParams: any): Promise<void>;
19
+ toString(): string;
20
+ updateRun(): void;
21
+ }
22
+ export type Pipe = import("../../types/types.js").Pipe;
23
+ export type TestData = import("../../types/types.js").TestData;
@@ -41,8 +41,8 @@ const debug = (0, debug_1.default)('@testomatio/reporter:pipe:bitbucket');
41
41
  //! and your pipeline trigger should be a pull request
42
42
  /**
43
43
  * @class BitbucketPipe
44
- * @typedef {import('../../types').Pipe} Pipe
45
- * @typedef {import('../../types').TestData} TestData
44
+ * @typedef {import('../../types/types.js').Pipe} Pipe
45
+ * @typedef {import('../../types/types.js').TestData} TestData
46
46
  */
47
47
  class BitbucketPipe {
48
48
  constructor(params, store = {}) {
@@ -0,0 +1,47 @@
1
+ export default CsvPipe;
2
+ export type Pipe = import("../../types/types.js").Pipe;
3
+ export type TestData = import("../../types/types.js").TestData;
4
+ /**
5
+ * @typedef {import('../../types/types.js').Pipe} Pipe
6
+ * @typedef {import('../../types/types.js').TestData} TestData
7
+ * @class CsvPipe
8
+ * @implements {Pipe}
9
+ */
10
+ declare class CsvPipe implements Pipe {
11
+ constructor(params: any, store: any);
12
+ store: any;
13
+ title: any;
14
+ results: any[];
15
+ outputDir: string;
16
+ defaultReportName: string;
17
+ csvFilename: string;
18
+ isEnabled: boolean;
19
+ outputFile: string;
20
+ prepareRun(): Promise<void>;
21
+ createRun(): Promise<void>;
22
+ updateRun(): void;
23
+ /**
24
+ * Create a folder that will contain the exported files
25
+ */
26
+ checkExportDir(): void;
27
+ /**
28
+ * Save data to the csv file.
29
+ * @param {Object} data - data that will be added to the CSV file.
30
+ * Example: [{suite_title: "Suite #1", test: "Test-case-1", message: "Test msg"}]
31
+ * @param {Object} headers - csv file headers. Example: [{ id: 'suite_title', title: 'Suite_title' }]
32
+ */
33
+ saveToCsv(data: any, headers: any): Promise<void>;
34
+ /**
35
+ * Add test data to the result array for saving. As a result of this function, we get a result object to save.
36
+ * @param {Object} test - object which includes each test entry.
37
+ */
38
+ addTest(test: any): void;
39
+ /**
40
+ * @param {{ tests?: TestData[] }} runParams
41
+ * @returns {Promise<void>}
42
+ */
43
+ finishRun(runParams: {
44
+ tests?: TestData[];
45
+ }): Promise<void>;
46
+ toString(): string;
47
+ }
package/lib/pipe/csv.js CHANGED
@@ -13,8 +13,8 @@ const utils_js_1 = require("../utils/utils.js");
13
13
  const constants_js_1 = require("../constants.js");
14
14
  const debug = (0, debug_1.default)('@testomatio/reporter:pipe:csv');
15
15
  /**
16
- * @typedef {import('../../types').Pipe} Pipe
17
- * @typedef {import('../../types').TestData} TestData
16
+ * @typedef {import('../../types/types.js').Pipe} Pipe
17
+ * @typedef {import('../../types/types.js').TestData} TestData
18
18
  * @class CsvPipe
19
19
  * @implements {Pipe}
20
20
  */
@@ -0,0 +1,29 @@
1
+ export class DebugPipe {
2
+ constructor(params: any, store: any);
3
+ params: any;
4
+ store: any;
5
+ isEnabled: boolean;
6
+ batch: {
7
+ isEnabled: any;
8
+ intervalFunction: any;
9
+ intervalTime: number;
10
+ tests: any[];
11
+ batchIndex: number;
12
+ };
13
+ logFilePath: string;
14
+ testomatioEnvVars: {};
15
+ batchUpload(): Promise<void>;
16
+ /**
17
+ * Logs data to a file if logging is enabled.
18
+ *
19
+ * @param {Object} logData - The data to be logged.
20
+ * @returns {Promise<void>} A promise that resolves when the log data has been appended to the file.
21
+ */
22
+ logToFile(logData: any): Promise<void>;
23
+ lastActionTimestamp: number;
24
+ prepareRun(opts: any): Promise<any[]>;
25
+ createRun(params?: {}): Promise<{}>;
26
+ addTest(data: any): Promise<void>;
27
+ finishRun(params: any): Promise<void>;
28
+ toString(): string;
29
+ }
@@ -0,0 +1,108 @@
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.DebugPipe = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const debug_1 = __importDefault(require("debug"));
11
+ const constants_js_1 = require("../constants.js");
12
+ const pretty_ms_1 = __importDefault(require("pretty-ms"));
13
+ const debug = (0, debug_1.default)('@testomatio/reporter:pipe:debug');
14
+ class DebugPipe {
15
+ constructor(params, store) {
16
+ this.params = params || {};
17
+ this.store = store || {};
18
+ this.isEnabled = !!process.env.TESTOMATIO_DEBUG || !!process.env.DEBUG;
19
+ if (this.isEnabled) {
20
+ this.batch = {
21
+ isEnabled: this.params.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
22
+ intervalFunction: null,
23
+ intervalTime: 5000,
24
+ tests: [],
25
+ batchIndex: 0,
26
+ };
27
+ this.logFilePath = path_1.default.join(os_1.default.tmpdir(), `testomatio.debug.${Date.now()}.json`);
28
+ debug('Creating debug file:', this.logFilePath);
29
+ fs_1.default.writeFileSync(this.logFilePath, '');
30
+ console.log(constants_js_1.APP_PREFIX, '🪲. Debug created:');
31
+ this.testomatioEnvVars = Object.keys(process.env)
32
+ .filter(key => key.startsWith('TESTOMATIO_'))
33
+ .reduce((acc, key) => {
34
+ acc[key] = process.env[key];
35
+ return acc;
36
+ }, {});
37
+ this.logToFile({ datetime: new Date().toISOString(), timestamp: Date.now() });
38
+ this.logToFile({ data: 'variables', testomatioEnvVars: this.testomatioEnvVars });
39
+ this.logToFile({ data: 'store', store: this.store || {} });
40
+ // Bind batchUpload to the instance
41
+ this.batchUpload = this.batchUpload.bind(this);
42
+ }
43
+ }
44
+ /**
45
+ * Logs data to a file if logging is enabled.
46
+ *
47
+ * @param {Object} logData - The data to be logged.
48
+ * @returns {Promise<void>} A promise that resolves when the log data has been appended to the file.
49
+ */
50
+ logToFile(logData) {
51
+ if (!this.isEnabled)
52
+ return;
53
+ const timePassedFromLastAction = Date.now() - (this.lastActionTimestamp || Date.now());
54
+ this.lastActionTimestamp = Date.now();
55
+ const logLine = JSON.stringify({ t: `+${(0, pretty_ms_1.default)(timePassedFromLastAction)}`, ...logData });
56
+ fs_1.default.appendFileSync(this.logFilePath, `${logLine}\n`);
57
+ }
58
+ async prepareRun(opts) {
59
+ if (!this.isEnabled)
60
+ return [];
61
+ this.logToFile({ action: 'prepareRun', data: opts });
62
+ }
63
+ async createRun(params = {}) {
64
+ if (!this.isEnabled)
65
+ return;
66
+ if (params.isBatchEnabled === true || params.isBatchEnabled === false)
67
+ this.batch.isEnabled = params.isBatchEnabled;
68
+ if (!this.isEnabled)
69
+ return {};
70
+ if (this.batch.isEnabled)
71
+ this.batch.intervalFunction = setInterval(this.batchUpload, this.batch.intervalTime);
72
+ this.logToFile({ action: 'createRun', params });
73
+ }
74
+ async addTest(data) {
75
+ if (!this.isEnabled)
76
+ return;
77
+ if (!this.batch.isEnabled)
78
+ this.logToFile({ action: 'addTest', testId: data });
79
+ else
80
+ this.batch.tests.push(data);
81
+ if (!this.batch.intervalFunction)
82
+ await this.batchUpload();
83
+ }
84
+ async batchUpload() {
85
+ this.batch.batchIndex++;
86
+ if (!this.batch.isEnabled)
87
+ return;
88
+ if (!this.batch.tests.length)
89
+ return;
90
+ const testsToSend = this.batch.tests.splice(0);
91
+ this.logToFile({ action: 'addTestsBatch', tests: testsToSend });
92
+ }
93
+ async finishRun(params) {
94
+ if (!this.isEnabled)
95
+ return;
96
+ this.logToFile({ actions: 'finishRun', params });
97
+ await this.batchUpload();
98
+ if (this.batch.intervalFunction)
99
+ clearInterval(this.batch.intervalFunction);
100
+ console.log(constants_js_1.APP_PREFIX, '🪲. Debug Saved to', this.logFilePath);
101
+ }
102
+ toString() {
103
+ return 'Debug Reporter';
104
+ }
105
+ }
106
+ exports.DebugPipe = DebugPipe;
107
+
108
+ module.exports.DebugPipe = DebugPipe;