@testomatio/reporter 2.0.0-beta-esm → 2.0.0-beta.1-xml

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 (123) hide show
  1. package/lib/adapter/codecept.d.ts +2 -0
  2. package/lib/adapter/codecept.js +31 -26
  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 +10 -10
  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 -4
  12. package/lib/adapter/nightwatch.d.ts +4 -0
  13. package/lib/adapter/nightwatch.js +80 -0
  14. package/lib/adapter/playwright.d.ts +14 -0
  15. package/lib/adapter/playwright.js +58 -33
  16. package/lib/adapter/vitest.d.ts +35 -0
  17. package/lib/adapter/vitest.js +6 -6
  18. package/lib/adapter/webdriver.d.ts +24 -0
  19. package/lib/adapter/webdriver.js +51 -14
  20. package/lib/bin/cli.d.ts +2 -0
  21. package/lib/bin/cli.js +250 -0
  22. package/lib/bin/reportXml.d.ts +2 -0
  23. package/lib/bin/reportXml.js +15 -11
  24. package/lib/bin/startTest.d.ts +2 -0
  25. package/lib/bin/startTest.js +12 -7
  26. package/lib/bin/uploadArtifacts.d.ts +2 -0
  27. package/lib/bin/uploadArtifacts.js +82 -0
  28. package/lib/client.d.ts +76 -0
  29. package/lib/client.js +128 -53
  30. package/lib/config.d.ts +1 -0
  31. package/lib/config.js +2 -2
  32. package/lib/constants.d.ts +25 -0
  33. package/lib/constants.js +5 -1
  34. package/lib/data-storage.d.ts +34 -0
  35. package/lib/data-storage.js +19 -9
  36. package/lib/junit-adapter/adapter.d.ts +9 -0
  37. package/lib/junit-adapter/csharp.d.ts +5 -0
  38. package/lib/junit-adapter/csharp.js +11 -1
  39. package/lib/junit-adapter/index.d.ts +3 -0
  40. package/lib/junit-adapter/java.d.ts +5 -0
  41. package/lib/junit-adapter/javascript.d.ts +4 -0
  42. package/lib/junit-adapter/python.d.ts +5 -0
  43. package/lib/junit-adapter/ruby.d.ts +4 -0
  44. package/lib/output.d.ts +11 -0
  45. package/lib/package.json +3 -1
  46. package/lib/pipe/bitbucket.d.ts +23 -0
  47. package/lib/pipe/bitbucket.js +19 -9
  48. package/lib/pipe/csv.d.ts +47 -0
  49. package/lib/pipe/csv.js +2 -2
  50. package/lib/pipe/debug.d.ts +29 -0
  51. package/lib/pipe/debug.js +108 -0
  52. package/lib/pipe/github.d.ts +30 -0
  53. package/lib/pipe/github.js +37 -5
  54. package/lib/pipe/gitlab.d.ts +23 -0
  55. package/lib/pipe/gitlab.js +2 -3
  56. package/lib/pipe/html.d.ts +35 -0
  57. package/lib/pipe/html.js +9 -4
  58. package/lib/pipe/index.d.ts +1 -0
  59. package/lib/pipe/index.js +20 -10
  60. package/lib/pipe/testomatio.d.ts +70 -0
  61. package/lib/pipe/testomatio.js +54 -39
  62. package/lib/reporter-functions.d.ts +34 -0
  63. package/lib/reporter-functions.js +17 -7
  64. package/lib/reporter.d.ts +232 -0
  65. package/lib/reporter.js +19 -33
  66. package/lib/services/artifacts.d.ts +33 -0
  67. package/lib/services/index.d.ts +9 -0
  68. package/lib/services/key-values.d.ts +27 -0
  69. package/lib/services/key-values.js +1 -1
  70. package/lib/services/logger.d.ts +64 -0
  71. package/lib/services/logger.js +1 -2
  72. package/lib/template/testomatio.hbs +651 -1366
  73. package/lib/uploader.d.ts +60 -0
  74. package/lib/uploader.js +312 -0
  75. package/lib/utils/pipe_utils.d.ts +41 -0
  76. package/lib/utils/pipe_utils.js +3 -5
  77. package/lib/utils/utils.d.ts +47 -0
  78. package/lib/utils/utils.js +99 -12
  79. package/lib/xmlReader.d.ts +92 -0
  80. package/lib/xmlReader.js +64 -25
  81. package/package.json +19 -13
  82. package/src/adapter/codecept.js +30 -26
  83. package/src/adapter/cypress-plugin/index.js +5 -5
  84. package/src/adapter/mocha.cjs +1 -1
  85. package/src/adapter/mocha.js +4 -4
  86. package/src/adapter/nightwatch.js +88 -0
  87. package/src/adapter/playwright.js +59 -31
  88. package/src/adapter/vitest.js +6 -6
  89. package/src/adapter/webdriver.js +42 -12
  90. package/src/bin/cli.js +303 -0
  91. package/src/bin/reportXml.js +19 -9
  92. package/src/bin/startTest.js +9 -4
  93. package/src/bin/uploadArtifacts.js +91 -0
  94. package/src/client.js +137 -57
  95. package/src/config.js +2 -2
  96. package/src/constants.js +5 -1
  97. package/src/data-storage.js +2 -2
  98. package/src/junit-adapter/csharp.js +13 -1
  99. package/src/pipe/bitbucket.js +2 -2
  100. package/src/pipe/csv.js +3 -3
  101. package/src/pipe/debug.js +104 -0
  102. package/src/pipe/github.js +3 -5
  103. package/src/pipe/gitlab.js +6 -7
  104. package/src/pipe/html.js +14 -7
  105. package/src/pipe/index.js +5 -7
  106. package/src/pipe/testomatio.js +75 -76
  107. package/src/reporter-functions.js +18 -7
  108. package/src/reporter.cjs_decprecated +21 -0
  109. package/src/reporter.js +20 -11
  110. package/src/services/key-values.js +1 -1
  111. package/src/services/logger.js +5 -4
  112. package/src/template/testomatio.hbs +651 -1366
  113. package/src/uploader.js +371 -0
  114. package/src/utils/pipe_utils.js +4 -12
  115. package/src/utils/utils.js +64 -15
  116. package/src/xmlReader.js +76 -26
  117. package/lib/adapter/jasmine/jasmine.js +0 -63
  118. package/lib/adapter/mocha/mocha.js +0 -125
  119. package/lib/fileUploader.js +0 -245
  120. package/lib/utils/chalk.js +0 -10
  121. package/src/fileUploader.js +0 -307
  122. package/src/reporter.cjs +0 -22
  123. package/src/utils/chalk.js +0 -13
