@testomatio/reporter 1.3.5-beta → 1.4.0-beta-wdio-bdd

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 (46) hide show
  1. package/README.md +60 -57
  2. package/lib/adapter/codecept.js +96 -35
  3. package/lib/adapter/cucumber/current.js +18 -11
  4. package/lib/adapter/cucumber/legacy.js +6 -5
  5. package/lib/adapter/cucumber.js +2 -2
  6. package/lib/adapter/cypress-plugin/index.js +52 -25
  7. package/lib/adapter/jasmine.js +1 -1
  8. package/lib/adapter/jest.js +49 -16
  9. package/lib/adapter/mocha.js +103 -51
  10. package/lib/adapter/playwright.js +95 -33
  11. package/lib/adapter/webdriver.js +46 -1
  12. package/lib/bin/reportXml.js +22 -16
  13. package/lib/bin/startTest.js +27 -6
  14. package/lib/client.js +179 -53
  15. package/lib/config.js +34 -0
  16. package/lib/constants.js +32 -7
  17. package/lib/data-storage.js +203 -0
  18. package/lib/fileUploader.js +135 -54
  19. package/lib/junit-adapter/adapter.js +0 -2
  20. package/lib/junit-adapter/csharp.js +3 -4
  21. package/lib/junit-adapter/index.js +3 -3
  22. package/lib/junit-adapter/java.js +35 -17
  23. package/lib/junit-adapter/javascript.js +1 -2
  24. package/lib/junit-adapter/python.js +12 -14
  25. package/lib/junit-adapter/ruby.js +1 -2
  26. package/lib/pipe/csv.js +5 -3
  27. package/lib/pipe/github.js +9 -19
  28. package/lib/pipe/gitlab.js +22 -26
  29. package/lib/pipe/html.js +354 -0
  30. package/lib/pipe/index.js +3 -1
  31. package/lib/pipe/testomatio.js +257 -53
  32. package/lib/reporter-functions.js +46 -0
  33. package/lib/reporter.js +11 -9
  34. package/lib/services/artifacts.js +57 -0
  35. package/lib/services/index.js +13 -0
  36. package/lib/services/key-values.js +58 -0
  37. package/lib/services/logger.js +311 -0
  38. package/lib/template/testomatio.hbs +1236 -0
  39. package/lib/utils/pipe_utils.js +129 -0
  40. package/lib/{util.js → utils/utils.js} +145 -15
  41. package/lib/xmlReader.js +211 -122
  42. package/package.json +17 -9
  43. package/lib/_ArtifactStorageOld.js +0 -142
  44. package/lib/artifactStorage.js +0 -25
  45. package/lib/dataStorage.js +0 -244
  46. package/lib/logger.js +0 -301
@@ -1,29 +1,30 @@
1
1
  #!/usr/bin/env node
2
- const program = require("commander");
3
- const chalk = require("chalk");
2
+ const program = require('commander');
3
+ const chalk = require('chalk');
4
4
  const glob = require('glob');
5
5
  const debug = require('debug')('@testomatio/reporter:xml-cli');
6
6
  const { APP_PREFIX } = require('../constants');
7
- const XmlReader = require("../xmlReader");
7
+ const XmlReader = require('../xmlReader');
8
8
 
9
9
  const { version } = require('../../package.json');
10
10
 
11
11
  console.log(chalk.cyan.bold(` 🤩 Testomat.io XML Reporter v${version}`));
12
12
 
13
13
  program
