@testomatio/reporter 0.8.0-beta.31 → 0.8.0-beta.32

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.
@@ -1,9 +1,9 @@
1
1
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
2
- const debug = require('debug')('@testomatio/reporter:adapter:mocha');
3
2
  const Mocha = require('mocha');
3
+ const debug = require('debug')('@testomatio/reporter:adapter:mocha');
4
4
  const chalk = require('chalk');
5
5
  const TestomatClient = require('../client');
6
- const TRConstants = require('../constants');
6
+ const { STATUS } = require('../constants');
7
7
  const { parseTest, specificTestInfo } = require('../util');
8
8
  const ArtifactStorage = require('../ArtifactStorage');
9
9
 
@@ -26,12 +26,12 @@ function MochaReporter(runner, opts) {
26
26
  client.createRun();
27
27
 
28
28
  const params = {
29
- "toFile": true
29
+ toFile: true
30
30
  };
31
-
32
- (runner._workerReporter !== undefined)
33
- ? artifactStore = new ArtifactStorage(params)
34
- : artifactStore = new ArtifactStorage();
31
+
32
+ artifactStore = runner._workerReporter !== undefined
33
+ ? new ArtifactStorage(params)
34
+ : new ArtifactStorage();
35
35
  });
36
36
 
37
37
  runner.on(EVENT_TEST_PASS, async(test) => {
@@ -45,9 +45,9 @@ function MochaReporter(runner, opts) {
45
45
  debug(`test=${specificTest} content = `, content);
46
46
 
47
47
  client.addTestRun(
48
- testId,
49
- TRConstants.PASSED,
48
+ STATUS.PASSED,
50
49
  {
50
+ test_id: testId,
51
51
  title: test.title,
52
52
  time: test.duration,
53
53
  },
@@ -59,8 +59,9 @@ function MochaReporter(runner, opts) {
59
59
  skipped += 1;
60
60
  console.log('skip: %s', test.fullTitle());
61
61
  const testId = parseTest(test.title);
62
- client.addTestRun(testId, TRConstants.SKIPPED, {
62
+ client.addTestRun(STATUS.SKIPPED, {
63
63
  title: test.title,
64
+ test_id: testId,
64
65
  time: test.duration,
65
66
  });
66
67
  });
@@ -76,9 +77,9 @@ function MochaReporter(runner, opts) {
76
77
  debug(`fail test=${specificTest} content = `, content);
77
78
 
78
79
  client.addTestRun(
79
- testId,
80
- TRConstants.FAILED, {
80
+ STATUS.FAILED, {
81
81
  error: err,
82
+ test_id: testId,
82
83
  title: test.title,
83
84
  time: test.duration,
84
85
  },
@@ -87,7 +88,7 @@ function MochaReporter(runner, opts) {
87
88
  });
88
89
 
89
90
  runner.on(EVENT_RUN_END, () => {
90
- const status = failures === 0 ? TRConstants.PASSED : TRConstants.FAILED;
91
+ const status = failures === 0 ? STATUS.PASSED : STATUS.FAILED;
91
92
  console.log(chalk.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
92
93
  client.updateRunStatus(status);
93
94
 
@@ -3,11 +3,12 @@ const crypto = require('crypto');
3
3
  const os = require('os');
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
- const Status = require('../constants');
6
+ const { APP_PREFIX, STATUS: Status } = require('../constants');
7
7
  const TestomatioClient = require('../client');
8
8
  const upload = require('../fileUploader');
9
9
  const { parseTest } = require('../util');
10
10
 
11
+
11
12
  class TestomatioReporter {
12
13
  constructor(config = {}) {
13
14
  this.client = new TestomatioClient({ apiKey: config?.apiKey });
@@ -56,8 +57,9 @@ class TestomatioReporter {
56
57
  files.push({ path: fileName, type: attachment.contentType });
57
58
  }
58
59
 
59
- this.client.addTestRun(testId, checkStatus(result.status), {
60
+ this.client.addTestRun(checkStatus(result.status), {
60
61
  error,
62
+ test_id: testId,
61
63
  suite_title,
62
64
  title,
63
65
  files,
@@ -70,14 +72,15 @@ class TestomatioReporter {
70
72
  if (!this.client) return;
71
73
 
72
74
  if (this.videos.length && upload.isArtifactsEnabled()) {
73
- console.log(Status.APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
75
+ console.log(APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
74
76
 
75
77
  const promises = [];
76
78
  for (const video of this.videos) {
77
79
  const { testId, title, attachment, suite_title } = video;
78
80
  const file = { path: attachment.path, title, type: attachment.contentType };
79
81
  promises.push(
80
- this.client.addTestRun(testId, undefined, {
82
+ this.client.addTestRun(undefined, {
83
+ test_id: testId,
81
84
  title,
82
85
  suite_title,
83
86
  files: [file],
@@ -43,9 +43,10 @@ class WebdriverReporter extends WDIOReporter {
43
43
  .filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
44
44
  .map(el => Buffer.from(el.result.value, 'base64'));
45
45
 
46
- await this.client.addTestRun(testId, state, {
46
+ await this.client.addTestRun(state, {
47
47
  error,
48
48
  title,
49
+ test_id: testId,
49
50
  time: duration,
50
51
  filesBuffers: screenshotsBuffers,
51
52
  });
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  const program = require("commander");
4
3
  const chalk = require("chalk");
5
4
  const glob = require('glob');
@@ -3,7 +3,7 @@ const { spawn } = require('child_process');
3
3
  const program = require('commander');
4
4
  const chalk = require('chalk');
5
5
  const TestomatClient = require('../client');
6
- const { APP_PREFIX, FINISHED } = require('../constants');
6
+ const { APP_PREFIX, STATUS } = require('../constants');
7
7
  const { version } = require('../../package.json');
8
8
 
9
9
  console.log(chalk.cyan.bold(` 🤩 Testomat.io Reporter v${version}`));
@@ -42,7 +42,7 @@ program
42
42
 
43
43
  const client = new TestomatClient({ apiKey });
44
44
 
45
- client.updateRunStatus(FINISHED, true).then(() => {
45
+ client.updateRunStatus(STATUS.FINISHED, true).then(() => {
46
46
  console.log(chalk.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
47
47
  process.exit(0);
48
48
  });
package/lib/client.js CHANGED
@@ -3,25 +3,26 @@ const createCallsiteRecord = require('callsite-record');
3
3
  const { sep, join } = require('path');
4
4
  const fs = require('fs');
5
5
  const chalk = require('chalk');
6
+ const { randomUUID } = require('crypto');
6
7
  const upload = require('./fileUploader');
7
- const { PASSED, FAILED, FINISHED, APP_PREFIX } = require('./constants');
8
+ const { APP_PREFIX } = require('./constants');
8
9
  const pipesFactory = require('./pipe');
9
10
 
10
- const { TESTOMATIO_ENV } = process.env;
11
+ /**
12
+ * @typedef {import('../types').TestData} TestData
13
+ * @typedef {import('../types').RunStatus} RunStatus
14
+ */
11
15
 
12
- class TestomatClient {
16
+ class Client {
13
17
  /**
14
18
  * Create a Testomat client instance
15
19
  *
16
20
  * @param {*} params
17
21
  */
18
22
  constructor(params = {}) {
19
- this.title = params.title || process.env.TESTOMATIO_TITLE;
20
- this.createNewTests = params.createNewTests ?? !!process.env.TESTOMATIO_CREATE;
21
- this.proceed = process.env.TESTOMATIO_PROCEED;
22
- this.env = TESTOMATIO_ENV;
23
23
  this.parallel = params.parallel;
24
24
  const store = {};
25
+ this.uuid = randomUUID();
25
26
  this.pipes = pipesFactory(params, store);
26
27
  this.queue = Promise.resolve();
27
28
  this.totalUploaded = 0;
@@ -32,11 +33,11 @@ class TestomatClient {
32
33
  /**
33
34
  * Used to create a new Test run
34
35
  *
35
- * @returns {Promise} - resolves to Run id which should be used to update / add test
36
+ * @returns {Promise<void>} - resolves to Run id which should be used to update / add test
36
37
  */
37
38
  createRun() {
38
39
  // all pipes disabled, skipping
39
- if (!this.pipes.filter(p => p.isEnabled).length) return;
40
+ if (!this.pipes.filter(p => p.isEnabled).length) return Promise.resolve();
40
41
 
41
42
  const runParams = {
42
43
  title: this.title,
@@ -48,22 +49,31 @@ class TestomatClient {
48
49
 
49
50
  this.queue = this.queue
50
51
  .then(() => Promise.all(this.pipes.map(p => p.createRun(runParams))))
51
- .catch(err => console.log(APP_PREFIX, err));
52
+ .catch(err => console.log(APP_PREFIX, err))
53
+ .then(() => undefined); // fixes return type
52
54
  debug('Run', this.queue);
53
55
  return this.queue;
54
56
  }
55
57
 
56
58
  /**
57
- * Used to add a new test to Run instance
58
- *
59
- * @returns {Promise}
59
+ * Updates test status and its data
60
+ *
61
+ * @param {string|undefined} status
62
+ * @param {TestData} [testData]
63
+ * @param {string[]} [storeArtifacts]
64
+ * @returns {Promise<void>}
60
65
  */
61
- async addTestRun(testId, status, testData = {}, storeArtifacts = []) {
66
+ async addTestRun(status, testData, storeArtifacts = []) {
62
67
  // all pipes disabled, skipping
63
68
  if (!this.pipes.filter(p => p.isEnabled).length) return;
64
69
 
70
+ if (!testData) testData = {
71
+ title: 'Unknown test',
72
+ suite_title: 'Unknown suite',
73
+ }
74
+
65
75
  const {
66
- error = '',
76
+ error = null,
67
77
  time = '',
68
78
  example = null,
69
79
  files = [],
@@ -79,20 +89,18 @@ class TestomatClient {
79
89
 
80
90
  const uploadedFiles = [];
81
91
 
82
- if (testId) testData.test_id = testId;
83
-
84
92
  let stack = '';
85
93
 
86
94
  if (error) {
87
- stack = this.formatError(error);
88
- message = error.message;
95
+ stack = this.formatError(error) || '';
96
+ message = error?.message;
89
97
  }
90
98
  if (steps) {
91
99
  stack = this.formatSteps(stack, steps);
92
100
  }
93
101
 
94
102
  if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
95
- debug("CLIENT storeArtefact", storeArtifacts);
103
+ debug("CLIENT storeArtifact", storeArtifacts);
96
104
  files.push(...storeArtifacts);
97
105
  }
98
106
 
@@ -103,12 +111,12 @@ class TestomatClient {
103
111
  }
104
112
 
105
113
  for (const file of files) {
106
- uploadedFiles.push(upload.uploadFileByPath(file, this.runId));
114
+ uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
107
115
  }
108
116
 
109
117
  for (const [idx, buffer] of filesBuffers.entries()) {
110
118
  const fileName = `${idx + 1}-${title.replace(/\s+/g, '-')}`;
111
- uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.runId));
119
+ uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
112
120
  }
113
121
 
114
122
  const artifacts = await Promise.all(uploadedFiles);
@@ -135,25 +143,23 @@ class TestomatClient {
135
143
 
136
144
  this.queue = this.queue
137
145
  .then(() => Promise.all(this.pipes.map(p => p.addTest(data))))
138
- .catch(err => console.log(APP_PREFIX, err));
146
+ .catch(err => console.log(APP_PREFIX, err))
147
+ .then(() => undefined);
139
148
  return this.queue;
140
149
  }
141
150
 
142
151
  /**
143
- * Update run status
144
152
  *
145
- * @returns {Promise}
153
+ * Updates the status of the current test run and finishes the run.
154
+ * @param {RunStatus} status - The status of the current test run. Must be one of "passed", "failed", or "finished"
155
+ * @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
156
+ * @returns {Promise<void>} - A Promise that resolves when finishes the run.
146
157
  */
147
- updateRunStatus(status, isParallel) {
158
+ updateRunStatus(status, isParallel = false) {
148
159
  // all pipes disabled, skipping
149
- if (!this.pipes.filter(p => p.isEnabled).length) return;
160
+ if (!this.pipes.filter(p => p.isEnabled).length) return Promise.resolve();
150
161
 
151
- let statusEvent;
152
- if (status === FINISHED) statusEvent = 'finish';
153
- if (status === PASSED) statusEvent = 'pass';
154
- if (status === FAILED) statusEvent = 'fail';
155
- if (isParallel) statusEvent += '_parallel';
156
- const runParams = { status, statusEvent };
162
+ const runParams = { status, parallel: isParallel };
157
163
 
158
164
  this.queue = this.queue
159
165
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
@@ -211,4 +217,4 @@ class TestomatClient {
211
217
  }
212
218
  }
213
219
 
214
- module.exports = TestomatClient;
220
+ module.exports = Client;
package/lib/constants.js CHANGED
@@ -11,12 +11,16 @@ const CSV_HEADERS = [
11
11
  { id: 'stack', title: 'Stack' },
12
12
  ];
13
13
 
14
- module.exports = Object.freeze({
14
+ const STATUS = {
15
15
  PASSED: 'passed',
16
16
  FAILED: 'failed',
17
17
  SKIPPED: 'skipped',
18
18
  FINISHED: 'finished',
19
+ };
20
+
21
+ module.exports = {
19
22
  APP_PREFIX,
23
+ TESTOMAT_ARTIFACT_SUFFIX,
20
24
  CSV_HEADERS,
21
- TESTOMAT_ARTIFACT_SUFFIX
22
- });
25
+ STATUS,
26
+ }
@@ -1,6 +1,6 @@
1
1
  const debug = require('debug')('@testomatio/reporter:file-uploader');
2
2
  const { S3 } = require('@aws-sdk/client-s3');
3
- const { Upload } = require("@aws-sdk/lib-storage");
3
+ const { Upload } = require('@aws-sdk/lib-storage');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const chalk = require('chalk');
@@ -14,5 +14,4 @@ class CSharpAdapter extends Adapter {
14
14
  }
15
15
  }
16
16
 
17
-
18
17
  module.exports = CSharpAdapter;
@@ -5,8 +5,7 @@ const PythonAdapter = require('./python');
5
5
  const RubyAdapter = require('./ruby');
6
6
  const CSharpAdapter = require('./csharp');
7
7
 
8
-
9
- module.exports = function (lang, opts) {
8
+ function AdapterFactory(lang, opts) {
10
9
  if (!lang) return new Adapter(opts);
11
10
 
12
11
  if (lang === 'java') {
@@ -25,3 +24,5 @@ module.exports = function (lang, opts) {
25
24
  return new CSharpAdapter(opts);
26
25
  }
27
26
  }
27
+
28
+ module.exports = AdapterFactory;
package/lib/pipe/csv.js CHANGED
@@ -7,9 +7,16 @@ const merge = require('lodash.merge');
7
7
  const { isSameTest, getCurrentDateTime } = require('../util');
8
8
  const { CSV_HEADERS } = require('../constants');
9
9
 
10
+ /**
11
+ * @typedef {import('../../types').Pipe} Pipe
12
+ * @typedef {import('../../types').TestData} TestData
13
+ * @class CsvPipe
14
+ * @implements {Pipe}
15
+ */
10
16
  class CsvPipe {
11
- constructor(params, store = {}) {
12
- this.store = store;
17
+
18
+ constructor(params, store) {
19
+ this.store = store || {};
13
20
  this.title = params.title || process.env.TESTOMATIO_TITLE;
14
21
  this.isEnabled = true;
15
22
  this.results = [];
@@ -59,7 +66,12 @@ class CsvPipe {
59
66
  // First, we check whether the export directory exists: if yes - OK, no - create it.
60
67
  this.checkExportDir();
61
68
 
62
- console.log(chalk.yellow(`The test results will be added to the csv. It will take some time...`));
69
+ if (!this.outputFile) {
70
+ console.log(this, chalk.yellow(`CSV file is not set, ignoring`));
71
+ return;
72
+ }
73
+
74
+ console.log(this, chalk.yellow(`The test results will be added to the csv. It will take some time...`));
63
75
  // Create csv writer object
64
76
  const writer = csvWriter.createObjectCsvWriter({
65
77
  path: this.outputFile,
@@ -68,7 +80,7 @@ class CsvPipe {
68
80
  // Save csv file based on the current data
69
81
  try {
70
82
  await writer.writeRecords(data);
71
- console.log(chalk.green(`Recording completed! You can check the result in file = ${this.outputFile}`));
83
+ console.log(this, chalk.green(`Recording completed! You can check the result in file = ${this.outputFile}`));
72
84
  } catch (e) {
73
85
  console.log('Unknown error: ', e);
74
86
  }
@@ -100,8 +112,8 @@ class CsvPipe {
100
112
  }
101
113
 
102
114
  /**
103
- * Save short tests data to the csv file.
104
- * @param {Object} runParams - run params.
115
+ * @param {{ tests?: TestData[] }} runParams
116
+ * @returns {Promise<void>}
105
117
  */
106
118
  async finishRun(runParams) {
107
119
  if (!this.isEnabled) return;
@@ -7,6 +7,12 @@ const { Octokit } = require('@octokit/rest');
7
7
  const { APP_PREFIX } = require('../constants');
8
8
  const { ansiRegExp, isSameTest } = require('../util');
9
9
 
10
+ /**
11
+ * @typedef {import('../../types').Pipe} Pipe
12
+ * @typedef {import('../../types').TestData} TestData
13
+ * @class GitHubPipe
14
+ * @implements {Pipe}
15
+ */
10
16
  class GitHubPipe {
11
17
  constructor(params, store = {}) {
12
18
  this.isEnabled = false;
@@ -23,7 +29,8 @@ class GitHubPipe {
23
29
  this.isEnabled = true;
24
30
  const matchedIssue = this.ref.match(/refs\/pull\/(\d+)\/merge/);
25
31
  if (!matchedIssue) return;
26
- this.issue = matchedIssue[1];
32
+ this.issue = parseInt(matchedIssue[1], 10);
33
+
27
34
  this.start = new Date();
28
35
 
29
36
  debug('GitHub Pipe: Enabled');
@@ -31,8 +38,6 @@ class GitHubPipe {
31
38
 
32
39
  async createRun() {}
33
40
 
34
- updateRun() {}
35
-
36
41
  addTest(test) {
37
42
  debug('Adding test:', test);
38
43
  if (!this.isEnabled) return;
@@ -49,6 +54,7 @@ class GitHubPipe {
49
54
 
50
55
  async finishRun(runParams) {
51
56
  if (!this.isEnabled) return;
57
+ if (!this.issue) return;
52
58
 
53
59
  if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
54
60
 
@@ -56,7 +62,7 @@ class GitHubPipe {
56
62
  auth: this.token,
57
63
  });
58
64
 
59
- const [owner, repo] = this.repo.split('/');
65
+ const [owner, repo] = (this.repo || '').split('/');
60
66
  if (!(owner || repo)) return;
61
67
 
62
68
  // ... create a comment on GitHub
@@ -148,6 +154,7 @@ class GitHubPipe {
148
154
  .join('\n');
149
155
  body += '\n</details>';
150
156
  }
157
+
151
158
 
152
159
  await deletePreviousReport(this.octokit, owner, repo, this.issue, this.hiddenCommentData);
153
160
 
@@ -1,5 +1,5 @@
1
1
  const debug = require('debug')('@testomatio/reporter:pipe:gitlab');
2
- const axios = require('axios');
2
+ const { default: axios } = require('axios');
3
3
  const chalk = require('chalk');
4
4
  const humanizeDuration = require('humanize-duration');
5
5
  const merge = require('lodash.merge');
@@ -10,6 +10,11 @@ const { ansiRegExp, isSameTest } = require('../util');
10
10
  //! GITLAB_PAT environment variable is required for this functionality to work
11
11
  //! and your pipeline trigger should be merge_request
12
12
 
13
+ /**
14
+ * @class GitLabPipe
15
+ * @typedef {import('../../types').Pipe} Pipe
16
+ * @typedef {import('../../types').TestData} TestData
17
+ */
13
18
  class GitLabPipe {
14
19
  constructor(params, store = {}) {
15
20
  this.isEnabled = false;
@@ -19,7 +24,6 @@ class GitLabPipe {
19
24
  // GitLab PAT looks like glpat-nKGdja3jsG4850sGksh7
20
25
  this.token = params.GITLAB_PAT || this.ENV.GITLAB_PAT;
21
26
  this.hiddenCommentData = `<!--- testomat.io report ${process.env.CI_JOB_NAME || ''} -->`;
22
- this.axios = axios.create();
23
27
 
24
28
  debug(
25
29
  chalk.yellow('GitLab Pipe:'),
@@ -142,13 +146,13 @@ class GitLabPipe {
142
146
  const commentsRequestURL = `https://gitlab.com/api/v4/projects/${this.ENV.CI_PROJECT_ID}/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}/notes`;
143
147
 
144
148
  // delete previous report
145
- await deletePreviousReport(this.axios, commentsRequestURL, this.hiddenCommentData, this.token);
149
+ await deletePreviousReport(axios, commentsRequestURL, this.hiddenCommentData, this.token);
146
150
 
147
151
  // add current report
148
152
  debug(`Adding comment via url: ${commentsRequestURL}`);
149
153
 
150
154
  try {
151
- const addCommentResponse = await this.axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
155
+ const addCommentResponse = await axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
152
156
 
153
157
  const commentID = addCommentResponse.data.id;
154
158
  // eslint-disable-next-line max-len
package/lib/pipe/index.js CHANGED
@@ -7,7 +7,7 @@ const GitHubPipe = require('./github');
7
7
  const GitLabPipe = require('./gitlab');
8
8
  const CsvPipe = require('./csv');
9
9
 
10
- module.exports = function (params, opts) {
10
+ function PipeFactory(params, opts) {
11
11
  const extraPipes = [];
12
12
 
13
13
  // Add extra pipes into package.json file:
@@ -17,7 +17,7 @@ module.exports = function (params, opts) {
17
17
 
18
18
  const packageJsonFile = path.join(process.cwd(), 'package.json');
19
19
  if (fs.existsSync(packageJsonFile)) {
20
- const packageJson = fs.readFileSync(packageJsonFile);
20
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonFile).toString());
21
21
  const pipeDefs = packageJson?.testomatio?.pipes || [];
22
22
 
23
23
  for (const pipeDef of pipeDefs) {
@@ -58,4 +58,6 @@ module.exports = function (params, opts) {
58
58
  );
59
59
 
60
60
  return pipes;
61
- };
61
+ }
62
+
63
+ module.exports = PipeFactory;
@@ -2,18 +2,22 @@ const debug = require('debug')('@testomatio/reporter:pipe:testomatio');
2
2
  const chalk = require('chalk');
3
3
  const axios = require('axios');
4
4
  const JsonCycle = require('json-cycle');
5
-
6
- const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_RUN } = process.env;
7
- const { APP_PREFIX } = require('../constants');
5
+ const { APP_PREFIX, STATUS } = require('../constants');
8
6
  const { isValidUrl } = require('../util');
9
7
 
10
-
8
+ const { TESTOMATIO_RUN } = process.env;
11
9
  if (TESTOMATIO_RUN) {
12
10
  process.env.runId = TESTOMATIO_RUN;
13
11
  }
14
12
 
13
+ /**
14
+ * @typedef {import('../../types').Pipe} Pipe
15
+ * @typedef {import('../../types').TestData} TestData
16
+ * @class TestomatioPipe
17
+ * @implements {Pipe}
18
+ */
15
19
  class TestomatioPipe {
16
- constructor(params, store = {}) {
20
+ constructor(params, store) {
17
21
  this.isEnabled = false;
18
22
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
19
23
  this.apiKey = params.apiKey || process.env.TESTOMATIO;
@@ -22,10 +26,13 @@ class TestomatioPipe {
22
26
  return;
23
27
  }
24
28
  debug('Testomatio Pipe: Enabled');
25
- this.store = store;
29
+ this.store = store || {};
26
30
  this.title = params.title || process.env.TESTOMATIO_TITLE;
31
+ this.groupTitle = params.groupTitle || process.env.TESTOMATIO_RUNGROUP_TITLE;
32
+ this.env = process.env.TESTOMATIO_ENV;
27
33
  this.axios = axios.create();
28
34
  this.isEnabled = true;
35
+ // do not finish this run (for parallel testing)
29
36
  this.proceed = process.env.TESTOMATIO_PROCEED;
30
37
  this.runId = params.runId || process.env.runId;
31
38
  this.createNewTests = !!process.env.TESTOMATIO_CREATE;
@@ -36,11 +43,20 @@ class TestomatioPipe {
36
43
  }
37
44
  }
38
45
 
39
- async createRun(runParams) {
46
+ /**
47
+ * @returns Promise<void>
48
+ */
49
+ async createRun() {
40
50
  if (!this.isEnabled) return;
41
51
 
42
- runParams.api_key = this.apiKey.trim();
43
- runParams.group_title = TESTOMATIO_RUNGROUP_TITLE;
52
+ const runParams = Object.fromEntries(
53
+ Object.entries({
54
+ api_key: this.apiKey.trim(),
55
+ group_title: this.groupTitle,
56
+ env: this.env,
57
+ title: this.title,
58
+ }).filter(([, value]) => !!value)
59
+ );
44
60
 
45
61
  if (this.runId) {
46
62
  return this.axios.put(`${this.url.trim()}/api/reporter/${this.runId}`, runParams);
@@ -65,6 +81,11 @@ class TestomatioPipe {
65
81
  }
66
82
  }
67
83
 
84
+ /**
85
+ *
86
+ * @param testData data
87
+ * @returns
88
+ */
68
89
  addTest(data) {
69
90
  if (!this.isEnabled) return;
70
91
  if (!this.runId) return;
@@ -98,14 +119,27 @@ class TestomatioPipe {
98
119
  });
99
120
  }
100
121
 
122
+ /**
123
+ * @param {import('../../types').RunData} params
124
+ * @returns
125
+ */
101
126
  async finishRun(params) {
102
127
  if (!this.isEnabled) return;
128
+
129
+ const { status, parallel } = params;
130
+
131
+ let status_event;
132
+
133
+ if (status === STATUS.FINISHED) status_event = 'finish';
134
+ if (status === STATUS.PASSED) status_event = 'pass';
135
+ if (status === STATUS.FAILED) status_event = 'fail';
136
+ if (parallel) status_event += '_parallel';
137
+
103
138
  try {
104
139
  if (this.runId && !this.proceed) {
105
140
  await this.axios.put(`${this.url}/api/reporter/${this.runId}`, {
106
141
  api_key: this.apiKey,
107
- status_event: params.statusEvent,
108
- status: params.status,
142
+ status_event,
109
143
  tests: params.tests,
110
144
  });
111
145
  if (this.runUrl) {