package/lib/client.js CHANGED
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
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
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -33,32 +43,33 @@ const minimatch_1 = require("minimatch");
33
43
  const fs_1 = __importDefault(require("fs"));
34
44
  const picocolors_1 = __importDefault(require("picocolors"));
35
45
  const crypto_1 = require("crypto");
36
- const fileUploader_js_1 = require("./fileUploader.js");
37
46
  const constants_js_1 = require("./constants.js");
38
47
  const index_js_1 = require("./pipe/index.js");
39
48
  const glob_1 = require("glob");
40
49
  const path_1 = __importStar(require("path"));
41
50
  const node_url_1 = require("node:url");
51
+ const uploader_js_1 = require("./uploader.js");
52
+ const utils_js_1 = require("./utils/utils.js");
53
+ const filesize_1 = require("filesize");
42
54
  const debug = (0, debug_1.default)('@testomatio/reporter:client');
43
55
  // removed __dirname usage, because:
44
56
  // 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)
57
+ // 2. got error "__dirname already defined" in compiles js code (cjs dir)
46
58
  let listOfTestFilesToExcludeFromReport = null;
47
59
  /**
48
- * @typedef {import('../types').TestData} TestData
49
- * @typedef {import('../types').PipeResult} PipeResult
60
+ * @typedef {import('../types/types.js').TestData} TestData
61
+ * @typedef {import('../types/types.js').PipeResult} PipeResult
50
62
  */
