@testomatio/reporter 2.0.1-beta-ignore-xml → 2.0.1-beta.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 (63) hide show
  1. package/lib/adapter/codecept.js +0 -2
  2. package/lib/adapter/cypress-plugin/index.js +0 -2
  3. package/lib/adapter/mocha.js +0 -1
  4. package/lib/adapter/nightwatch.d.ts +4 -0
  5. package/lib/adapter/nightwatch.js +80 -0
  6. package/lib/adapter/webdriver.d.ts +1 -1
  7. package/lib/adapter/webdriver.js +17 -8
  8. package/lib/bin/cli.js +126 -8
  9. package/lib/bin/reportXml.js +4 -2
  10. package/lib/bin/startTest.js +3 -2
  11. package/lib/bin/uploadArtifacts.js +5 -4
  12. package/lib/client.js +18 -9
  13. package/lib/config.js +2 -2
  14. package/lib/data-storage.d.ts +1 -1
  15. package/lib/data-storage.js +17 -7
  16. package/lib/junit-adapter/csharp.d.ts +1 -0
  17. package/lib/junit-adapter/csharp.js +11 -1
  18. package/lib/pipe/bitbucket.d.ts +2 -0
  19. package/lib/pipe/bitbucket.js +38 -26
  20. package/lib/pipe/debug.js +17 -3
  21. package/lib/pipe/github.d.ts +2 -2
  22. package/lib/pipe/github.js +35 -3
  23. package/lib/pipe/gitlab.d.ts +2 -0
  24. package/lib/pipe/gitlab.js +27 -9
  25. package/lib/pipe/html.d.ts +1 -0
  26. package/lib/pipe/html.js +1 -3
  27. package/lib/pipe/index.js +17 -7
  28. package/lib/pipe/testomatio.d.ts +2 -1
  29. package/lib/pipe/testomatio.js +79 -73
  30. package/lib/reporter.d.ts +12 -12
  31. package/lib/services/artifacts.d.ts +1 -1
  32. package/lib/services/key-values.d.ts +1 -1
  33. package/lib/services/logger.d.ts +1 -1
  34. package/lib/services/logger.js +1 -2
  35. package/lib/template/testomatio.hbs +443 -68
  36. package/lib/uploader.js +2 -2
  37. package/lib/utils/utils.d.ts +2 -0
  38. package/lib/utils/utils.js +41 -18
  39. package/lib/xmlReader.js +54 -19
  40. package/package.json +8 -9
  41. package/src/adapter/codecept.js +0 -2
  42. package/src/adapter/cypress-plugin/index.js +0 -2
  43. package/src/adapter/mocha.js +0 -1
  44. package/src/adapter/nightwatch.js +88 -0
  45. package/src/adapter/webdriver.js +1 -2
  46. package/src/bin/cli.js +131 -2
  47. package/src/bin/reportXml.js +4 -1
  48. package/src/bin/startTest.js +2 -1
  49. package/src/bin/uploadArtifacts.js +2 -1
  50. package/src/client.js +1 -2
  51. package/src/config.js +2 -2
  52. package/src/junit-adapter/csharp.js +13 -1
  53. package/src/pipe/bitbucket.js +22 -24
  54. package/src/pipe/debug.js +18 -3
  55. package/src/pipe/github.js +1 -2
  56. package/src/pipe/gitlab.js +27 -9
  57. package/src/pipe/html.js +3 -4
  58. package/src/pipe/testomatio.js +98 -103
  59. package/src/services/logger.js +1 -2
  60. package/src/template/testomatio.hbs +443 -68
  61. package/src/uploader.js +2 -2
  62. package/src/utils/utils.js +19 -9
  63. package/src/xmlReader.js +69 -17
@@ -1,7 +1,7 @@
1
1
  import { APP_PREFIX, testomatLogoURL } from '../constants.js';
2
2
  import { ansiRegExp, isSameTest } from '../utils/utils.js';
3
3
  import { statusEmoji, fullName } from '../utils/pipe_utils.js';
