@testomatio/reporter 1.3.0-beta → 1.3.0-ignore-stack-for-passed.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +61 -54
  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 +1 -1
  12. package/lib/bin/reportXml.js +14 -13
  13. package/lib/bin/startTest.js +27 -6
  14. package/lib/client.js +180 -61
  15. package/lib/config.js +34 -0
  16. package/lib/constants.js +19 -7
  17. package/lib/data-storage.js +203 -0
  18. package/lib/fileUploader.js +128 -53
  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 +27 -39
  28. package/lib/pipe/gitlab.js +20 -24
  29. package/lib/pipe/html.js +317 -0
  30. package/lib/pipe/index.js +3 -1
  31. package/lib/pipe/testomatio.js +189 -56
  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/template-draft.hbs +249 -0
  39. package/lib/template/testomatio.hbs +388 -0
  40. package/lib/utils/pipe_utils.js +128 -0
  41. package/lib/{util.js → utils/utils.js} +144 -14
  42. package/lib/xmlReader.js +211 -122
  43. package/package.json +16 -7
  44. package/lib/_ArtifactStorageOld.js +0 -142
  45. package/lib/artifactStorage.js +0 -25
  46. package/lib/dataStorage.js +0 -244
  47. package/lib/logger.js +0 -294
@@ -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,7 +38,7 @@ 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
 
@@ -46,7 +47,7 @@ program
46
47
  timeoutTimer = setTimeout(() => {
47
48
  console.log(`⚠️ Reached timeout of ${opts.timelimit}s. Exiting... (Exit code is 0 to not fail the pipeline)`);
48
49
  process.exit(0);
49
- }, parseInt(opts.timelimit, 10) * 1000)
50
+ }, parseInt(opts.timelimit, 10) * 1000);
50
51
  }
51
52
 
52
53
  try {
@@ -56,7 +57,7 @@ program
56
57
  console.log(APP_PREFIX, 'Error updating status, skipping...', err);
57
58
  }
58
59
 
59
- if (timeoutTimer) clearTimeout(timeoutTimer)
60
+ if (timeoutTimer) clearTimeout(timeoutTimer);
60
61
  });
61
62
 
62
63
  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