51
63
  class Client {
52
64
  /**
53
65
  * Create a Testomat client instance
54
66
  * @returns
55
67
  */
56
- // eslint-disable-next-line
57
68
  constructor(params = {}) {
58
- this.uuid = (0, crypto_1.randomUUID)();
69
+ this.paramsForPipesFactory = params;
70
+ this.pipeStore = {};
71
+ this.runId = (0, crypto_1.randomUUID)(); // will be replaced by real run id
59
72
  this.queue = Promise.resolve();
60
- this.totalUploaded = 0;
61
- this.failedToUpload = 0;
62
73
  // @ts-ignore this line will be removed in compiled code, because __dirname is defined in commonjs
63
74
  const pathToPackageJSON = path_1.default.join(__dirname, '../package.json');
64
75
  try {
@@ -69,6 +80,7 @@ class Client {
69
80
  // do nothing
70
81
  }
71
82
  this.executionList = Promise.resolve();
83
+ this.uploader = new uploader_js_1.S3Uploader();
72
84
  }
73
85
  /**
74
86
  * Asynchronously prepares the execution list for running tests through various pipes.
@@ -87,8 +99,7 @@ class Client {
87
99
  * or resolves to undefined if no valid results are found or if all pipes are disabled.
88
100
  */
89
101
  async prepareRun(params) {
90
- const store = {};
91
- this.pipes = await (0, index_js_1.pipesFactory)(params, store);
102
+ this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
92
103
  const { pipe, pipeOptions } = params;
93
104
  // all pipes disabled, skipping
94
105
  if (!this.pipes.some(p => p.isEnabled)) {
@@ -96,7 +107,7 @@ class Client {
96
107
  }
97
108
  try {
98
109
  const filterPipe = this.pipes.find(p => p.constructor.name.toLowerCase() === `${pipe.toLowerCase()}pipe`);
99
- if (!filterPipe.isEnabled) {
110
+ if (!filterPipe?.isEnabled) {
100
111
  // TODO:for the future for the another pipes
101
112
  console.warn(constants_js_1.APP_PREFIX, `At the moment processing is available only for the "testomatio" key. Example: "testomatio:tag-name=xxx"`);
102
113
  return;
@@ -120,7 +131,7 @@ class Client {
120
131
  */
121
132
  async createRun(params) {
122
133
  if (!this.pipes || !this.pipes.length)
123
- this.pipes = await (0, index_js_1.pipesFactory)(params || {}, {});
134
+ this.pipes = await (0, index_js_1.pipesFactory)(params || this.paramsForPipesFactory || {}, this.pipeStore);
124
135
  debug('Creating run...');
125
136
  // all pipes disabled, skipping
126
137
  if (!this.pipes?.filter(p => p.isEnabled).length)
@@ -128,6 +139,13 @@ class Client {
128
139
  this.queue = this.queue
129
140
  .then(() => Promise.all(this.pipes.map(p => p.createRun())))
130
141
  .catch(err => console.log(constants_js_1.APP_PREFIX, err))
142
+ .then(() => {
143
+ const runId = this.pipeStore?.runId;
144
+ if (runId)
145
+ this.runId = runId;
146
+ (0, utils_js_1.storeRunId)(this.runId);
147
+ })
148
+ .then(() => this.uploader.checkEnabled())
131
149
  .then(() => undefined); // fixes return type
132
150
  // debug('Run', this.queue);
133
151
  return this.queue;
@@ -157,8 +175,45 @@ class Client {
157
175
  /**
158
176
  * @type {TestData}
159
177
  */
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;
178
+ const { rid, error = null, time = 0, example = null, files = [], filesBuffers = [], steps, code = null, title, file, suite_title, suite_id, test_id, manuallyAttachedArtifacts, } = testData;
179
+ let { message = '', meta = {} } = testData;
180
+ // stringify meta values and limit keys and values length to 255
181
+ meta = Object.entries(meta)
182
+ .filter(([, value]) => value !== null && value !== undefined)
183
+ .map(([key, value]) => {
184
+ try {
185
+ if (typeof value === 'object') {
186
+ value = JSON.stringify(value);
187
+ }
188
+ else if (typeof value !== 'string') {
189
+ try {
190
+ value = value.toString();
191
+ }
192
+ catch (err) {
193
+ console.warn(constants_js_1.APP_PREFIX, `Can't convert meta value to string`, err);
194
+ }
195
+ }
196
+ if (value?.length > 255) {
197
+ value = value.substring(0, 255);
198
+ debug(constants_js_1.APP_PREFIX, `Meta info value "${value}" is too long, trimmed to 255 characters`);
199
+ }
200
+ if (key?.length > 255) {
201
+ const newKey = key.substring(0, 255);
202
+ debug(constants_js_1.APP_PREFIX, `Meta info key "${key}" is too long, trimmed to 255 characters`);
203
+ return [newKey, value];
204
+ }
205
+ return [key, value];
206
+ }
207
+ catch (err) {
208
+ debug(constants_js_1.APP_PREFIX, `Error while processing meta info key ${key}`, err);
209
+ return [null, null];
210
+ }
211
+ })
212
+ .reduce((acc, [key, value]) => {
213
+ if (key)
214
+ acc[key] = value;
215
+ return acc;
216
+ }, {});
162
217
  let errorFormatted = '';
163
218
  if (error) {
164
219
  errorFormatted += this.formatError(error) || '';
@@ -170,19 +225,21 @@ class Client {
170
225
  if (manuallyAttachedArtifacts?.length)
171
226
  files.push(...manuallyAttachedArtifacts);
172
227
  const uploadedFiles = [];
173
- for (const f of files) {
174
- uploadedFiles.push(fileUploader_js_1.upload.uploadFileByPath(f, this.uuid));
228
+ for (let f of files) {
229
+ if (!f)
230
+ continue; // f === null
231
+ if (typeof f === 'object') {
232
+ if (!f.path)
233
+ continue;
234
+ f = f.path;
235
+ }
236
+ uploadedFiles.push(this.uploader.uploadFileByPath(f, [this.runId, rid, path_1.default.basename(f)]));
175
237
  }
176
238
  for (const [idx, buffer] of filesBuffers.entries()) {
177
239
  const fileName = `${idx + 1}-${title.replace(/\s+/g, '-')}`;
178
- uploadedFiles.push(fileUploader_js_1.upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
240
+ uploadedFiles.push(this.uploader.uploadFileAsBuffer(buffer, [this.runId, rid, fileName]));
179
241
  }
180
242
  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
243
  const data = {
187
244
  rid,
188
245
  files,
@@ -232,15 +289,47 @@ class Client {
232
289
  this.queue = this.queue
233
290
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
234
291
  .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
- }
292
+ if (!this.uploader.isEnabled)
293
+ return;
294
+ const filesizeStrMaxLength = 7;
295
+ if (this.uploader.successfulUploads.length) {
296
+ debug('\n', constants_js_1.APP_PREFIX, `🗄️ ${this.uploader.successfulUploads.length} artifacts uploaded to S3 bucket`);
297
+ const uploadedArtifacts = this.uploader.successfulUploads.map(file => ({
298
+ relativePath: file.path.replace(process.cwd(), ''),
299
+ link: file.link,
300
+ sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
301
+ }));
302
+ uploadedArtifacts.forEach(upload => {
303
+ debug(`🟢Uploaded artifact`, `${upload.relativePath},`, 'size:', `${upload.sizePretty},`, 'link:', `${upload.link}`);
304
+ });
305
+ }
306
+ if (this.uploader.failedUploads.length) {
307
+ console.log(constants_js_1.APP_PREFIX, `🗄️ ${this.uploader.failedUploads.length} artifacts 🔴${picocolors_1.default.bold('failed')} to upload`);
308
+ const failedUploads = this.uploader.failedUploads.map(file => ({
309
+ relativePath: file.path.replace(process.cwd(), ''),
310
+ sizePretty: (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
311
+ }));
312
+ const pathPadding = Math.max(...failedUploads.map(upload => upload.relativePath.length)) + 1;
313
+ failedUploads.forEach(upload => {
314
+ console.log(` ${picocolors_1.default.gray('|')} 🔴 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
315
+ });
316
+ }
317
+ if (this.uploader.skippedUploads.length) {
318
+ console.log('\n', constants_js_1.APP_PREFIX, `🗄️ ${picocolors_1.default.bold(this.uploader.skippedUploads.length)} artifacts uploading 🟡${picocolors_1.default.bold('skipped')}`);
319
+ const skippedUploads = this.uploader.skippedUploads.map(file => ({
320
+ relativePath: file.path.replace(process.cwd(), ''),
321
+ sizePretty: file.size === null ? 'unknown' : (0, filesize_1.filesize)(file.size, { round: 0 }).toString(),
322
+ }));
323
+ const pathPadding = Math.max(...skippedUploads.map(upload => upload.relativePath.length)) + 1;
324
+ skippedUploads.forEach(upload => {
325
+ console.log(` ${picocolors_1.default.gray('|')} 🟡 ${upload.relativePath.padEnd(pathPadding)} ${picocolors_1.default.gray(`| ${upload.sizePretty.padStart(filesizeStrMaxLength)} |`)}`);
326
+ });
327
+ }
328
+ if (this.uploader.skippedUploads.length || this.uploader.failedUploads.length) {
329
+ const command = `TESTOMATIO=<your_api_key> TESTOMATIO_RUN=${this.runId} npx @testomatio/reporter upload-artifacts`;
330
+ const numberOfNotUploadedArtifacts = this.uploader.skippedUploads.length + this.uploader.failedUploads.length;
331
+ console.log(constants_js_1.APP_PREFIX, `${numberOfNotUploadedArtifacts} artifacts were not uploaded.
332
+ Run "${picocolors_1.default.magenta(command)}" with valid S3 credentials to upload skipped & failed artifacts`);
244
333
  }
245
334
  })
246
335
  .catch(err => console.log(constants_js_1.APP_PREFIX, err));
@@ -255,7 +344,7 @@ class Client {
255
344
  logs = logs?.trim();
256
345
  if (Array.isArray(steps)) {
257
346
  steps = steps
258
- .map(step => formatStep(step))
347
+ .map(step => (0, utils_js_1.formatStep)(step))
259
348
  .flat()
260
349
  .join('\n');
261
350
  }
@@ -327,20 +416,6 @@ function isNotInternalFrame(frame) {
327
416
  !frame.getFileName().includes('node_modules') &&
328
417
  !frame.getFileName().includes('internal'));
329
418
  }
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
419
  /**
345
420
  *
346
421
  * @param {TestData} testData
@@ -0,0 +1 @@
1
+ export const config: NodeJS.ProcessEnv;
package/lib/config.js CHANGED
@@ -9,10 +9,10 @@ const debug_1 = __importDefault(require("debug"));
9
9
  const debug = (0, debug_1.default)('@testomatio/reporter:config');
10
10
  /* for possibility to use multiple env files (reading different paths)
11
11
  const envFileVars = dotenv.config({ path: '.env' }).parsed; */
12
- if (process.env.TESTOMATIO_API_KEY) {
12
+ if (process.env.TESTOMATIO_API_KEY && !process.env.TESTOMATIO) {
13
13
  process.env.TESTOMATIO = process.env.TESTOMATIO_API_KEY;
14
14
  }
15
- if (process.env.TESTOMATIO_TOKEN) {
15
+ if (process.env.TESTOMATIO_TOKEN && !process.env.TESTOMATIO) {
16
16
  process.env.TESTOMATIO = process.env.TESTOMATIO_TOKEN;
17
17
  }
18
18
  if (process.env.TESTOMATIO === 'undefined')
@@ -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 {};
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
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
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -76,7 +86,7 @@ class DataStorage {
76
86
  return;
77
87
  context = context || this.context || utils_js_1.testRunnerHelper.getNameOfCurrentlyRunningTest();
78
88
  if (!context) {
79
- debug(`No context provided for "${dataType}" data:`, data);
89
+ // debug(`No context provided for "${dataType}" data:`, data);
80
90
  return;
81
91
  }
82
92
  const contextHash = stringToMD5Hash(context);
@@ -119,7 +129,7 @@ class DataStorage {
119
129
  if (testDataFromFile.length) {
120
130
  return testDataFromFile;
121
131
  }
122
- debug(`No "${dataType}" data for context "${contextHash}" in both file and global variable`);
132
+ // debug(`No "${dataType}" data for context "${contextHash}" in both file and global variable`);
123
133
  // in case no data found for context
124
134
  return null;
125
135
  }
@@ -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,5 @@
1
+ export default CSharpAdapter;
2
+ declare class CSharpAdapter extends Adapter {
3
+ getFilePath(t: any): string;
4
+ }
5
+ import Adapter from './adapter.js';
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const path_1 = __importDefault(require("path"));
6
7
  const adapter_js_1 = __importDefault(require("./adapter.js"));
7
8
  class CSharpAdapter extends adapter_js_1.default {
8
9
  formatTest(t) {
@@ -12,9 +13,18 @@ class CSharpAdapter extends adapter_js_1.default {
12
13
  t.example = { ...example[1].split(',') };
13
14
  const suite = t.suite_title.split('.');
14
15
  t.suite_title = suite.pop();
15
- t.file = suite.join('/');
16
+ t.file = namespaceToFileName(t.file);
16
17
  t.title = title.trim();
17
18
  return t;
18
19
  }
20
+ getFilePath(t) {
21
+ const fileName = namespaceToFileName(t.file);
22
+ return fileName;
23
+ }
19
24
  }
20
25
  module.exports = CSharpAdapter;
26
+ function namespaceToFileName(fileName) {
27
+ const fileParts = fileName.split('.');
28
+ fileParts[fileParts.length - 1] = fileParts[fileParts.length - 1]?.replace(/\$.*/, '');
29
+ return `${fileParts.join(path_1.default.sep)}.cs`;
30
+ }
@@ -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;
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
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
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
@@ -41,8 +51,8 @@ const debug = (0, debug_1.default)('@testomatio/reporter:pipe:bitbucket');
41
51
  //! and your pipeline trigger should be a pull request
42
52
  /**
43
53
  * @class BitbucketPipe
44
- * @typedef {import('../../types').Pipe} Pipe
45
- * @typedef {import('../../types').TestData} TestData
54
+ * @typedef {import('../../types/types.js').Pipe} Pipe
55
+ * @typedef {import('../../types/types.js').TestData} TestData
46
56
  */
47
57
  class BitbucketPipe {
48
58
  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
  */