14
- .arguments("<pattern>")
15
- .option("-d, --dir <dir>", "Project directory")
16
- .option("--java-tests [java-path]", "Load Java tests from path, by default: src/test/java")
17
- .option("--lang <lang>", "Language used (python, ruby, java)")
18
- .option("--timelimit <time>", "default time limit in seconds to kill a stuck process")
19
- .option("--env-file <envfile>", "Load environment variables from env file")
14
+ .arguments('<pattern>')
15
+ .option('-d, --dir <dir>', 'Project directory')
16
+ .option('--java-tests [java-path]', 'Load Java tests from path, by default: src/test/java')
17
+ .option('--lang <lang>', 'Language used (python, ruby, java)')
18
+ .option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
19
+ .option('--env-file <envfile>', 'Load environment variables from env file')
20
20
  .action(async (pattern, opts) => {
21
21
  if (!pattern.endsWith('.xml')) {
22
22
  pattern += '.xml';
23
23
  }
24
24
  let { javaTests, lang } = opts;
25
25
  if (opts.envFile) {
26
- debug('Loading env file: %s', opts.envFile)
26
+ console.log(APP_PREFIX, 'Loading env file:', opts.envFile);
27
+ debug('Loading env file: %s', opts.envFile);
27
28
  require('dotenv').config({ path: opts.envFile }); // eslint-disable-line
28
29
  }
29
30
  if (javaTests === true) javaTests = 'src/test/java';
@@ -37,16 +38,21 @@ program
37
38
  }
38
39
 
39
40
  for (const file of files) {
40
- console.log(APP_PREFIX,`Parsed ${file}`);
41
+ console.log(APP_PREFIX, `Parsed ${file}`);
41
42
  runReader.parse(file);
42
43
  }
43
44
 
44
45
  let timeoutTimer;
45
46
  if (opts.timelimit) {
46
- timeoutTimer = setTimeout(() => {
47
- console.log(`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`);
48
- process.exit(0);
49
- }, parseInt(opts.timelimit, 10) * 1000)
47
+ timeoutTimer = setTimeout(
48
+ () => {
49
+ console.log(
50
+ `⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`,
51
+ );
52
+ process.exit(0);
53
+ },
54
+ parseInt(opts.timelimit, 10) * 1000,
55
+ );
50
56
  }
51
57
 
52
58
  try {
@@ -56,7 +62,7 @@ program
56
62
  console.log(APP_PREFIX, 'Error updating status, skipping...', err);
57
63
  }
58
64
 
59
- if (timeoutTimer) clearTimeout(timeoutTimer)
65
+ if (timeoutTimer) clearTimeout(timeoutTimer);
60
66
  });
61
67
 