4
- import axios from 'axios';
4
+ import { Gaxios } from 'gaxios';
5
5
  import pc from 'picocolors';
6
6
  import humanizeDuration from 'humanize-duration';
7
7
  import merge from 'lodash.merge';
@@ -40,6 +40,13 @@ export class BitbucketPipe {
40
40
  }
41
41
 
42
42
  this.isEnabled = true;
43
+ this.client = new Gaxios({
44
+ baseURL: 'https://api.bitbucket.org/2.0',
45
+ headers: {
46
+ 'Content-Type': 'application/json',
47
+ 'Authorization': `Bearer ${this.token}`
48
+ }
49
+ });
43
50
 
44
51
  debug('Bitbucket Pipe: Enabled');
45
52
  }
@@ -166,26 +173,21 @@ export class BitbucketPipe {
166
173
 
167
174
  // Construct Bitbucket API URL for comments
168
175
  // eslint-disable-next-line max-len
169
- const commentsRequestURL = `https://api.bitbucket.org/2.0/repositories/${this.ENV.BITBUCKET_WORKSPACE}/${this.ENV.BITBUCKET_REPO_SLUG}/pullrequests/${this.ENV.BITBUCKET_PR_ID}/comments`;
176
+ const commentsRequestURL = `/repositories/${this.ENV.BITBUCKET_WORKSPACE}/${this.ENV.BITBUCKET_REPO_SLUG}/pullrequests/${this.ENV.BITBUCKET_PR_ID}/comments`;
170
177
 
171
178
  // Delete previous report
172
- await deletePreviousReport(axios, commentsRequestURL, this.hiddenCommentData, this.token);
179
+ await deletePreviousReport(this.client, commentsRequestURL, this.hiddenCommentData);
173
180
 
174
181
  // Add current report
175
182
  debug(`Adding comment via URL: ${commentsRequestURL}`);
176
183
  debug(`Final Bitbucket API call body: ${body}`);
177
184
 
178
185
  try {
179
- const addCommentResponse = await axios.post(
180
- commentsRequestURL,
181
- { content: { raw: body } },
182
- {
183
- headers: {
184
- Authorization: `Bearer ${this.token}`,
185
- 'Content-Type': 'application/json',
186
- },
187
- },
188
- );
186
+ const addCommentResponse = await this.client.request({
187
+ method: 'POST',
188
+ url: commentsRequestURL,
189
+ data: { content: { raw: body } }
190
+ });
189
191
 
190
192
  const commentID = addCommentResponse.data.id;
191
193
  // eslint-disable-next-line max-len
@@ -210,18 +212,16 @@ export class BitbucketPipe {
210
212
  updateRun() {}
211
213
  }
212
214
 
213
- async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCommentData, token) {
215
+ async function deletePreviousReport(client, commentsRequestURL, hiddenCommentData) {
214
216
  if (process.env.BITBUCKET_KEEP_OUTDATED_REPORTS) return;
215
217
 
216
218
  // Get comments
217
219
  let comments = [];
218
220
 
219
221
  try {
220
- const response = await axiosInstance.get(commentsRequestURL, {
221
- headers: {
222
- Authorization: `Bearer ${token}`,
223
- 'Content-Type': 'application/json',
224
- },
222
+ const response = await client.request({
223
+ method: 'GET',
224
+ url: commentsRequestURL
225
225
  });
226
226
  comments = response.data.values;
227
227
  } catch (e) {
@@ -236,11 +236,9 @@ async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCom
236
236
  try {
237
237
  // Delete previous comment
238
238
  const deleteCommentURL = `${commentsRequestURL}/${comment.id}`;
239
- await axiosInstance.delete(deleteCommentURL, {
240
- headers: {
241
- Authorization: `Bearer ${token}`,
242
- 'Content-Type': 'application/json',
243
- },
239
+ await client.request({
240
+ method: 'DELETE',
241
+ url: deleteCommentURL
244
242
  });
245
243
  } catch (e) {
246
244
  console.warn(`Can't delete previously added comment with testomat.io report. Ignored.`);
package/src/pipe/debug.js CHANGED
@@ -25,7 +25,22 @@ export class DebugPipe {
25
25
 
26
26
  debug('Creating debug file:', this.logFilePath);
27
27
  fs.writeFileSync(this.logFilePath, '');
28
- console.log(APP_PREFIX, '🪲. Debug created:');
28
+
29
+ // Create symlink to ensure consistent path to latest debug file
30
+ const symlinkPath = path.join(os.tmpdir(), 'testomatio.debug.latest.json');
31
+ try {
32
+ // Remove existing symlink if it exists
33
+ if (fs.existsSync(symlinkPath)) {
34
+ fs.unlinkSync(symlinkPath);
35
+ }
36
+ // Create new symlink pointing to the timestamped debug file
37
+ fs.symlinkSync(this.logFilePath, symlinkPath);
38
+ debug('Created symlink:', symlinkPath, '->', this.logFilePath);
39
+ } catch (err) {
40
+ debug('Failed to create symlink:', err.message);
41
+ }
42
+
43
+ console.log(APP_PREFIX, '🪲 Debug file created');
29
44
  this.testomatioEnvVars = Object.keys(process.env)
30
45
  .filter(key => key.startsWith('TESTOMATIO_'))
31
46
  .reduce((acc, key) => {
@@ -92,10 +107,10 @@ export class DebugPipe {
92
107
 
93
108
  async finishRun(params) {
94
109
  if (!this.isEnabled) return;
95
- this.logToFile({ actions: 'finishRun', params });
96
110
  await this.batchUpload();
97
111
  if (this.batch.intervalFunction) clearInterval(this.batch.intervalFunction);
98
- console.log(APP_PREFIX, '🪲. Debug Saved to', this.logFilePath);
112
+ this.logToFile({ actions: 'finishRun', params });
113
+ console.log(APP_PREFIX, '🪲 Debug Saved to', this.logFilePath);
99
114
  }
100
115
 
101
116
  toString() {
@@ -3,7 +3,6 @@ import path from 'path';
3
3
  import pc from 'picocolors';
4
4
  import humanizeDuration from 'humanize-duration';
5
5
  import merge from 'lodash.merge';
6
- import { Octokit } from '@octokit/rest';
7
6
  import { APP_PREFIX, testomatLogoURL } from '../constants.js';
8
7
  import { ansiRegExp, isSameTest } from '../utils/utils.js';
9
8
  import { statusEmoji, fullName } from '../utils/pipe_utils.js';
@@ -64,6 +63,7 @@ class GitHubPipe {
64
63
  if (!this.issue) return;
65
64
 
66
65
  if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
66
+ const { Octokit } = await import('@octokit/rest');
67
67
 
68
68
  this.octokit = new Octokit({
69
69
  auth: this.token,
@@ -154,7 +154,6 @@ class GitHubPipe {
154
154
  if (this.tests.length > 0) {
155
155
  body += '\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n';
156
156
  body += this.tests
157
- // eslint-disable-next-line no-unsafe-optional-chaining
158
157
  .sort((a, b) => b?.run_time - a?.run_time)
159
158
  .slice(0, 5)
160
159
  .map(t => `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`)
@@ -1,5 +1,5 @@
1
1
  import createDebugMessages from 'debug';
2
- import axios from 'axios';
2
+ import { Gaxios } from 'gaxios';
3
3
  import pc from 'picocolors';
4
4
  import humanizeDuration from 'humanize-duration';
5
5
  import merge from 'lodash.merge';
@@ -45,6 +45,12 @@ class GitLabPipe {
45
45
  }
46
46
 
47
47
  this.isEnabled = true;
48
+ this.client = new Gaxios({
49
+ baseURL: 'https://gitlab.com/api/v4',
50
+ headers: {
51
+ 'Content-Type': 'application/json',
52
+ }
53
+ });
48
54
 
49
55
  debug('GitLab Pipe: Enabled');
50
56
  }
@@ -149,7 +155,6 @@ class GitLabPipe {
149
155
  if (this.tests.length > 0) {
150
156
  body += '\n<details>\n<summary><h3>🐢 Slowest Tests</h3></summary>\n\n';
151
157
  body += this.tests
152
- // eslint-disable-next-line no-unsafe-optional-chaining
153
158
  .sort((a, b) => b?.run_time - a?.run_time)
154
159
  .slice(0, 5)
155
160
  .map(t => `* ${fullName(t)} (${humanizeDuration(parseFloat(t.run_time))})`)
@@ -158,16 +163,21 @@ class GitLabPipe {
158
163
  }
159
164
 
160
165
  // eslint-disable-next-line max-len
161
- const commentsRequestURL = `https://gitlab.com/api/v4/projects/${this.ENV.CI_PROJECT_ID}/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}/notes`;
166
+ const commentsRequestURL = `/projects/${this.ENV.CI_PROJECT_ID}/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}/notes`;
162
167
 
163
168
  // delete previous report
164
- await deletePreviousReport(axios, commentsRequestURL, this.hiddenCommentData, this.token);
169
+ await deletePreviousReport(this.client, commentsRequestURL, this.hiddenCommentData, this.token);
165
170
 
166
171
  // add current report
167
172
  debug(`Adding comment via url: ${commentsRequestURL}`);
168
173
 
169
174
  try {
170
- const addCommentResponse = await axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
175
+ const addCommentResponse = await this.client.request({
176
+ method: 'POST',
177
+ url: commentsRequestURL,
178
+ params: { access_token: this.token },
179
+ data: { body }
180
+ });
171
181
 
172
182
  const commentID = addCommentResponse.data.id;
173
183
  // eslint-disable-next-line max-len
@@ -192,14 +202,18 @@ class GitLabPipe {
192
202
  updateRun() {}
193
203
  }
194
204
 
195
- async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCommentData, token) {
205
+ async function deletePreviousReport(client, commentsRequestURL, hiddenCommentData, token) {
196
206
  if (process.env.GITLAB_KEEP_OUTDATED_REPORTS) return;
197
207
 
198
208
  // get comments
199
209
  let comments = [];
200
210
 
201
211
  try {
202
- const response = await axiosInstance.get(`${commentsRequestURL}?access_token=${token}`);
212
+ const response = await client.request({
213
+ method: 'GET',
214
+ url: commentsRequestURL,
215
+ params: { access_token: token }
216
+ });
203
217
  comments = response.data;
204
218
  } catch (e) {
205
219
  console.error('Error while attempt to retrieve comments on GitLab Merge Request:\n', e);
@@ -212,8 +226,12 @@ async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCom
212
226
  if (comment.body.includes(hiddenCommentData)) {
213
227
  try {
214
228
  // delete previous comment
215
- const deleteCommentURL = `${commentsRequestURL}/${comment.id}?access_token=${token}`;
216
- await axiosInstance.delete(deleteCommentURL);
229
+ const deleteCommentURL = `${commentsRequestURL}/${comment.id}`;
230
+ await client.request({
231
+ method: 'DELETE',
232
+ url: deleteCommentURL,
233
+ params: { access_token: token }
234
+ });
217
235
  } catch (e) {
218
236
  console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
219
237
  }
package/src/pipe/html.js CHANGED
@@ -66,6 +66,8 @@ class HtmlPipe {
66
66
  // empty
67
67
  }
68
68
 
69
+ async prepareRun() {}
70
+
69
71
  updateRun() {
70
72
  // empty
71
73
  }
@@ -235,7 +237,6 @@ class HtmlPipe {
235
237
  </select>`,
236
238
  ),
237
239
  );
238
- /* eslint-disable */
239
240
  handlebars.registerHelper('emptyDataComponent', () => {
240
241
  const svgFilePath = path.join(__dirname, '..', 'template', 'emptyData.svg');
241
242
  const svgContent = fs.readFileSync(svgFilePath, 'utf8');
@@ -252,13 +253,12 @@ class HtmlPipe {
252
253
  <div>`,
253
254
  );
254
255
  });
255
- /* eslint-enable */
256
256
  handlebars.registerHelper('pageDispleyElements', tests => {
257
257
  // We wrapp the lines to the HTML format we need
258
258
  const totalTests = JSON.parse(
259
259
  JSON.stringify(tests)
260
260
  .replace(/<script>/g, '&lt;script&gt;')
261
- .replace(/<\/script>/g, '&lt;/script&gt;'), // eslint-disable-line
261
+ .replace(/<\/script>/g, '&lt;/script&gt;'),
262
262
  );
263
263
 
264
264
  const paginationOptions = {
@@ -285,7 +285,6 @@ class HtmlPipe {
285
285
 
286
286
  statuses.forEach(status => {
287
287
  for (const option in paginationOptions) {
288
- // eslint-disable-next-line no-prototype-builtins
289
288
  if (paginationOptions.hasOwnProperty(option)) {
290
289
  const pageSize = paginationOptions[option];
291
290
  let filteredItems = totalTests;
@@ -1,12 +1,6 @@
1
1
  import createDebugMessages from 'debug';
2
2
  import pc from 'picocolors';
3
-
4
- // Retry interceptor function
5
- import axiosRetry from 'axios-retry';
6
-
7
- // Default axios instance
8
- import axios from 'axios';
9
-
3
+ import { Gaxios } from 'gaxios';
10
4
  import JsonCycle from 'json-cycle';
11
5
  import { APP_PREFIX, STATUS, AXIOS_TIMEOUT, REPORTER_REQUEST_RETRIES } from '../constants.js';
12
6
  import { isValidUrl, foundedTestLog } from '../utils/utils.js';
@@ -15,9 +9,7 @@ import { config } from '../config.js';
15
9
 
16
10
  const debug = createDebugMessages('@testomatio/reporter:pipe:testomatio');
17
11
 
18
- if (process.env.TESTOMATIO_RUN) {
19
- // process.env.runId = process.env.TESTOMATIO_RUN;
20
- }
12
+ if (process.env.TESTOMATIO_RUN) process.env.runId = process.env.TESTOMATIO_RUN;
21
13
 
22
14
  /**
23
15
  * @typedef {import('../../types/types.js').Pipe} Pipe
@@ -59,50 +51,38 @@ class TestomatioPipe {
59
51
  this.groupTitle = params.groupTitle || process.env.TESTOMATIO_RUNGROUP_TITLE;
60
52
  this.env = process.env.TESTOMATIO_ENV;
61
53
  this.label = process.env.TESTOMATIO_LABEL;
62
- // Create a new instance of axios with a custom config
63
- this.axios = axios.create({
54
+
55
+ // Create a new instance of gaxios with a custom config
56
+ this.client = new Gaxios({
64
57
  baseURL: `${this.url.trim()}`,
65
58
  timeout: AXIOS_TIMEOUT,
66
- proxy: proxy
67
- ? {
68
- host: proxy.hostname,
69
- port: parseInt(proxy.port, 10),
70
- protocol: proxy.protocol,
59
+ proxy: proxy ? proxy.toString() : undefined,
60
+ retry: true,
61
+ retryConfig: {
62
+ retry: REPORTER_REQUEST_RETRIES.retriesPerRequest,
63
+ retryDelay: REPORTER_REQUEST_RETRIES.retryTimeout,
64
+ httpMethodsToRetry: ['GET','PUT','HEAD','OPTIONS','DELETE','POST'],
65
+ shouldRetry: (error) => {
66
+ if (!error.response) return false;
67
+ switch (error.response?.status) {
68
+ case 400: // Bad request (probably wrong API key)
69
+ case 404: // Test not matched
70
+ case 429: // Rate limit exceeded
71
+ case 500: // Internal server error
72
+ return false;
73
+ default:
74
+ break;
71
75
  }
72
- : false,
73
- });
74
-
75
- // Pass the axios instance to the retry function
76
- axiosRetry(this.axios, {
77
- // do not use retries for unit tests
78
- retries: REPORTER_REQUEST_RETRIES.retriesPerRequest, // Number of retries
79
- shouldResetTimeout: true,
80
- retryCondition: error => {
81
- if (!error.response) return false;
82
- switch (error.response?.status) {
83
- case 400: // Bad request (probably wrong API key)
84
- case 404: // Test not matched
85
- case 429: // Rate limit exceeded
86
- case 500: // Internal server error
87
- return false;
88
- default:
89
- break;
76
+ return error.response?.status >= 401; // Retry on 401+ and 5xx
90
77
  }
91
- return error.response?.status >= 401; // Retry on 401+ and 5xx
92
- },
93
- retryDelay: () => REPORTER_REQUEST_RETRIES.retryTimeout, // sum = 15sec
94
- onRetry: async (retryCount, error) => {
95
- this.retriesTimestamps.push(Date.now());
96
-
97
- debug(`${error.message || `Request failed ${error.status}`}. Retry #${retryCount} ...`);
98
- },
78
+ }
99
79
  });
100
80
 
101
81
  this.isEnabled = true;
102
82
  // do not finish this run (for parallel testing)
103
83
  this.proceed = process.env.TESTOMATIO_PROCEED;
104
84
  this.jiraId = process.env.TESTOMATIO_JIRA_ID;
105
- this.runId = params.runId || process.env.runId;
85
+ this.runId = params.runId || process.env.TESTOMATIO_RUN;
106
86
  this.createNewTests = params.createNewTests ?? !!process.env.TESTOMATIO_CREATE;
107
87
  this.hasUnmatchedTests = false;
108
88
  this.requestFailures = 0;
@@ -136,12 +116,15 @@ class TestomatioPipe {
136
116
  return;
137
117
  }
138
118
 
139
- const resp = await this.axios.get('/api/test_grep', q);
140
- const { data } = resp;
119
+ const resp = await this.client.request({
120
+ method: 'GET',
121
+ url: '/api/test_grep',
122
+ params: q
123
+ });
141
124
 
142
- if (Array.isArray(data?.tests) && data?.tests?.length > 0) {
143
- foundedTestLog(APP_PREFIX, data.tests);
144
- return data.tests;
125
+ if (Array.isArray(resp.data?.tests) && resp.data?.tests?.length > 0) {
126
+ foundedTestLog(APP_PREFIX, resp.data.tests);
127
+ return resp.data.tests;
145
128
  }
146
129
 
147
130
  console.log(APP_PREFIX, `⛔ No tests found for your --filter --> ${type}=${id}`);
@@ -201,16 +184,23 @@ class TestomatioPipe {
201
184
  if (this.runId) {
202
185
  this.store.runId = this.runId;
203
186
  debug(`Run with id ${this.runId} already created, updating...`);
204
- const resp = await this.axios.put(`/api/reporter/${this.runId}`, runParams);
187
+ const resp = await this.client.request({
188
+ method: 'PUT',
189
+ url: `/api/reporter/${this.runId}`,
190
+ data: runParams
191
+ });
205
192
  if (resp.data.artifacts) setS3Credentials(resp.data.artifacts);
206
193
  return;
207
194
  }
208
195
 
209
196
  debug('Creating run...');
210
197
  try {
211
- const resp = await this.axios.post(`/api/reporter`, runParams, {
198
+ const resp = await this.client.request({
199
+ method: 'POST',
200
+ url: '/api/reporter',
201
+ data: runParams,
212
202
  maxContentLength: Infinity,
213
- maxBodyLength: Infinity,
203
+ responseType: 'json'
214
204
  });
215
205
 
216
206
  this.runId = resp.data.uid;
@@ -227,6 +217,7 @@ class TestomatioPipe {
227
217
  debug('Run created', this.runId);
228
218
  } catch (err) {
229
219
  const errorText = err.response?.data?.message || err.message;
220
+ debug('Error creating run', err);
230
221
  console.log(errorText || err);
231
222
  if (!this.apiKey) console.error('Testomat.io API key is not set');
232
223
  if (!this.apiKey?.startsWith('tstmt')) console.error('Testomat.io API key is invalid');
@@ -273,7 +264,15 @@ class TestomatioPipe {
273
264
 
274
265
  debug('Adding test', json);
275
266
 
276
- return this.axios.post(`/api/reporter/${this.runId}/testrun`, json, axiosAddTestrunRequestConfig).catch(err => {
267
+ return this.client.request({
268
+ method: 'POST',
269
+ url: `/api/reporter/${this.runId}/testrun`,
270
+ data: json,
271
+ headers: {
272
+ 'Content-Type': 'application/json',
273
+ },
274
+ maxContentLength: Infinity
275
+ }).catch(err => {
277
276
  this.requestFailures++;
278
277
  this.notReportedTestsCount++;
279
278
  if (err.response) {
@@ -325,38 +324,43 @@ class TestomatioPipe {
325
324
  const testsToSend = this.batch.tests.splice(0);
326
325
  debug('📨 Batch upload', testsToSend.length, 'tests');
327
326
 
328
- return this.axios
329
- .post(
330
- `/api/reporter/${this.runId}/testrun`,
331
- { api_key: this.apiKey, tests: testsToSend, batch_index: this.batch.batchIndex },
332
- axiosAddTestrunRequestConfig,
333
- )
334
- .catch(err => {
335
- this.requestFailures++;
336
- this.notReportedTestsCount += testsToSend.length;
337
- if (err.response) {
338
- if (err.response.status >= 400) {
339
- const responseData = err.response.data || { message: '' };
340
- console.log(
341
- APP_PREFIX,
342
- pc.yellow(`Warning: ${responseData.message} (${err.response.status})`),
343
- // pc.grey(data?.title || ''),
344
- );
345
- if (err.response?.data?.message?.includes('could not be matched')) {
346
- this.hasUnmatchedTests = true;
347
- }
348
- return;
349
- }
327
+ return this.client.request({
328
+ method: 'POST',
329
+ url: `/api/reporter/${this.runId}/testrun`,
330
+ data: {
331
+ api_key: this.apiKey,
332
+ tests: testsToSend,
333
+ batch_index: this.batch.batchIndex
334
+ },
335
+ headers: {
336
+ 'Content-Type': 'application/json',
337
+ },
338
+ maxContentLength: Infinity
339
+ }).catch(err => {
340
+ this.requestFailures++;
341
+ this.notReportedTestsCount += testsToSend.length;
342
+ if (err.response) {
343
+ if (err.response.status >= 400) {
344
+ const responseData = err.response.data || { message: '' };
350
345
  console.log(
351
346
  APP_PREFIX,
352
- pc.yellow(`Warning: (${err.response?.status})`),
353
- `Report couldn't be processed: ${err?.response?.data?.message}`,
347
+ pc.yellow(`Warning: ${responseData.message} (${err.response.status})`),
354
348
  );
355
- printCreateIssue(err);
356
- } else {
357
- console.log(APP_PREFIX, "Report couldn't be processed", err);
349
+ if (err.response?.data?.message?.includes('could not be matched')) {
350
+ this.hasUnmatchedTests = true;
351
+ }
352
+ return;
358
353
  }
359
- });
354
+ console.log(
355
+ APP_PREFIX,
356
+ pc.yellow(`Warning: (${err.response?.status})`),
357
+ `Report couldn't be processed: ${err?.response?.data?.message}`,
358
+ );
359
+ printCreateIssue(err);
360
+ } else {
361
+ console.log(APP_PREFIX, "Report couldn't be processed", err);
362
+ }
363
+ });
360
364
  };
361
365
 
362
366
  /**
@@ -415,12 +419,16 @@ class TestomatioPipe {
415
419
 
416
420
  try {
417
421
  if (this.runId && !this.proceed) {
418
- await this.axios.put(`/api/reporter/${this.runId}`, {
419
- api_key: this.apiKey,
420
- duration: params.duration,
421
- status_event,
422
- detach: params.detach,
423
- tests: params.tests,
422
+ await this.client.request({
423
+ method: 'PUT',
424
+ url: `/api/reporter/${this.runId}`,
425
+ data: {
426
+ api_key: this.apiKey,
427
+ duration: params.duration,
428
+ status_event,
429
+ detach: params.detach,
430
+ tests: params.tests,
431
+ }
424
432
  });
425
433
  if (this.runUrl) {
426
434
  console.log(APP_PREFIX, '📊 Report Saved. Report URL:', pc.magenta(this.runUrl));
@@ -437,14 +445,11 @@ class TestomatioPipe {
437
445
 
438
446
  if (this.hasUnmatchedTests) {
439
447
  console.log('');
440
- // eslint-disable-next-line max-len
441
448
  console.log(APP_PREFIX, pc.yellow(pc.bold('⚠️ Some reported tests were not found in Testomat.io project')));
442
- // eslint-disable-next-line max-len
443
449
  console.log(
444
450
  APP_PREFIX,
445
451
  `If you use Testomat.io as a reporter only, please re-run tests using ${pc.bold('TESTOMATIO_CREATE=1')}`,
446
452
  );
447
- // eslint-disable-next-line max-len
448
453
  console.log(
449
454
  APP_PREFIX,
450
455
  `But to keep your tests consistent it is recommended to ${pc.bold('import tests first')}`,
@@ -453,7 +458,6 @@ class TestomatioPipe {
453
458
  console.log(APP_PREFIX, 'You can do that automatically via command line tools:');
454
459
  console.log(APP_PREFIX, pc.bold('npx check-tests ... --update-ids'), 'See: https://bit.ly/js-update-ids');
455
460
  console.log(APP_PREFIX, 'or for Cucumber:');
456
- // eslint-disable-next-line max-len
457
461
  console.log(APP_PREFIX, pc.bold('npx check-cucumber ... --update-ids'), 'See: https://bit.ly/bdd-update-ids');
458
462
  }
459
463
  } catch (err) {
@@ -478,26 +482,17 @@ function printCreateIssue(err) {
478
482
  console.log(
479
483
  APP_PREFIX,
480
484
  'If you think this is a bug please create an issue: https://github.com/testomatio/reporter/issues/new',
481
- ); // eslint-disable-line max-len
485
+ );
482
486
  console.log(APP_PREFIX, 'Provide this information:');
483
487
  console.log('Error:', err.message || err.code);
484
488
  if (!err.config) return;
485
489
 
486
490
  const time = new Date().toUTCString();
487
- const { data, url, baseURL, method } = err?.config || {};
491
+ const { body, url, baseURL, method } = err?.config || {};
488
492
  console.log('```js');
489
- console.log({ data: data?.replace(/"(tstmt_[^"]+)"/g, 'tstmt_*'), url, baseURL, method, time });
493
+ console.log({ body: body?.replace(/"(tstmt_[^"]+)"/g, 'tstmt_*'), url, baseURL, method, time });
490
494
  console.log('```');
491
495
  });
492
496
  }
493
497
 
494
- const axiosAddTestrunRequestConfig = {
495
- maxContentLength: Infinity,
496
- maxBodyLength: Infinity,
497
- headers: {
498
- // Overwrite Axios's automatically set Content-Type
499
- 'Content-Type': 'application/json',
500
- },
501
- };
502
-
503
498
  export default TestomatioPipe;
@@ -93,7 +93,6 @@ class Logger {
93
93
  logs.push(arg.join(' '));
94
94
  } else {
95
95
  try {
96
- // eslint-disable-next-line no-unused-expressions
97
96
  this.prettyObjects ? logs.push(JSON.stringify(arg, null, 2)) : logs.push(JSON.stringify(arg));
98
97
  } catch (e) {
99
98
  debug('Error while stringify object', e);
@@ -123,7 +122,7 @@ class Logger {
123
122
  current +
124
123
  // strings are splitted by args when use tagged template, thus we add arg after each string
125
124
  // it looks like: `string1 arg1 string2 arg2 string3`
126
- (args[index] !== undefined // eslint-disable-line no-nested-ternary
125
+ (args[index] !== undefined
127
126
  ? typeof args[index] === 'string'
128
127
  ? args[index] // add arg as it is
129
128
  : this.#stringifyLogs(args[index]) // stringify arg