@testomatio/reporter 0.8.0-beta.20 → 0.8.0-beta.30

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,39 +1,37 @@
1
1
  const path = require('path');
2
2
  const chalk = require('chalk');
3
- const humanizeDuration = require("humanize-duration");
3
+ const humanizeDuration = require('humanize-duration');
4
4
  const merge = require('lodash.merge');
5
- const { Octokit } = require("@octokit/rest");
5
+ const { Octokit } = require('@octokit/rest');
6
6
  const { APP_PREFIX } = require('../constants');
7
7
  const { ansiRegExp, isSameTest } = require('../util');
8
8
 
9
-
10
9
  class GitHubPipe {
11
-
12
- isEnabled = false;
13
-
14
10
  constructor(params, store = {}) {
11
+ this.isEnabled = false;
15
12
  this.store = store;
16
- this.tests = []
13
+ this.tests = [];
17
14
  this.token = params.GH_PAT || process.env.GH_PAT;
18
- this.ref = process.env.GITHUB_REF
19
- this.repo = process.env.GITHUB_REPOSITORY
15
+ this.ref = process.env.GITHUB_REF;
16
+ this.repo = process.env.GITHUB_REPOSITORY;
17
+ this.hiddenCommentData = `<!--- testomat.io report ${process.env.GITHUB_WORKFLOW || ''} -->`;
20
18
 
21
19
  if (process.env.DEBUG) {
22
- console.log(APP_PREFIX, 'GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', this.ref, this.repo);
20
+ console.log(APP_PREFIX, 'GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', this.ref, this.repo);
23
21
  }
24
22
 
25
23
  if (!this.token || !this.ref || !this.repo) return;
26
24
  this.isEnabled = true;
27
25
  const matchedIssue = this.ref.match(/refs\/pull\/(\d+)\/merge/);
28
26
  if (!matchedIssue) return;
29
- this.issue = matchedIssue[1]
27
+ this.issue = matchedIssue[1];
30
28
  this.start = new Date();
31
29
 
32
30
  if (process.env.DEBUG) {
33
- console.log(APP_PREFIX, 'GitHub Pipe: Enabled');
31
+ console.log(APP_PREFIX, 'GitHub Pipe: Enabled');
34
32
  }
35
33
  }
36
-
34
+
37
35
  async createRun() {}
38
36
 
39
37
  updateRun() {}
@@ -41,21 +39,20 @@ class GitHubPipe {
41
39
  addTest(test) {
42
40
  if (!this.isEnabled) return;
43
41
 
44
- const index = this.tests.findIndex(t => isSameTest(t, test))
42
+ const index = this.tests.findIndex(t => isSameTest(t, test));
45
43
  // update if they were already added
46
44
  if (index >= 0) {
47
45
  this.tests[index] = merge(this.tests[index], test);
48
46
  return;
49
47
  }
50
48
 
51
- this.tests.push(test)
49
+ this.tests.push(test);
52
50
  }
53
51
 
54
52
  async finishRun(runParams) {
55
53
  if (!this.isEnabled) return;
56
54
 
57
55
  if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
58
-
59
56
 
60
57
  this.octokit = new Octokit({
61
58
  auth: this.token,
@@ -69,14 +66,17 @@ class GitHubPipe {
69
66
  const failedCount = this.tests.filter(t => t.status === 'failed').length;
70
67
  const skippedCount = this.tests.filter(t => t.status === 'skipped').length;
71
68
 
72
- let summary = `
69
+ let summary = `${this.hiddenCommentData}
73
70
 
74
- | [![Testomat.io Report](https://avatars.githubusercontent.com/u/59105116?s=36&v=4)](https://testomat.io) | ${statusEmoji(runParams.status)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
71
+ | [![Testomat.io Report](https://avatars.githubusercontent.com/u/59105116?s=36&v=4)](https://testomat.io) | ${
72
+ statusEmoji(runParams.status)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
75
73
  | --- | --- |
76
74
  | Tests | ✔️ **${this.tests.length}** tests run |
77
- | Summary | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji('passed')} **${passedCount}** passed; **${statusEmoji('skipped')}** ${skippedCount} skipped |
75
+ | Summary | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji(
76
+ 'passed',
77
+ )} **${passedCount}** passed; **${statusEmoji('skipped')}** ${skippedCount} skipped |
78
78
  | Duration | 🕐 **${humanizeDuration(parseFloat(this.tests.reduce((a, t) => a + (t.run_time || 0), 0)))}** |
79
- `
79
+ `;
80
80
  if (this.store.runUrl) {
81
81
  summary += `| Testomat.io Report | 📊 [Run #${this.store.runId}](${this.store.runUrl}) | `;
82
82
  }
@@ -93,46 +93,67 @@ class GitHubPipe {
93
93
  summary += `| Run Attempt | 🌒 \`${process.env.GITHUB_RUN_ATTEMPT}\` | `;
94
94
  }
95
95
  if (process.env.GITHUB_RUN_ID) {
96
- summary += `| Build Log | ✒️ ${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${this.repo}/actions/runs/${process.env.GITHUB_RUN_ID} | `;
96
+ summary += `| Build Log | ✒️ ${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${
97
+ this.repo
98
+ }/actions/runs/${process.env.GITHUB_RUN_ID} | `;
97
99
  }
98
100
 
101
+ const failures = this.tests
102
+ .filter(t => t.status === 'failed')
103
+ .slice(0, 20)
104
+ .map(t => {
105
+ let text = `#### ${statusEmoji('failed')} ${fullName(t)} `;
106
+ text += '\n\n';
107
+ if (t.message)
108
+ text += `> ${t.message
109
+ .replace(/[^\x20-\x7E]/g, '')
110
+ .replace(ansiRegExp(), '')
111
+ .trim()}\n`;
112
+ if (t.stack) text += `\`\`\`diff\n${t.stack.replace(ansiRegExp(), '').trim()}\n\`\`\`\n`;
113
+
114
+ if (t.artifacts && t.artifacts.length && !process.env.TESTOMATIO_PRIVATE_ARTIFACTS) {
115
+ t.artifacts
116
+ .filter(f => !!f)
117
+ .filter(f => f.endsWith('.png'))
118
+ .forEach(f => {
119
+ if (f.endsWith('.png')) {
120
+ text += `![](${f})\n`;
121
+ return text;
122
+ }
123
+ text += `[📄 ${path.basename(f)}](${f})\n`;
124
+ return text;
125
+ });
126
+ }
127
+
128
+ text += '\n---\n';
129
+
130
+ return text;
131
+ });
99
132
 
100
- const failures = this.tests.filter(t => t.status === 'failed').slice(0, 20).map(t => {
101
- let text = `#### ${statusEmoji('failed')} ${fullName(t)} `;
102
- text += "\n\n"
103
- if (t.message) text += "> " + t.message.replace(/[^\x20-\x7E]/g, '').replace(ansiRegExp(), '').trim() + "\n"
104
- if (t.stack) text += "```diff\n" + t.stack.replace(ansiRegExp(), '').trim() + "\n```\n";
105
-
106
- if (t.artifacts && t.artifacts.length && !process.env.TESTOMATIO_PRIVATE_ARTIFACTS) {
107
- t.artifacts.filter(f => !!f).filter(f => f.endsWith('.png')).forEach(f => {
108
- if (f.endsWith('.png')) return text+= `![](${f})\n`
109
- return text+= `[📄 ${path.basename(f)}](${f})\n`
110
- });
111
- }
112
-
113
- text += "\n---\n"
114
-
115
- return text;
116
- })
117
-
118
133
  let body = summary;
119
134
 
120
135
  if (failures.length) {
121
136
  body += `\n<details>\n<summary><h3>🟥 Failures (${failures.length})</h4></summary>\n\n${failures.join('\n')}\n`;
122
137
  if (failures.length > 20) {
123
- body += "\n> Notice\n> Only first 20 failures shown*"
138
+ body += '\n> Notice\n> Only first 20 failures shown*';
124
139
  }
125
- body += "\n\n</details>";
140
+ body += '\n\n</details>';
126
141
  }
127
142
 
128
143
  if (this.tests.length > 0) {
129
- body += "\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n"
130
- body += this.tests.sort((a, b) => b?.run_time - a?.run_time).slice(0, 5).map(t => {
131
- return `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`
132
- }).join('\n')
133
- body += "\n</details>"
144
+ body += '\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n';
145
+ body += this.tests
146
+ // eslint-disable-next-line no-unsafe-optional-chaining
147
+ .sort((a, b) => b?.run_time - a?.run_time)
148
+ .slice(0, 5)
149
+ .map(t => `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`)
150
+ .join('\n');
151
+ body += '\n</details>';
134
152
  }
135
153
 
154
+ await deletePreviousReport(this.octokit, owner, repo, this.issue, this.hiddenCommentData);
155
+
156
+ // add report as comment
136
157
  try {
137
158
  const resp = await this.octokit.rest.issues.createComment({
138
159
  owner,
@@ -140,26 +161,18 @@ class GitHubPipe {
140
161
  issue_number: this.issue,
141
162
  body,
142
163
  });
143
-
164
+
144
165
  const url = resp.data?.html_url;
145
166
  this.store.githubUrl = url;
146
-
147
- console.log(
148
- APP_PREFIX,
149
- chalk.yellow('GitHub'),
150
- `Report created: ${chalk.magenta(url)}`,
151
- );
167
+
168
+ console.log(APP_PREFIX, chalk.yellow('GitHub'), `Report created: ${chalk.magenta(url)}`);
152
169
  } catch (err) {
153
- console.log(
154
- APP_PREFIX,
155
- chalk.yellow('GitHub'),
156
- `Couldn't create GitHub report ${err}`,
157
- );
170
+ console.log(APP_PREFIX, chalk.yellow('GitHub'), `Couldn't create GitHub report ${err}`);
158
171
  }
159
172
  }
160
173
 
161
174
  toString() {
162
- return 'GitHub Reporter'
175
+ return 'GitHub Reporter';
163
176
  }
164
177
  }
165
178
 
@@ -167,15 +180,56 @@ function statusEmoji(status) {
167
180
  if (status === 'passed') return '🟢';
168
181
  if (status === 'failed') return '🔴';
169
182
  if (status === 'skipped') return '🟡';
170
- return ''
183
+ return '';
171
184
  }
172
185
 
173
186
  function fullName(t) {
174
187
  let line = '';
175
- if (t.suite_title) line = `${t.suite_title}: `;
176
- line += `**${t.title}**`
188
+ if (t.suite_title) line = `${t.suite_title}: `;
189
+ line += `**${t.title}**`;
177
190
  if (t.example) line += ` \`[${Object.values(t.example)}]\``;
178
191
  return line;
179
192
  }
180
193
 
181
- module.exports = GitHubPipe;
194
+ async function deletePreviousReport(octokit, owner, repo, issue, hiddenCommentData) {
195
+ if (process.env.GITHUB_KEEP_OUTDATED_REPORTS) return;
196
+
197
+ // get comments
198
+ let comments = [];
199
+ try {
200
+ const response = await octokit.rest.issues.listComments({
201
+ owner,
202
+ repo,
203
+ issue_number: issue,
204
+ });
205
+ comments = response.data;
206
+ } catch (e) {
207
+ console.error('Error while attempt to retrieve comments on GitHub Pull Request:\n', e);
208
+ }
209
+
210
+ if (!comments.length) return;
211
+
212
+ for (const comment of comments) {
213
+ // if comment was left by the same workflow
214
+ if (comment.body.includes(hiddenCommentData)) {
215
+ try {
216
+ // delete previous comment
217
+ await octokit.rest.issues.deleteComment({
218
+ owner,
219
+ repo,
220
+ issue_number: issue,
221
+ comment_id: comment.id,
222
+ });
223
+ } catch (e) {
224
+ console.error(`Can't delete previously added comment with testomat.io report. Ignore.`);
225
+ }
226
+
227
+ // pass next env var if need to clear all previous reports;
228
+ // only the last one is removed by default
229
+ if (!process.env.GITHUB_REMOVE_ALL_OUTDATED_REPORTS) break;
230
+ // TODO: in case of many reports should implement pagination
231
+ }
232
+ }
233
+ }
234
+
235
+ module.exports = GitHubPipe;
@@ -1,22 +1,24 @@
1
- const { ansiRegExp, isSameTest } = require('../util');
2
- const { APP_PREFIX } = require('../constants');
1
+ const axios = require('axios');
3
2
  const chalk = require('chalk');
4
- const got = require('got');
5
3
  const humanizeDuration = require('humanize-duration');
6
4
  const merge = require('lodash.merge');
7
5
  const path = require('path');
6
+ const { APP_PREFIX } = require('../constants');
7
+ const { ansiRegExp, isSameTest } = require('../util');
8
8
 
9
- //! GITLAB_PAT environment variable is required for this functionality to work and your pipeline trigger should be merge_request
9
+ //! GITLAB_PAT environment variable is required for this functionality to work
10
+ //! and your pipeline trigger should be merge_request
10
11
 
11
12
  class GitLabPipe {
12
- isEnabled = false;
13
-
14
13
  constructor(params, store = {}) {
14
+ this.isEnabled = false;
15
15
  this.ENV = process.env;
16
16
  this.store = store;
17
17
  this.tests = [];
18
18
  // GitLab PAT looks like glpat-nKGdja3jsG4850sGksh7
19
19
  this.token = params.GITLAB_PAT || this.ENV.GITLAB_PAT;
20
+ this.hiddenCommentData = `<!--- testomat.io report ${process.env.CI_JOB_NAME || ''} -->`;
21
+ this.axios = axios.create();
20
22
 
21
23
  if (this.ENV.DEBUG) {
22
24
  console.log(
@@ -28,9 +30,7 @@ class GitLabPipe {
28
30
  }
29
31
 
30
32
  if (!this.ENV.CI_PROJECT_ID || !this.ENV.CI_MERGE_REQUEST_IID) {
31
- console.warn(
32
- `CI pipeline should be run in Merge Request to have ability to add the report comment.`,
33
- );
33
+ // console.warn(`CI pipeline should be run in Merge Request to have ability to add the report comment.`);
34
34
  return;
35
35
  }
36
36
 
@@ -72,10 +72,10 @@ class GitLabPipe {
72
72
  const skippedCount = this.tests.filter(t => t.status === 'skipped').length;
73
73
 
74
74
  // constructing the table
75
- let summary = `
75
+ let summary = `${this.hiddenCommentData}
76
76
 
77
- | [![Testomat.io Report](https://avatars.githubusercontent.com/u/59105116?s=36&v=4)](https://testomat.io) | ${statusEmoji(
78
- runParams.status,
77
+ | [![Testomat.io Report](https://avatars.githubusercontent.com/u/59105116?s=36&v=4)](https://testomat.io) | ${
78
+ statusEmoji(runParams.status,
79
79
  )} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
80
80
  | --- | --- |
81
81
  | Tests | ✔️ **${this.tests.length}** tests run |
@@ -86,7 +86,8 @@ class GitLabPipe {
86
86
  `;
87
87
 
88
88
  if (this.ENV.CI_JOB_NAME && this.ENV.CI_JOB_ID) {
89
- summary += `| Job | 👷 [${this.ENV.CI_JOB_ID}](${this.ENV.CI_JOB_URL})<br>Name: **${this.ENV.CI_JOB_NAME}**<br>Stage: **${this.ENV.CI_JOB_STAGE}** | `;
89
+ summary += `| Job | 👷 [${this.ENV.CI_JOB_ID}](${this.ENV.CI_JOB_URL})<br>Name: **${
90
+ this.ENV.CI_JOB_NAME}**<br>Stage: **${this.ENV.CI_JOB_STAGE}** | `;
90
91
  }
91
92
 
92
93
  const failures = this.tests
@@ -96,22 +97,23 @@ class GitLabPipe {
96
97
  let text = `#### ${statusEmoji('failed')} ${fullName(t)} `;
97
98
  text += '\n\n';
98
99
  if (t.message)
99
- text +=
100
- '> ' +
101
- t.message
102
- .replace(/[^\x20-\x7E]/g, '')
103
- .replace(ansiRegExp(), '')
104
- .trim() +
105
- '\n';
106
- if (t.stack) text += '```diff\n' + t.stack.replace(ansiRegExp(), '').trim() + '\n```\n';
100
+ text += `> ${t.message
101
+ .replace(/[^\x20-\x7E]/g, '')
102
+ .replace(ansiRegExp(), '')
103
+ .trim()}\n`;
104
+ if (t.stack) text += `\`\`\`diff\n${t.stack.replace(ansiRegExp(), '').trim()}\n\`\`\`\n`;
107
105
 
108
106
  if (t.artifacts && t.artifacts.length && !this.ENV.TESTOMATIO_PRIVATE_ARTIFACTS) {
109
107
  t.artifacts
110
108
  .filter(f => !!f)
111
109
  .filter(f => f.endsWith('.png'))
112
110
  .forEach(f => {
113
- if (f.endsWith('.png')) return (text += `![](${f})\n`);
114
- return (text += `[📄 ${path.basename(f)}](${f})\n`);
111
+ if (f.endsWith('.png')) {
112
+ text += `![](${f})\n`;
113
+ return text;
114
+ }
115
+ text += `[📄 ${path.basename(f)}](${f})\n`;
116
+ return text;
115
117
  });
116
118
  }
117
119
 
@@ -133,26 +135,27 @@ class GitLabPipe {
133
135
  if (this.tests.length > 0) {
134
136
  body += '\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n';
135
137
  body += this.tests
138
+ // eslint-disable-next-line no-unsafe-optional-chaining
136
139
  .sort((a, b) => b?.run_time - a?.run_time)
137
140
  .slice(0, 5)
138
- .map(t => {
139
- return `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`;
140
- })
141
+ .map(t => `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`)
141
142
  .join('\n');
142
143
  body += '\n</details>';
143
144
  }
144
145
 
146
+ // eslint-disable-next-line max-len
147
+ const commentsRequestURL = `https://gitlab.com/api/v4/projects/${this.ENV.CI_PROJECT_ID}/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}/notes`;
148
+
149
+ // delete previous report
150
+ await deletePreviousReport(this.axios, commentsRequestURL, this.hiddenCommentData, this.token);
151
+
152
+ // add current report
153
+ console.info(chalk.grey(`Adding comment via url: ${commentsRequestURL}`));
145
154
  try {
146
- const addCommentRequestURL = `https://gitlab.com/api/v4/projects/${this.ENV.CI_PROJECT_ID}/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}/notes?access_token=${this.token}`;
147
- console.info(chalk.grey(`Adding comment via url: ${addCommentRequestURL}`));
148
- const options = {
149
- json: {
150
- body,
151
- },
152
- };
153
-
154
- const addCommentResponse = await got.post(addCommentRequestURL, options);
155
- const commentID = JSON.parse(addCommentResponse.body).id;
155
+ const addCommentResponse = await this.axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
156
+
157
+ const commentID = addCommentResponse.data.id;
158
+ // eslint-disable-next-line max-len
156
159
  const commentURL = `${this.ENV.CI_PROJECT_URL}/-/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}#note_${commentID}`;
157
160
 
158
161
  console.log(APP_PREFIX, chalk.yellow('GitLab'), `Report created: ${chalk.magenta(commentURL)}`);
@@ -161,8 +164,8 @@ class GitLabPipe {
161
164
  APP_PREFIX,
162
165
  chalk.yellow('GitLab'),
163
166
  `Couldn't create GitLab report\n${err}.
164
- Reqest url: ${addCommentRequestURL}
165
- Request data: ${JSON.stringify(options)}`,
167
+ Request url: ${commentsRequestURL}
168
+ Request data: ${body}`,
166
169
  );
167
170
  }
168
171
  }
@@ -189,4 +192,38 @@ function fullName(t) {
189
192
  return line;
190
193
  }
191
194
 
195
+ async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCommentData, token) {
196
+ if (process.env.GITLAB_KEEP_OUTDATED_REPORTS) return;
197
+
198
+ // get comments
199
+ let comments = [];
200
+
201
+ try {
202
+ const response = await axiosInstance.get(`${commentsRequestURL}?access_token=${token}`);
203
+ comments = response.data;
204
+ } catch (e) {
205
+ console.error('Error while attempt to retrieve comments on GitLab Merge Request:\n', e);
206
+ }
207
+
208
+ if (!comments.length) return;
209
+
210
+ for (const comment of comments) {
211
+ // if comment was left by the same workflow
212
+ if (comment.body.includes(hiddenCommentData)) {
213
+ try {
214
+ // delete previous comment
215
+ const deleteCommentURL = `${commentsRequestURL}/${comment.id}?access_token=${token}`;
216
+ await axiosInstance.delete(deleteCommentURL);
217
+ } catch (e) {
218
+ console.error(`Can't delete previously added comment with testomat.io report. Ignore.`);
219
+ }
220
+
221
+ // pass next env var if need to clear all previous reports;
222
+ // only the last one is removed by default
223
+ if (!process.env.GITLAB_REMOVE_ALL_OUTDATED_REPORTS) break;
224
+ // TODO: in case of many reports should implement pagination
225
+ }
226
+ }
227
+ }
228
+
192
229
  module.exports = GitLabPipe;
package/lib/pipe/index.js CHANGED
@@ -7,47 +7,55 @@ 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
+ module.exports = function (params, opts) {
11
11
  const extraPipes = [];
12
12
 
13
13
  // Add extra pipes into package.json file:
14
14
  // "testomatio": {
15
- // "pipes": ["my-module-pipe", "./local/js/file/pipe"]
15
+ // "pipes": ["my-module-pipe", "./local/js/file/pipe"]
16
16
  // }
17
17
 
18
18
  const packageJsonFile = path.join(process.cwd(), 'package.json');
19
19
  if (fs.existsSync(packageJsonFile)) {
20
- const package = fs.readFileSync(packageJsonFile);
21
- const pipeDefs = package?.testomatio?.pipes || [];
22
-
20
+ const packageJson = fs.readFileSync(packageJsonFile);
21
+ const pipeDefs = packageJson?.testomatio?.pipes || [];
22
+
23
23
  for (const pipeDef of pipeDefs) {
24
- let pipeClass;
24
+ let PipeClass;
25
25
  try {
26
- pipeClass = require(pipeDef);
26
+ PipeClass = require(pipeDef);
27
27
  } catch (err) {
28
28
  console.log(APP_PREFIX, `Can't load module Testomatio pipe module from ${pipeDef}`);
29
29
  continue;
30
30
  }
31
31
 
32
32
  try {
33
- extraPipes.push(new pipeClass(params, opts))
33
+ extraPipes.push(new PipeClass(params, opts));
34
34
  } catch (err) {
35
35
  console.log(APP_PREFIX, `Can't instantiate Testomatio for ${pipeDef}`, err);
36
36
  continue;
37
37
  }
38
38
  }
39
39
  }
40
-
41
40
 
42
41
  const pipes = [
43
42
  new TestomatioPipe(params, opts),
44
43
  new GitHubPipe(params, opts),
45
44
  new GitLabPipe(params, opts),
46
45
  new CsvPipe(params, opts),
47
- ...extraPipes
46
+ ...extraPipes,
48
47
  ];
49
48
 
50
- console.log(APP_PREFIX, chalk.cyan('Pipes:'), chalk.cyan(pipes.filter(p => p.isEnabled).map(p => p.toString()).join(', ') || "No pipes enabled"));
49
+ console.log(
50
+ APP_PREFIX,
51
+ chalk.cyan('Pipes:'),
52
+ chalk.cyan(
53
+ pipes
54
+ .filter(p => p.isEnabled)
55
+ .map(p => p.toString())
56
+ .join(', ') || 'No pipes enabled',
57
+ ),
58
+ );
51
59
 
52
60
  return pipes;
53
- }
61
+ };
@@ -1,6 +1,7 @@
1
1
  const chalk = require('chalk');
2
2
  const axios = require('axios');
3
3
  const JsonCycle = require('json-cycle');
4
+
4
5
  const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_RUN } = process.env;
5
6
  const { APP_PREFIX } = require('../constants');
6
7
  const { isValidUrl } = require('../util');
@@ -10,9 +11,9 @@ if (TESTOMATIO_RUN) {
10
11
  }
11
12
 
12
13
  class TestomatioPipe {
13
- isEnabled = false;
14
-
14
+
15
15
  constructor(params, store = {}) {
16
+ this.isEnabled = false;
16
17
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
17
18
  this.apiKey = params.apiKey || process.env.TESTOMATIO;
18
19
  if (process.env.DEBUG) {
@@ -38,7 +39,7 @@ class TestomatioPipe {
38
39
  APP_PREFIX,
39
40
  chalk.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`),
40
41
  );
41
- return;
42
+
42
43
  }
43
44
  }
44
45
 
@@ -90,11 +91,11 @@ class TestomatioPipe {
90
91
  } catch (err) {
91
92
  if (err.response) {
92
93
  if (err.response.status >= 400) {
93
- const data = err.response.data || { message: '' };
94
+ const responseData = err.response.data || { message: '' };
94
95
  console.log(
95
96
  APP_PREFIX,
96
97
  chalk.blue(this.title),
97
- `Report couldn't be processed: (${err.response.status}) ${data.message}`,
98
+ `Report couldn't be processed: (${err.response.status}) ${responseData.message}`,
98
99
  );
99
100
  return;
100
101
  }
@@ -114,6 +115,7 @@ class TestomatioPipe {
114
115
  api_key: this.apiKey,
115
116
  status_event: params.statusEvent,
116
117
  status: params.status,
118
+ tests: params.tests,
117
119
  });
118
120
  if (this.runUrl) {
119
121
  console.log(APP_PREFIX, '📊 Report Saved. Report URL:', chalk.magenta(this.runUrl));
package/lib/util.js CHANGED
@@ -79,6 +79,8 @@ const fetchSourceCodeFromStackTrace = (stack = '') => {
79
79
  const prepend = 3;
80
80
  const source = fetchSourceCode(fs.readFileSync(file).toString(), { line, prepend, limit: 7 })
81
81
 
82
+ if (!source) return '';
83
+
82
84
  return source.split('\n')
83
85
  .map((l, i) => {
84
86
  if (i === prepend) return `${line} > ${chalk.bold(l)}`;
@@ -137,20 +139,18 @@ const fetchSourceCode = (contents, opts = {}) => {
137
139
  }
138
140
  }
139
141
 
140
- const isSameTest = (test, t) => {
141
- return (typeof t === 'object')
142
+ const isSameTest = (test, t) => (typeof t === 'object')
142
143
  && (typeof test === 'object')
143
- && t.title == test.title
144
- && t.suite_title == test.suite_title
145
- && Object.values(t.example || {}) == Object.values(test.example || {})
146
- && t.test_id == test.test_id
147
- };
144
+ && t.title === test.title
145
+ && t.suite_title === test.suite_title
146
+ && Object.values(t.example || {}) === Object.values(test.example || {})
147
+ && t.test_id === test.test_id;
148
148
 
149
149
  const getCurrentDateTime = () => {
150
150
  const today = new Date();
151
151
 
152
- return today.getFullYear() + '_' + (today.getMonth() + 1) + '_' + today.getDate() + '_' +
153
- today.getHours() + "_" + today.getMinutes() + "_" + today.getSeconds();
152
+ return `${today.getFullYear() }_${ today.getMonth() + 1 }_${ today.getDate() }_${
153
+ today.getHours() }_${ today.getMinutes() }_${ today.getSeconds()}`;
154
154
  }
155
155
 
156
156
  module.exports = {