@@ -21,36 +26,83 @@ class Client {
21
26
  * @param {*} params
22
27
  */
23
28
  constructor(params = {}) {
24
- this.parallel = params.parallel;
25
29
  const store = {};
26
30
  this.uuid = randomUUID();
27
31
  this.pipes = pipesFactory(params, store);
28
32
  this.queue = Promise.resolve();
29
33
  this.totalUploaded = 0;
34
+ this.failedToUpload = 0;
30
35
  this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
36
+ this.executionList = Promise.resolve();
37
+
31
38
  console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
32
39
  }
33
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
+
34
94
  /**
35
95
  * Used to create a new Test run
36
96
  *
37
97
  * @returns {Promise<any>} - resolves to Run id which should be used to update / add test
38
98
  */
39
99
  createRun() {
100
+ debug('Creating run...');
40
101
  // all pipes disabled, skipping
41
102
  if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
42
103
 
43
- const runParams = {
44
- title: this.title,
45
- parallel: this.parallel,
46
- env: this.env,
47
- };
48
-
49
- global.testomatioArtifacts = [];
50
- if (!global.testomatioDataStore) global.testomatioDataStore = {};
51
-
52
104
  this.queue = this.queue
53
- .then(() => Promise.all(this.pipes.map(p => p.createRun(runParams))))
105
+ .then(() => Promise.all(this.pipes.map(p => p.createRun())))
54
106
  .catch(err => console.log(APP_PREFIX, err))
55
107
  .then(() => undefined); // fixes return type
56
108
  // debug('Run', this.queue);
@@ -62,13 +114,14 @@ class Client {
62
114
  *
63
115
  * @param {string|undefined} status
64
116
  * @param {TestData} [testData]
65
- * @param {string[]} [storeArtifacts]
66
117
  * @returns {Promise<PipeResult[]>}
67
118
  */
68
- async addTestRun(status, testData, storeArtifacts = []) {
119
+ async addTestRun(status, testData) {
69
120
  // all pipes disabled, skipping
70
121
  if (!this.pipes?.filter(p => p.isEnabled).length) return [];
71
122
 
123
+ if (isTestShouldBeExculedFromReport(testData)) return [];
124
+
72
125
  if (!testData)
73
126
  testData = {
74
127
  title: 'Unknown test',
@@ -84,46 +137,31 @@ class Client {
84
137
  steps,
85
138
  code = null,
86
139
  title,
140
+ file,
87
141
  suite_title,
88
142
  suite_id,
89
143
  test_id,
144
+ manuallyAttachedArtifacts,
145
+ meta,
90
146
  } = testData;
91
147
  let { message = '' } = testData;
92
148
 
93
- const uploadedFiles = [];
94
-
95
- let stack = '';
96
-
149
+ let errorFormatted = '';
97
150
  if (error) {
98
- stack = this.formatError(error) || '';
151
+ errorFormatted += this.formatError(error) || '';
99
152
  message = error?.message;
100
153
  }
101
- if (steps) {
102
- stack += this.formatSteps(stack, steps);
103
- }
104
-
105
- stack += testData.stack || '';
106
154
 
107
- // in some cases (e.g. using cucumber) logger instance becomes empty object, if import at the top of the file
108
- const logger = require('./logger');
109
- const testLogs = logger.getLogs(test_id);
110
- // debug(`Test logs for ${test_id}:\n`, testLogs);
111
- if (stack) stack += '\n\n';
112
- stack += testLogs ? `${chalk.bold('Logs:')}\n${testLogs}` : '';
155
+ // Attach logs
156
+ const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
113
157
 
114
- if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
115
- debug('CLIENT storeArtifact', storeArtifacts);
116
- files.push(...storeArtifacts);
117
- }
158
+ // add artifacts
159
+ if (manuallyAttachedArtifacts?.length) files.push(...manuallyAttachedArtifacts);
118
160
 
119
- if (Array.isArray(global.testomatioArtifacts)) {
120
- debug('CLIENT global[testomatioArtifacts]', global.testomatioArtifacts);
121
- files.push(...global.testomatioArtifacts);
122
- global.testomatioArtifacts = [];
123
- }
161
+ const uploadedFiles = [];
124
162
 
125
- for (const file of files) {
126
- uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
163
+ for (const f of files) {
164
+ uploadedFiles.push(upload.uploadFileByPath(f, this.uuid));
127
165
  }
128
166
 
129
167
  for (const [idx, buffer] of filesBuffers.entries()) {
@@ -131,18 +169,22 @@ class Client {
131
169
  uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
132
170
  }
133
171
 
134
- const artifacts = await Promise.all(uploadedFiles);
172
+ const artifacts = (await Promise.all(uploadedFiles)).filter(n => !!n);
135
173
 
136
- global.testomatioArtifacts = [];
174
+ if (artifacts.length < uploadedFiles.length) {
175
+ const failedUploading = uploadedFiles.length - artifacts.length;
176
+ this.failedToUpload += failedUploading;
177
+ }
137
178
 
138
- this.totalUploaded += uploadedFiles.filter(n => n).length;
179
+ this.totalUploaded += artifacts.length;
139
180
 
140
181
  const data = {
141
182
  files,
142
183
  steps,
143
184
  status,
144
- stack,
185
+ stack: fullLogs,
145
186
  example,
187
+ file,
146
188
  code,
147
189
  title,
148
190
  suite_title,
@@ -151,16 +193,19 @@ class Client {
151
193
  message,
152
194
  run_time: parseFloat(time),
153
195
  artifacts,
196
+ meta,
154
197
  };
155
198
 
199
+ // debug('Adding test run...', data);
200
+
156
201
  this.queue = this.queue.then(() =>
157
202
  Promise.all(
158
- this.pipes.map(async p => {
203
+ this.pipes.map(async pipe => {
159
204
  try {
160
- const result = await p.addTest(data);
161
- return { pipe: p.toString(), result };
205
+ const result = await pipe.addTest(data);
206
+ return { pipe: pipe.toString(), result };
162
207
  } catch (err) {
163
- console.log(APP_PREFIX, p.toString(), err);
208
+ console.log(APP_PREFIX, pipe.toString(), err);
164
209
  }
165
210
  }),
166
211
  ),
@@ -177,6 +222,7 @@ class Client {
177
222
  * @returns {Promise<any>} - A Promise that resolves when finishes the run.
178
223
  */
179
224
  updateRunStatus(status, isParallel = false) {
225
+ debug('Updating run status...');
180
226
  // all pipes disabled, skipping
181
227
  if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
182
228
 
@@ -185,15 +231,27 @@ class Client {
185
231
  this.queue = this.queue
186
232
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
187
233
  .then(() => {
188
- 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`);
189
237
 
190
- if (upload.isArtifactsEnabled() && this.totalUploaded > 0) {
238
+ if (this.totalUploaded && upload.isArtifactsEnabled()) {
191
239
  console.log(
192
240
  APP_PREFIX,
193
- `🗄️ Total ${this.totalUploaded} artifacts ${
241
+ `🗄️ ${this.totalUploaded} artifacts ${
194
242
  process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
195
- } uploaded to S3 bucket `,
243
+ } uploaded to S3 bucket`,
196
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
+ }
197
255
  }
198
256
  })
199
257
  .catch(err => console.log(APP_PREFIX, err));
@@ -201,15 +259,27 @@ class Client {
201
259
  return this.queue;
202
260
  }
203
261
 
204
- formatSteps(stack, steps) {
205
- 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;
206
276
  }
207
277
 
208
278
  formatError(error, message) {
209
279
  if (!message) message = error.message;
210
280
  if (error.inspect) message = error.inspect() || '';
211
281
 
212
- let stack = `\n${chalk.bold(message)}\n`;
282
+ let stack = `${message}\n`;
213
283
 
214
284
  // diffs for mocha, cypress, codeceptjs style
215
285
  if (error.actual && error.expected) {
@@ -219,17 +289,21 @@ class Client {
219
289
  stack += '\n\n';
220
290
  }
221
291
 
292
+ const customFilter = process.env.TESTOMATIO_STACK_IGNORE;
293
+
222
294
  try {
295
+ let hasFrame = false;
223
296
  const record = createCallsiteRecord({
224
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
+ },
225
304
  });
226
305
  if (record && !record.filename.startsWith('http')) {
227
- stack += record.renderSync({
228
- stackFilter: frame =>
229
- frame.getFileName().indexOf(sep) > -1 &&
230
- frame.getFileName().indexOf('node_modules') < 0 &&
231
- frame.getFileName().indexOf('internal') < 0,
232
- });
306
+ stack += record.renderSync({ stackFilter: isNotInternalFrame });
233
307
  }
234
308
  return stack;
235
309
  } catch (e) {
@@ -238,4 +312,49 @@ class Client {
238
312
  }
239
313
  }
240
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
+
241
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,12 @@
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
7
+ const AXIOS_RETRY_TIMEOUT = 5 * 1000; // sum = 5sec
5
8
 
6
- const TESTOMAT_TMP_STORAGE = {
7
- mainDir: "testomatio_tmp",
8
- }
9
+ const TESTOMAT_TMP_STORAGE_DIR = path.join(os.tmpdir(), 'testomatio_tmp');
9
10
 
10
11
  const CSV_HEADERS = [
11
12
  { id: 'suite_title', title: 'Suite_title' },
@@ -21,11 +22,22 @@ const STATUS = {
21
22
  SKIPPED: 'skipped',
22
23
  FINISHED: 'finished',
23
24
  };
25
+ // html pipe var
26
+ const HTML_REPORT = {
27
+ FOLDER: 'html-report',
28
+ REPORT_DEFAULT_NAME: 'testomatio-report.html',
29
+ TEMPLATE_NAME: 'testomatio.hbs',
30
+ };
31
+
32
+ const testomatLogoURL = 'https://avatars.githubusercontent.com/u/59105116?s=36&v=4';
24
33
 
25
34
  module.exports = {
26
35
  APP_PREFIX,
27
- TESTOMAT_ARTIFACT_SUFFIX,
28
- TESTOMAT_TMP_STORAGE,
36
+ TESTOMAT_TMP_STORAGE_DIR,
29
37
  CSV_HEADERS,
30
38
  STATUS,
31
- }
39
+ HTML_REPORT,
40
+ AXIOS_TIMEOUT,
41
+ AXIOS_RETRY_TIMEOUT,
42
+ testomatLogoURL,
43
+ };