62
68
  if (process.argv.length < 3) {
@@ -5,6 +5,7 @@ const chalk = require('chalk');
5
5
  const TestomatClient = require('../client');
6
6
  const { APP_PREFIX, STATUS } = require('../constants');
7
7
  const { version } = require('../../package.json');
8
+ const config = require('../config');
8
9
 
9
10
  console.log(chalk.cyan.bold(` 🤩 Testomat.io Reporter v${version}`));
10
11
 
@@ -12,13 +13,15 @@ program
12
13
  .option('-c, --command <cmd>', 'Test runner command')
13
14
  .option('--launch', 'Start a new run and return its ID')
14
15
  .option('--finish', 'Finish Run by its ID')
15
- .option("--env-file <envfile>", "Load environment variables from env file")
16
- .action(opts => {
16
+ .option('--env-file <envfile>', 'Load environment variables from env file')
17
+ .option('--filter <filter>', 'Additional execution filter')
18
+ .action(async opts => {
19
+ const { launch, finish, filter } = opts;
20
+ let { command } = opts;
17
21
 
18
- const { command, launch, finish } = opts;
19
22
  if (opts.envFile) require('dotenv').config(opts.envFile); // eslint-disable-line
20
23
 
21
- const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || process.env.TESTOMATIO;
24
+ const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || config.TESTOMATIO;
22
25
  const title = process.env.TESTOMATIO_TITLE;
23
26
 
24
27
  if (launch) {
@@ -57,6 +60,26 @@ program
57
60
  return;
58
61
  }
59
62
 
63
+ const client = new TestomatClient({ apiKey, title, parallel: true });
64
+
65
+ if (filter) {
66
+ const [pipe, ...optsArray] = filter.split(':');
67
+ const pipeOptions = optsArray.join(':');
68
+
69
+ try {
70
+ const tests = await client.prepareRun({ pipe, pipeOptions });
71
+
72
+ if (!tests || tests.length === 0) {
73
+ return;
74
+ }
75
+
76
+ const grep = ` --grep (${tests.join('|')})`;
77
+ command += grep;
78
+ } catch (err) {
79
+ console.log(APP_PREFIX, err);
80
+ }
81
+ }
82
+
60
83
  const testCmds = command.split(' ');
61
84
  console.log(APP_PREFIX, `🚀 Running`, chalk.green(command));
62
85
 
@@ -73,8 +96,6 @@ program
73
96
  return;
74
97
  }
75
98
 
76
- const client = new TestomatClient({ apiKey, title, parallel: true });
77
-
78
99
  client.createRun().then(() => {
79
100
  const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
80
101
 
package/lib/client.js CHANGED
@@ -1,12 +1,17 @@
1
1
  const debug = require('debug')('@testomatio/reporter:client');
2
2
  const createCallsiteRecord = require('callsite-record');
3
3
  const { sep, join } = require('path');
4
+ const { minimatch } = require('minimatch');
4
5
  const fs = require('fs');
5
6
  const chalk = require('chalk');
6
7
  const { randomUUID } = require('crypto');
7
8
  const upload = require('./fileUploader');
8
9
  const { APP_PREFIX } = require('./constants');
9
10
  const pipesFactory = require('./pipe');
11
+ const { glob } = require('glob');
12
+ const path = require('path');
13
+
14
+ let listOfTestFilesToExcludeFromReport = null;
10
15
 
11
16
  /**
12
17
  * @typedef {import('../types').TestData} TestData
@@ -26,22 +31,76 @@ class Client {
26
31
  this.pipes = pipesFactory(params, store);
27
32
  this.queue = Promise.resolve();
28
33
  this.totalUploaded = 0;
34
+ this.failedToUpload = 0;
29
35
  this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
36
+ this.executionList = Promise.resolve();
37
+
30
38
  console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
31
39
  }
32
40
 
41
+ /**
42
+ * Asynchronously prepares the execution list for running tests through various pipes.
43
+ * Each pipe in the client is checked for enablement,
44
+ * and if all pipes are disabled, the function returns a resolved Promise.
45
+ * Otherwise, it executes the `prepareRun` method for each enabled pipe and collects the results.
46
+ * The results are then filtered to remove any undefined values.
47
+ * If no valid results are found, the function returns undefined.
48
+ * Otherwise, it returns the first non-empty array from the filtered results.
49
+ *
50
+ * @param {Object} params - The options for preparing the test execution list.
51
+ * @param {string} params.pipe - Name of the executed pipe.
52
+ * @param {string} params.pipeOptions - Filter option.
53
+ * @returns {Promise<any>} - A Promise that resolves to an
54
+ * array containing the prepared execution list,
55
+ * or resolves to undefined if no valid results are found or if all pipes are disabled.
56
+ */
57
+ async prepareRun(params) {
58
+ const { pipe, pipeOptions } = params;
59
+ // all pipes disabled, skipping
60
+ if (!this.pipes.some(p => p.isEnabled)) {
61
+ return Promise.resolve();
62
+ }
63
+
64
+ try {
65
+ const filterPipe = this.pipes.find(p => p.constructor.name.toLowerCase() === `${pipe.toLowerCase()}pipe`);
66
+
67
+ if (!filterPipe.isEnabled) {
68
+ // TODO:for the future for the another pipes
69
+ console.warn(
70
+ APP_PREFIX,
71
+ `At the moment processing is available only for the "testomatio" key. Example: "testomatio:tag-name=xxx"`,
72
+ );
73
+ return;
74
+ }
75
+
76
+ const results = await Promise.all(
77
+ this.pipes.map(async p => ({ pipe: p.toString(), result: await p.prepareRun(pipeOptions) })),
78
+ );
79
+
80
+ const result = results.filter(p => p.pipe.includes('Testomatio'))[0]?.result;
81
+
82
+ if (!result || result.length === 0) {
83
+ return;
84
+ }
85
+
86
+ debug('Execution tests list', result);
87
+
88
+ return result;
89
+ } catch (err) {
90
+ console.error(APP_PREFIX, err);
91
+ }
92
+ }
93
+
33
94
  /**
34
95
  * Used to create a new Test run
35
96
  *
36
97
  * @returns {Promise<any>} - resolves to Run id which should be used to update / add test
37
98
  */
38
99
  createRun() {
100
+ debug('Creating run...');
39
101
  // all pipes disabled, skipping
40
102
  if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
41
103
 
42
- global.testomatioArtifacts = [];
43
- if (!global.testomatioDataStore) global.testomatioDataStore = {};
44
-
45
104
  this.queue = this.queue
46
105
  .then(() => Promise.all(this.pipes.map(p => p.createRun())))
47
106
  .catch(err => console.log(APP_PREFIX, err))
@@ -55,13 +114,14 @@ class Client {
55
114
  *
56
115
  * @param {string|undefined} status
57
116
  * @param {TestData} [testData]
58
- * @param {string[]} [storeArtifacts]
59
117
  * @returns {Promise<PipeResult[]>}
60
118
  */
61
- async addTestRun(status, testData, storeArtifacts = []) {
119
+ async addTestRun(status, testData) {
62
120
  // all pipes disabled, skipping
63
121
  if (!this.pipes?.filter(p => p.isEnabled).length) return [];
64
122
 
123
+ if (isTestShouldBeExculedFromReport(testData)) return [];
124
+
65
125
  if (!testData)
66
126
  testData = {
67
127
  title: 'Unknown test',
@@ -77,46 +137,31 @@ class Client {
77
137
  steps,
78
138
  code = null,
79
139
  title,
140
+ file,
80
141
  suite_title,
81
142
  suite_id,
82
143
  test_id,
144
+ manuallyAttachedArtifacts,
145
+ meta,
83
146
  } = testData;
84
147
  let { message = '' } = testData;
85
148
 
86
- const uploadedFiles = [];
87
-
88
- let stack = '';
89
-
149
+ let errorFormatted = '';
90
150
  if (error) {
91
- stack = this.formatError(error) || '';
151
+ errorFormatted += this.formatError(error) || '';
92
152
  message = error?.message;
93
153
  }
94
- if (steps) {
95
- stack += this.formatSteps(stack, steps);
96
- }
97
154
 
98
- stack += testData.stack || '';
155
+ // Attach logs
156
+ const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
99
157
 
100
- // in some cases (e.g. using cucumber) logger instance becomes empty object, if import at the top of the file
101
- const logger = require('./logger');
102
- const testLogs = logger.getLogs(test_id);
103
- // debug(`Test logs for ${test_id}:\n`, testLogs);
104
- if (stack) stack += '\n\n';
105
- stack += testLogs ? `${chalk.bold('Logs:')}\n${testLogs}` : '';
158
+ // add artifacts
159
+ if (manuallyAttachedArtifacts?.length) files.push(...manuallyAttachedArtifacts);
106
160
 
107
- if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
108
- debug('CLIENT storeArtifact', storeArtifacts);
109
- files.push(...storeArtifacts);
110
- }
111
-
112
- if (Array.isArray(global.testomatioArtifacts)) {
113
- debug('CLIENT global[testomatioArtifacts]', global.testomatioArtifacts);
114
- files.push(...global.testomatioArtifacts);
115
- global.testomatioArtifacts = [];
116
- }
161
+ const uploadedFiles = [];
117
162
 
118
- for (const file of files) {
119
- uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
163
+ for (const f of files) {
164
+ uploadedFiles.push(upload.uploadFileByPath(f, this.uuid));
120
165
  }
121
166
 
122
167
  for (const [idx, buffer] of filesBuffers.entries()) {
@@ -124,18 +169,22 @@ class Client {
124
169
  uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
125
170
  }
126
171
 
127
- const artifacts = await Promise.all(uploadedFiles);
172
+ const artifacts = (await Promise.all(uploadedFiles)).filter(n => !!n);
128
173
 
129
- global.testomatioArtifacts = [];
174
+ if (artifacts.length < uploadedFiles.length) {
175
+ const failedUploading = uploadedFiles.length - artifacts.length;
176
+ this.failedToUpload += failedUploading;
177
+ }
130
178
 
131
- this.totalUploaded += uploadedFiles.filter(n => n).length;
179
+ this.totalUploaded += artifacts.length;
132
180
 
133
181
  const data = {
134
182
  files,
135
183
  steps,
136
184
  status,
137
- stack,
185
+ stack: fullLogs,
138
186
  example,
187
+ file,
139
188
  code,
140
189
  title,
141
190
  suite_title,
@@ -144,16 +193,19 @@ class Client {
144
193
  message,
145
194
  run_time: parseFloat(time),
146
195
  artifacts,
196
+ meta,
147
197
  };
148
198
 
199
+ // debug('Adding test run...', data);
200
+
149
201
  this.queue = this.queue.then(() =>
150
202
  Promise.all(
151
- this.pipes.map(async p => {
203
+ this.pipes.map(async pipe => {
152
204
  try {
153
- const result = await p.addTest(data);
154
- return { pipe: p.toString(), result };
205
+ const result = await pipe.addTest(data);
206
+ return { pipe: pipe.toString(), result };
155
207
  } catch (err) {
156
- console.log(APP_PREFIX, p.toString(), err);
208
+ console.log(APP_PREFIX, pipe.toString(), err);
157
209
  }
158
210
  }),
159
211
  ),
@@ -170,6 +222,7 @@ class Client {
170
222
  * @returns {Promise<any>} - A Promise that resolves when finishes the run.
171
223
  */
172
224
  updateRunStatus(status, isParallel = false) {
225
+ debug('Updating run status...');
173
226
  // all pipes disabled, skipping
174
227
  if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
175
228
 
@@ -178,15 +231,27 @@ class Client {
178
231
  this.queue = this.queue
179
232
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
180
233
  .then(() => {
181
- debug('TOTAL uploaded files', this.totalUploaded);
234
+ debug('TOTAL artifacts', this.totalUploaded);
235
+ if (this.totalUploaded && !upload.isArtifactsEnabled())
236
+ debug(`${this.totalUploaded} artifacts are not uploaded, because artifacts uploading is not enabled`);
182
237
 
183
- if (upload.isArtifactsEnabled() && this.totalUploaded > 0) {
238
+ if (this.totalUploaded && upload.isArtifactsEnabled()) {
184
239
  console.log(
185
240
  APP_PREFIX,
186
- `🗄️ Total ${this.totalUploaded} artifacts ${
241
+ `🗄️ ${this.totalUploaded} artifacts ${
187
242
  process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
188
- } uploaded to S3 bucket `,
243
+ } uploaded to S3 bucket`,
189
244
  );
245
+
246
+ if (this.failedToUpload > 0) {
247
+ console.log(
248
+ APP_PREFIX,
249
+ chalk.yellow(
250
+ `Some artifacts were not uploaded. ${this.failedToUpload} artifacts could not be uploaded.
251
+ Run tests with DEBUG="@testomatio/reporter:file-uploader" to see details"`,
252
+ ),
253
+ );
254
+ }
190
255
  }
191
256
  })
192
257
  .catch(err => console.log(APP_PREFIX, err));
@@ -194,15 +259,27 @@ class Client {
194
259
  return this.queue;
195
260
  }
196
261
 
197
- formatSteps(stack, steps) {
198
- return stack ? `${steps}\n\n${chalk.bold.red('################[ Failure ]################')}\n${stack}` : steps;
262
+ /**
263
+ * Returns the formatted stack including the stack trace, steps, and logs.
264
+ * @returns {string}
265
+ */
266
+ formatLogs({ error, steps, logs }) {
267
+ error = error?.trim();
268
+ steps = steps?.trim();
269
+ logs = logs?.trim();
270
+
271
+ let testLogs = '';
272
+ if (steps) testLogs += `${chalk.bold.blue('################[ Steps ]################')}\n${steps}\n\n`;
273
+ if (logs) testLogs += `${chalk.bold.gray('################[ Logs ]################')}\n${logs}\n\n`;
274
+ if (error) testLogs += `${chalk.bold.red('################[ Failure ]################')}\n${error}`;
275
+ return testLogs;
199
276
  }
200
277
 
201
278
  formatError(error, message) {
202
279
  if (!message) message = error.message;
203
280
  if (error.inspect) message = error.inspect() || '';
204
281
 
205
- let stack = `\n${chalk.bold(message)}\n`;
282
+ let stack = `${message}\n`;
206
283
 
207
284
  // diffs for mocha, cypress, codeceptjs style
208
285
  if (error.actual && error.expected) {
@@ -212,17 +289,21 @@ class Client {
212
289
  stack += '\n\n';
213
290
  }
214
291
 
292
+ const customFilter = process.env.TESTOMATIO_STACK_IGNORE;
293
+
215
294
  try {
295
+ let hasFrame = false;
216
296
  const record = createCallsiteRecord({
217
297
  forError: error,
298
+ isCallsiteFrame: frame => {
299
+ if (customFilter && minimatch(frame.getFileName(), customFilter)) return false;
300
+ if (hasFrame) return false;
301
+ if (isNotInternalFrame(frame)) hasFrame = true;
302
+ return hasFrame;
303
+ },
218
304
  });
219
305
  if (record && !record.filename.startsWith('http')) {
220
- stack += record.renderSync({
221
- stackFilter: frame =>
222
- frame.getFileName().indexOf(sep) > -1 &&
223
- frame.getFileName().indexOf('node_modules') < 0 &&
224
- frame.getFileName().indexOf('internal') < 0,
225
- });
306
+ stack += record.renderSync({ stackFilter: isNotInternalFrame });
226
307
  }
227
308
  return stack;
228
309
  } catch (e) {
@@ -231,4 +312,49 @@ class Client {
231
312
  }
232
313
  }
233
314
 
315
+ function isNotInternalFrame(frame) {
316
+ return (
317
+ frame.getFileName() &&
318
+ frame.getFileName().includes(sep) &&
319
+ !frame.getFileName().includes('node_modules') &&
320
+ !frame.getFileName().includes('internal')
321
+ );
322
+ }
323
+
324
+ /**
325
+ *
326
+ * @param {TestData} testData
327
+ * @returns boolean
328
+ */
329
+ function isTestShouldBeExculedFromReport(testData) {
330
+ // const fileName = path.basename(test.location?.file || '');
331
+ const globExcludeFilesPattern = process.env.TESTOMATIO_EXCLUDE_FILES_FROM_REPORT_GLOB_PATTERN;
332
+ if (!globExcludeFilesPattern) return false;
333
+
334
+ if (!testData.file) {
335
+ debug('No "file" property found for test ', testData.title);
336
+ return false;
337
+ }
338
+
339
+ const excludeParretnsList = globExcludeFilesPattern.split(';');
340
+
341
+ // as scanning files is time consuming operation, just save the result in variable to avoid multiple scans
342
+ if (!listOfTestFilesToExcludeFromReport) {
343
+ // list of files with relative paths
344
+ listOfTestFilesToExcludeFromReport = glob.sync(excludeParretnsList, { ignore: '**/node_modules/**' });
345
+ debug('Tests from next files will not be reported:', listOfTestFilesToExcludeFromReport);
346
+ }
347
+
348
+ const testFileRelativePath = path.relative(process.cwd(), testData.file);
349
+
350
+ // no files found matching the exclusion pattern
351
+ if (!listOfTestFilesToExcludeFromReport.length) return false;
352
+
353
+ if (listOfTestFilesToExcludeFromReport.includes(testFileRelativePath)) {
354
+ debug(`Excluding test '${testData.title}' <${testFileRelativePath}> from reporting`);
355
+ return true;
356
+ }
357
+ return false;
358
+ }
359
+
234
360
  module.exports = Client;
package/lib/config.js ADDED
@@ -0,0 +1,34 @@
1
+ // This file is used to read environment variables from .env file
2
+
3
+ // require('dotenv').config({ path: process.env.TESTOMATIO_ENV_FILE_PATH });
4
+
5
+ const debug = require('debug')('@testomatio/reporter:config');
6
+
7
+ /* for possibility to use multiple env files (reading different paths)
8
+ const dotenv = require('dotenv');
9
+ const envFileVars = dotenv.config({ path: '.env' }).parsed; */
10
+
11
+ if (process.env.TESTOMATIO_API_KEY) {
12
+ process.env.TESTOMATIO = process.env.TESTOMATIO_API_KEY;
13
+ }
14
+ if (process.env.TESTOMATIO_TOKEN) {
15
+ process.env.TESTOMATIO = process.env.TESTOMATIO_TOKEN;
16
+ }
17
+
18
+ if (process.env.TESTOMATIO === 'undefined')
19
+ console.error('TESTOMATIO is "undefined". Something went wrong. Contact dev team.');
20
+
21
+ // select only TESTOMATIO related variables (only to print them in debug)
22
+ const testomatioEnvVars =
23
+ Object.keys(process.env)
24
+ .filter(key => key.startsWith('TESTOMATIO') || key.startsWith('S3_'))
25
+ .reduce((obj, key) => {
26
+ obj[key] = process.env[key];
27
+ return obj;
28
+ }, {}) || {};
29
+ debug('TESTOMATIO variables:', testomatioEnvVars);
30
+
31
+ // includes variables from .env file and process.env
32
+ const config = process.env;
33
+
34
+ module.exports = config;
package/lib/constants.js CHANGED
@@ -1,11 +1,11 @@
1
1
  const chalk = require('chalk');
2
+ const os = require('os');
3
+ const path = require('path');
2
4
 
3
5
  const APP_PREFIX = chalk.gray('[TESTOMATIO]');
4
- const TESTOMAT_ARTIFACT_SUFFIX = "testomatio_artifact_";
6
+ const AXIOS_TIMEOUT = 20 * 1000; // sum = 20sec
5
7
 
6
- const TESTOMAT_TMP_STORAGE = {
7
- mainDir: "testomatio_tmp",
8
- }
8
+ const TESTOMAT_TMP_STORAGE_DIR = path.join(os.tmpdir(), 'testomatio_tmp');
9
9
 
10
10
  const CSV_HEADERS = [
11
11
  { id: 'suite_title', title: 'Suite_title' },
@@ -21,11 +21,36 @@ const STATUS = {
21
21
  SKIPPED: 'skipped',
22
22
  FINISHED: 'finished',
23
23
  };
24
+ // html pipe var
25
+ const HTML_REPORT = {
26
+ FOLDER: 'html-report',
27
+ REPORT_DEFAULT_NAME: 'testomatio-report.html',
28
+ TEMPLATE_NAME: 'testomatio.hbs',
29
+ };
30
+
31
+ const testomatLogoURL = 'https://avatars.githubusercontent.com/u/59105116?s=36&v=4';
32
+
33
+ const REPORTER_REQUEST_RETRIES = {
34
+ retryTimeout: 5 * 1000, // sum = 5sec
35
+ retriesPerRequest: 2,
36
+ maxTotalRetries: Number(process.env.TESTOMATIO_MAX_REQUEST_FAILURES_COUNT) || 10,
37
+ withinTimeSeconds: Number(process.env.TESTOMATIO_MAX_REQUEST_RETRIES_WITHIN_TIME_SECONDS) || 60,
38
+ };
39
+
40
+ const RunStatus = {
41
+ Passed: 'passed',
42
+ Failed: 'failed',
43
+ Finished: 'finished',
44
+ };
24
45
 
25
46
  module.exports = {
26
47
  APP_PREFIX,
27
- TESTOMAT_ARTIFACT_SUFFIX,
28
- TESTOMAT_TMP_STORAGE,
48
+ TESTOMAT_TMP_STORAGE_DIR,
29
49
  CSV_HEADERS,
30
50
  STATUS,
31
- }
51
+ HTML_REPORT,
52
+ AXIOS_TIMEOUT,
53
+ testomatLogoURL,
54
+ REPORTER_REQUEST_RETRIES,
55
+ RunStatus,
56
+ };