@testomatio/reporter 1.2.4-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 (48) hide show
  1. package/README.md +61 -54
  2. package/lib/adapter/codecept.js +96 -35
  3. package/lib/adapter/cucumber/current.js +19 -12
  4. package/lib/adapter/cucumber/legacy.js +8 -7
  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 +80 -27
  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 +192 -69
  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 -12
  42. package/lib/xmlReader.js +211 -122
  43. package/package.json +18 -7
  44. package/lib/_ArtifactStorageOld.js +0 -142
  45. package/lib/artifactStorage.js +0 -25
  46. package/lib/dataStorage.js +0 -241
  47. package/lib/helpers.js +0 -34
  48. package/lib/logger.js +0 -293
@@ -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
- if (!this.pipes.filter(p => p.isEnabled).length) return Promise.resolve();
42
-
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 = {};
102
+ if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
51
103
 
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,12 +114,13 @@ 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
- if (!this.pipes.filter(p => p.isEnabled).length) return;
121
+ if (!this.pipes?.filter(p => p.isEnabled).length) return [];
122
+
123
+ if (isTestShouldBeExculedFromReport(testData)) return [];
71
124
 
72
125
  if (!testData)
73
126
  testData = {
@@ -84,44 +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 = testData.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
154
 
105
- // in some cases (e.g. using cucumber) logger instance becomes empty object, if import at the top of the file
106
- const logger = require('./logger');
107
- const testLogs = logger.getLogs(test_id);
108
- // debug(`Test logs for ${test_id}:\n`, testLogs);
109
- if (stack) stack += '\n\n';
110
- stack += testLogs ? `${chalk.bold('Logs:')}\n${testLogs}` : '';
155
+ // Attach logs
156
+ const fullLogs = this.formatLogs({ error: errorFormatted, steps, logs: testData.logs });
111
157
 
112
- if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
113
- debug('CLIENT storeArtifact', storeArtifacts);
114
- files.push(...storeArtifacts);
115
- }
158
+ // add artifacts
159
+ if (manuallyAttachedArtifacts?.length) files.push(...manuallyAttachedArtifacts);
116
160
 
117
- if (Array.isArray(global.testomatioArtifacts)) {
118
- debug('CLIENT global[testomatioArtifacts]', global.testomatioArtifacts);
119
- files.push(...global.testomatioArtifacts);
120
- global.testomatioArtifacts = [];
121
- }
161
+ const uploadedFiles = [];
122
162
 
123
- for (const file of files) {
124
- uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
163
+ for (const f of files) {
164
+ uploadedFiles.push(upload.uploadFileByPath(f, this.uuid));
125
165
  }
126
166
 
127
167
  for (const [idx, buffer] of filesBuffers.entries()) {
@@ -129,18 +169,22 @@ class Client {
129
169
  uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
130
170
  }
131
171
 
132
- const artifacts = await Promise.all(uploadedFiles);
172
+ const artifacts = (await Promise.all(uploadedFiles)).filter(n => !!n);
133
173
 
134
- global.testomatioArtifacts = [];
174
+ if (artifacts.length < uploadedFiles.length) {
175
+ const failedUploading = uploadedFiles.length - artifacts.length;
176
+ this.failedToUpload += failedUploading;
177
+ }
135
178
 
136
- this.totalUploaded += uploadedFiles.filter(n => n).length;
179
+ this.totalUploaded += artifacts.length;
137
180
 
138
181
  const data = {
139
182
  files,
140
183
  steps,
141
184
  status,
142
- stack,
185
+ stack: fullLogs,
143
186
  example,
187
+ file,
144
188
  code,
145
189
  title,
146
190
  suite_title,
@@ -149,19 +193,24 @@ class Client {
149
193
  message,
150
194
  run_time: parseFloat(time),
151
195
  artifacts,
196
+ meta,
152
197
  };
153
198
 
154
- this.queue = this.queue
155
- .then(() => Promise.all(this.pipes.map(async p => {
156
- try {
157
- const result = await p.addTest(data);
158
- return { pipe: p.toString(), result };
159
- } catch (err) {
160
- console.log(APP_PREFIX, p.toString(), err);
161
- }
162
- }
163
- )));
164
-
199
+ // debug('Adding test run...', data);
200
+
201
+ this.queue = this.queue.then(() =>
202
+ Promise.all(
203
+ this.pipes.map(async pipe => {
204
+ try {
205
+ const result = await pipe.addTest(data);
206
+ return { pipe: pipe.toString(), result };
207
+ } catch (err) {
208
+ console.log(APP_PREFIX, pipe.toString(), err);
209
+ }
210
+ }),
211
+ ),
212
+ );
213
+
165
214
  return this.queue;
166
215
  }
167
216
 
@@ -173,23 +222,36 @@ class Client {
173
222
  * @returns {Promise<any>} - A Promise that resolves when finishes the run.
174
223
  */
175
224
  updateRunStatus(status, isParallel = false) {
225
+ debug('Updating run status...');
176
226
  // all pipes disabled, skipping
177
- if (!this.pipes.filter(p => p.isEnabled).length) return Promise.resolve();
227
+ if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
178
228
 
179
229
  const runParams = { status, parallel: isParallel };
180
230
 
181
231
  this.queue = this.queue
182
232
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
183
233
  .then(() => {
184
- 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`);
185
237
 
186
- if (upload.isArtifactsEnabled() && this.totalUploaded > 0) {
238
+ if (this.totalUploaded && upload.isArtifactsEnabled()) {
187
239
  console.log(
188
240
  APP_PREFIX,
189
- `🗄️ Total ${this.totalUploaded} artifacts ${
241
+ `🗄️ ${this.totalUploaded} artifacts ${
190
242
  process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
191
- } uploaded to S3 bucket `,
243
+ } uploaded to S3 bucket`,
192
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
+ }
193
255
  }
194
256
  })
195
257
  .catch(err => console.log(APP_PREFIX, err));
@@ -197,15 +259,27 @@ class Client {
197
259
  return this.queue;
198
260
  }
199
261
 
200
- formatSteps(stack, steps) {
201
- 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;
202
276
  }
203
277
 
204
278
  formatError(error, message) {
205
279
  if (!message) message = error.message;
206
280
  if (error.inspect) message = error.inspect() || '';
207
281
 
208
- let stack = `\n${chalk.bold(message)}\n`;
282
+ let stack = `${message}\n`;
209
283
 
210
284
  // diffs for mocha, cypress, codeceptjs style
211
285
  if (error.actual && error.expected) {
@@ -215,17 +289,21 @@ class Client {
215
289
  stack += '\n\n';
216
290
  }
217
291
 
292
+ const customFilter = process.env.TESTOMATIO_STACK_IGNORE;
293
+
218
294
  try {
295
+ let hasFrame = false;
219
296
  const record = createCallsiteRecord({
220
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
+ },
221
304
  });
222
305
  if (record && !record.filename.startsWith('http')) {
223
- stack += record.renderSync({
224
- stackFilter: frame =>
225
- frame.getFileName().indexOf(sep) > -1 &&
226
- frame.getFileName().indexOf('node_modules') < 0 &&
227
- frame.getFileName().indexOf('internal') < 0,
228
- });
306
+ stack += record.renderSync({ stackFilter: isNotInternalFrame });
229
307
  }
230
308
  return stack;
231
309
  } catch (e) {
@@ -234,4 +312,49 @@ class Client {
234
312
  }
235
313
  }
236
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
+
237
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
+ };