@testomatio/reporter 0.8.0-beta.30 → 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,4 +1,5 @@
1
- const axios = require('axios');
1
+ const debug = require('debug')('@testomatio/reporter:pipe:gitlab');
2
+ const { default: axios } = require('axios');
2
3
  const chalk = require('chalk');
3
4
  const humanizeDuration = require('humanize-duration');
4
5
  const merge = require('lodash.merge');
@@ -9,6 +10,11 @@ const { ansiRegExp, isSameTest } = require('../util');
9
10
  //! GITLAB_PAT environment variable is required for this functionality to work
10
11
  //! and your pipeline trigger should be merge_request
11
12
 
13
+ /**
14
+ * @class GitLabPipe
15
+ * @typedef {import('../../types').Pipe} Pipe
16
+ * @typedef {import('../../types').TestData} TestData
17
+ */
12
18
  class GitLabPipe {
13
19
  constructor(params, store = {}) {
14
20
  this.isEnabled = false;
@@ -18,32 +24,26 @@ class GitLabPipe {
18
24
  // GitLab PAT looks like glpat-nKGdja3jsG4850sGksh7
19
25
  this.token = params.GITLAB_PAT || this.ENV.GITLAB_PAT;
20
26
  this.hiddenCommentData = `<!--- testomat.io report ${process.env.CI_JOB_NAME || ''} -->`;
21
- this.axios = axios.create();
22
27
 
23
- if (this.ENV.DEBUG) {
24
- console.log(
25
- APP_PREFIX,
26
- chalk.yellow('GitLab Pipe:'),
27
- this.token ? 'TOKEN passed' : '*no token*',
28
- `Project id: ${this.ENV.CI_PROJECT_ID}, MR id: ${this.ENV.CI_MERGE_REQUEST_IID}`,
29
- );
30
- }
28
+ debug(
29
+ chalk.yellow('GitLab Pipe:'),
30
+ this.token ? 'TOKEN passed' : '*no token*',
31
+ `Project id: ${this.ENV.CI_PROJECT_ID}, MR id: ${this.ENV.CI_MERGE_REQUEST_IID}`,
32
+ );
31
33
 
32
34
  if (!this.ENV.CI_PROJECT_ID || !this.ENV.CI_MERGE_REQUEST_IID) {
33
- // console.warn(`CI pipeline should be run in Merge Request to have ability to add the report comment.`);
35
+ debug(`CI pipeline should be run in Merge Request to have ability to add the report comment.`);
34
36
  return;
35
37
  }
36
38
 
37
39
  if (!this.token) {
38
- console.warn(chalk.grey(`Hint: GitLab CI variables are unavailable for unprotected branches by default.`));
40
+ debug(`Hint: GitLab CI variables are unavailable for unprotected branches by default.`);
39
41
  return;
40
42
  }
41
43
 
42
44
  this.isEnabled = true;
43
45
 
44
- if (this.ENV.DEBUG) {
45
- console.log(APP_PREFIX, chalk.yellow('GitLab Pipe: Enabled'));
46
- }
46
+ debug('GitLab Pipe: Enabled');
47
47
  }
48
48
 
49
49
  async createRun() {}
@@ -75,8 +75,7 @@ class GitLabPipe {
75
75
  let summary = `${this.hiddenCommentData}
76
76
 
77
77
  | [![Testomat.io Report](https://avatars.githubusercontent.com/u/59105116?s=36&v=4)](https://testomat.io) | ${
78
- statusEmoji(runParams.status,
79
- )} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
78
+ statusEmoji(runParams.status)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
80
79
  | --- | --- |
81
80
  | Tests | ✔️ **${this.tests.length}** tests run |
82
81
  | Summary | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji(
@@ -86,8 +85,8 @@ class GitLabPipe {
86
85
  `;
87
86
 
88
87
  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: **${
90
- this.ENV.CI_JOB_NAME}**<br>Stage: **${this.ENV.CI_JOB_STAGE}** | `;
88
+ // eslint-disable-next-line max-len
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}** | `;
91
90
  }
92
91
 
93
92
  const failures = this.tests
@@ -147,12 +146,13 @@ class GitLabPipe {
147
146
  const commentsRequestURL = `https://gitlab.com/api/v4/projects/${this.ENV.CI_PROJECT_ID}/merge_requests/${this.ENV.CI_MERGE_REQUEST_IID}/notes`;
148
147
 
149
148
  // delete previous report
150
- await deletePreviousReport(this.axios, commentsRequestURL, this.hiddenCommentData, this.token);
149
+ await deletePreviousReport(axios, commentsRequestURL, this.hiddenCommentData, this.token);
151
150
 
152
151
  // add current report
153
- console.info(chalk.grey(`Adding comment via url: ${commentsRequestURL}`));
152
+ debug(`Adding comment via url: ${commentsRequestURL}`);
153
+
154
154
  try {
155
- const addCommentResponse = await this.axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
155
+ const addCommentResponse = await axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
156
156
 
157
157
  const commentID = addCommentResponse.data.id;
158
158
  // eslint-disable-next-line max-len
@@ -160,7 +160,7 @@ class GitLabPipe {
160
160
 
161
161
  console.log(APP_PREFIX, chalk.yellow('GitLab'), `Report created: ${chalk.magenta(commentURL)}`);
162
162
  } catch (err) {
163
- console.log(
163
+ console.error(
164
164
  APP_PREFIX,
165
165
  chalk.yellow('GitLab'),
166
166
  `Couldn't create GitLab report\n${err}.
@@ -215,7 +215,7 @@ async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCom
215
215
  const deleteCommentURL = `${commentsRequestURL}/${comment.id}?access_token=${token}`;
216
216
  await axiosInstance.delete(deleteCommentURL);
217
217
  } catch (e) {
218
- console.error(`Can't delete previously added comment with testomat.io report. Ignore.`);
218
+ console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
219
219
  }
220
220
 
221
221
  // pass next env var if need to clear all previous reports;
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;
@@ -1,94 +1,107 @@
1
+ const debug = require('debug')('@testomatio/reporter:pipe:testomatio');
1
2
  const chalk = require('chalk');
2
3
  const axios = require('axios');
3
4
  const JsonCycle = require('json-cycle');
4
-
5
- const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_RUN } = process.env;
6
- const { APP_PREFIX } = require('../constants');
5
+ const { APP_PREFIX, STATUS } = require('../constants');
7
6
  const { isValidUrl } = require('../util');
8
7
 
8
+ const { TESTOMATIO_RUN } = process.env;
9
9
  if (TESTOMATIO_RUN) {
10
10
  process.env.runId = TESTOMATIO_RUN;
11
11
  }
12
12
 
13
+ /**
14
+ * @typedef {import('../../types').Pipe} Pipe
15
+ * @typedef {import('../../types').TestData} TestData
16
+ * @class TestomatioPipe
17
+ * @implements {Pipe}
18
+ */
13
19
  class TestomatioPipe {
14
-
15
- constructor(params, store = {}) {
20
+ constructor(params, store) {
16
21
  this.isEnabled = false;
17
22
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
18
23
  this.apiKey = params.apiKey || process.env.TESTOMATIO;
19
- if (process.env.DEBUG) {
20
- console.log(APP_PREFIX, 'Testomatio Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
21
- }
24
+ debug('Testomatio Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
22
25
  if (!this.apiKey) {
23
26
  return;
24
27
  }
25
- if (process.env.DEBUG) {
26
- console.log(APP_PREFIX, 'Testomatio Pipe: Enabled');
27
- }
28
- this.store = store;
28
+ debug('Testomatio Pipe: Enabled');
29
+ this.store = store || {};
29
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;
30
33
  this.axios = axios.create();
31
34
  this.isEnabled = true;
35
+ // do not finish this run (for parallel testing)
32
36
  this.proceed = process.env.TESTOMATIO_PROCEED;
33
37
  this.runId = params.runId || process.env.runId;
34
38
  this.createNewTests = !!process.env.TESTOMATIO_CREATE;
35
39
 
36
40
  if (!isValidUrl(this.url.trim())) {
37
41
  this.isEnabled = false;
38
- console.log(
39
- APP_PREFIX,
40
- chalk.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`),
41
- );
42
-
42
+ console.error(APP_PREFIX, chalk.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`));
43
43
  }
44
44
  }
45
45
 
46
- async createRun(runParams) {
46
+ /**
47
+ * @returns Promise<void>
48
+ */
49
+ async createRun() {
47
50
  if (!this.isEnabled) return;
48
51
 
49
- runParams.api_key = this.apiKey.trim();
50
- runParams.group_title = TESTOMATIO_RUNGROUP_TITLE;
51
-
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
+ );
60
+
52
61
  if (this.runId) {
53
- return this.axios.put(`${this.url.trim()}/api/reporter/${this.runId}`, runParams)
62
+ return this.axios.put(`${this.url.trim()}/api/reporter/${this.runId}`, runParams);
54
63
  }
55
-
64
+
56
65
  try {
57
66
  const resp = await this.axios.post(`${this.url.trim()}/api/reporter`, runParams, {
58
67
  maxContentLength: Infinity,
59
68
  maxBodyLength: Infinity,
60
- })
69
+ });
61
70
  this.runId = resp.data.uid;
62
71
  this.runUrl = `${this.url}/${resp.data.url.split('/').splice(3).join('/')}`;
63
72
  this.store.runUrl = this.runUrl;
64
- this.store.runId = this.runId;
73
+ this.store.runId = this.runId;
65
74
  console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId);
66
75
  process.env.runId = this.runId;
67
76
  } catch (err) {
68
- console.log(
77
+ console.error(
69
78
  APP_PREFIX,
70
79
  'Error creating Testomat.io report, please check if your API key is valid. Skipping report',
71
80
  );
72
81
  }
73
82
  }
74
83
 
75
- async addTest(data) {
84
+ /**
85
+ *
86
+ * @param testData data
87
+ * @returns
88
+ */
89
+ addTest(data) {
76
90
  if (!this.isEnabled) return;
77
91
  if (!this.runId) return;
78
92
  data.api_key = this.apiKey;
79
93
  data.create = this.createNewTests;
80
94
  const json = JsonCycle.stringify(data);
81
95
 
82
- try {
83
- return await this.axios.post(`${this.url}/api/reporter/${this.runId}/testrun`, json, {
84
- maxContentLength: Infinity,
85
- maxBodyLength: Infinity,
86
- headers: {
87
- // Overwrite Axios's automatically set Content-Type
88
- 'Content-Type': 'application/json',
89
- },
90
- });
91
- } catch (err) {
96
+ return this.axios.post(`${this.url}/api/reporter/${this.runId}/testrun`, json, {
97
+ maxContentLength: Infinity,
98
+ maxBodyLength: Infinity,
99
+ headers: {
100
+ // Overwrite Axios's automatically set Content-Type
101
+ 'Content-Type': 'application/json',
102
+ },
103
+ })
104
+ .catch((err) => {
92
105
  if (err.response) {
93
106
  if (err.response.status >= 400) {
94
107
  const responseData = err.response.data || { message: '' };
@@ -103,18 +116,30 @@ class TestomatioPipe {
103
116
  } else {
104
117
  console.log(APP_PREFIX, chalk.blue(this.title), "Report couldn't be processed", err);
105
118
  }
106
- }
107
-
119
+ });
108
120
  }
109
121
 
122
+ /**
123
+ * @param {import('../../types').RunData} params
124
+ * @returns
125
+ */
110
126
  async finishRun(params) {
111
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
+
112
138
  try {
113
139
  if (this.runId && !this.proceed) {
114
140
  await this.axios.put(`${this.url}/api/reporter/${this.runId}`, {
115
141
  api_key: this.apiKey,
116
- status_event: params.statusEvent,
117
- status: params.status,
142
+ status_event,
118
143
  tests: params.tests,
119
144
  });
120
145
  if (this.runUrl) {
@@ -136,4 +161,4 @@ class TestomatioPipe {
136
161
  }
137
162
  }
138
163
 
139
- module.exports = TestomatioPipe;
164
+ module.exports = TestomatioPipe;
package/lib/reporter.js CHANGED
@@ -1,7 +1,9 @@
1
1
  const TestomatClient = require('./client');
2
2
  const TRConstants = require('./constants');
3
+ const TRArtifacts = require('./ArtifactStorage');
3
4
 
4
5
  module.exports = {
5
6
  TestomatClient,
6
7
  TRConstants,
8
+ TRArtifacts
7
9
  };
package/lib/util.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { URL } = require('url');
2
- const { sep } = require('path');
2
+ const { sep, basename } = require('path');
3
3
  const chalk = require('chalk');
4
4
  const fs = require('fs');
5
5
  const isValid = require('is-valid-path');
@@ -7,7 +7,7 @@ const isValid = require('is-valid-path');
7
7
  /**
8
8
  * @param {String} testTitle - Test title
9
9
  *
10
- * @returns {String} testId
10
+ * @returns {String|null} testId
11
11
  */
12
12
  const parseTest = testTitle => {
13
13
  const captures = testTitle.match(/@T([\w\d]+)/);
@@ -21,7 +21,7 @@ const parseTest = testTitle => {
21
21
  /**
22
22
  * @param {String} suiteTitle - suite title
23
23
  *
24
- * @returns {String} suiteId
24
+ * @returns {String|null} suiteId
25
25
  */
26
26
  const parseSuite = suiteTitle => {
27
27
  const captures = suiteTitle.match(/@S([\w\d]+)/);
@@ -63,12 +63,12 @@ const fetchSourceCodeFromStackTrace = (stack = '') => {
63
63
  // .map(l => l.match(/\[(.*?)\]/)?.[1] || l) // minitest format
64
64
  // .map(l => l.split(':')[0])
65
65
  .map(l => l.trim())
66
- .map(l => l.split(' ').find(p => p.includes(':')))
67
- .filter(l => isValid(l.split(':')[0]))
66
+ .map(l => l.split(' ').find(p => p.includes(':')) || '')
67
+ .filter(l => isValid(l?.split(':')[0]))
68
68
 
69
69
  // // filter out 3rd party libs
70
- .filter(l => !l.includes(`vendor${ sep}`))
71
- .filter(l => !l.includes(`node_modules${ sep}`))
70
+ .filter(l => !l?.includes(`vendor${ sep}`))
71
+ .filter(l => !l?.includes(`node_modules${ sep}`))
72
72
  .filter(l => fs.existsSync(l.split(':')[0]))
73
73
  .filter(l => fs.lstatSync(l.split(':')[0]).isFile())
74
74
 
@@ -153,14 +153,32 @@ const getCurrentDateTime = () => {
153
153
  today.getHours() }_${ today.getMinutes() }_${ today.getSeconds()}`;
154
154
  }
155
155
 
156
+ /**
157
+ * @param {Object} test - Test adapter object
158
+ *
159
+ * @returns {String|null} testInfo as one string
160
+ */
161
+ const specificTestInfo = test => {
162
+ // TODO: afterEach has another context.... need to add specific handler, maybe...
163
+ if (test?.title && test?.file) {
164
+
165
+ return `${basename(test.file).split(".").join("#")
166
+ }#${
167
+ test.title.split(" ").join("#")}`;
168
+ }
169
+
170
+ return null;
171
+ };
172
+
156
173
  module.exports = {
157
- parseTest,
158
- parseSuite,
159
- ansiRegExp,
160
174
  isSameTest,
161
- isValidUrl,
162
175
  fetchSourceCode,
163
176
  fetchSourceCodeFromStackTrace,
164
177
  fetchFilesFromStackTrace,
165
- getCurrentDateTime
166
- };
178
+ getCurrentDateTime,
179
+ specificTestInfo,
180
+ isValidUrl,
181
+ ansiRegExp,
182
+ parseTest,
183
+ parseSuite
184
+ }
package/lib/xmlReader.js CHANGED
@@ -2,15 +2,14 @@ const debug = require('debug')('@testomatio/reporter:xml');
2
2
  const path = require("path");
3
3
  const chalk = require('chalk');
4
4
  const fs = require("fs");
5
-
6
- // const util = require("util"); // you can see a result
7
5
  const { XMLParser } = require("fast-xml-parser");
8
- const { APP_PREFIX, PASSED, FAILED, SKIPPED } = require('./constants');
6
+ const { APP_PREFIX, STATUS } = require('./constants');
9
7
  const { fetchFilesFromStackTrace, fetchSourceCode, fetchSourceCodeFromStackTrace } = require('./util');
10
8
  const upload = require('./fileUploader');
11
9
  const pipesFactory = require('./pipe');
12
10
  const adapterFactory = require('./junit-adapter');
13
11
 
12
+
14
13
  const TESTOMATIO_URL = process.env.TESTOMATIO_URL || "https://app.testomat.io";
15
14
  const TESTOMATIO = process.env.TESTOMATIO; // key?
16
15
  const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } = process.env;
@@ -37,7 +36,9 @@ class XmlReader {
37
36
  };
38
37
  this.runId = opts.runId || TESTOMATIO_RUN;
39
38
  this.adapter = adapterFactory(null, opts)
40
- this.opts = opts;
39
+ if (!this.adapter) throw new Error('XML adapter for this format not found');
40
+
41
+ this.opts = opts || {};
41
42
  const store = {}
42
43
  this.pipes = pipesFactory(opts, store);
43
44
 
@@ -93,7 +94,7 @@ class XmlReader {
93
94
  create_tests: true,
94
95
  name,
95
96
  tests_count: parseInt(tests, 10),
96
- passed_count: parseInt(tests - failures, 10),
97
+ passed_count: parseInt(tests, 10) - parseInt(failures, 10),
97
98
  failed_count: parseInt(failures, 10),
98
99
  skipped_count: 0,
99
100
  tests: resultTests,
@@ -127,12 +128,13 @@ class XmlReader {
127
128
  const title = td.name.replace(/\(.*?\)/, '').trim();
128
129
  let example = td.name.match(/\((.*?)\)/);
129
130
  if (example) example = { ...example[1].split(',')};
130
- const suite = td.TestMethod.className.split('.');
131
+ const suite = td.TestMethod.className.split(', ')[0].split('.');
131
132
  const suite_title = suite.pop();
132
133
  return {
133
134
  title,
134
135
  example,
135
136
  file: suite.join('/'),
137
+ description: td.Description,
136
138
  suite_title,
137
139
  id: td.Execution.id,
138
140
  }
@@ -154,12 +156,14 @@ class XmlReader {
154
156
  const test = tests.find(t => t.id === r.id) || { };
155
157
  r.suite_title = test.suite_title;
156
158
  r.title = test.title?.trim();
159
+ if (test.code) r.code = test.code;
160
+ if (test.description) r.description = test.description;
157
161
  if (test.example) r.example = test.example;
158
162
  if (test.file) r.file = test.file;
159
163
  r.create = true;
160
- if (r.status === 'Passed') r.status = PASSED;
161
- if (r.status === 'Failed') r.status = FAILED;
162
- if (r.status === 'Skipped') r.status = SKIPPED;
164
+ if (r.status === 'Passed') r.status = STATUS.PASSED;
165
+ if (r.status === 'Failed') r.status = STATUS.FAILED;
166
+ if (r.status === 'Skipped') r.status = STATUS.SKIPPED;
163
167
  delete r.id;
164
168
  });
165
169
 
@@ -169,8 +173,8 @@ class XmlReader {
169
173
 
170
174
  const failed_count = parseInt(counters.failed, 10) + parseInt(counters.error, 10);
171
175
 
172
- let status = PASSED;
173
- if (failed_count > 0) status = FAILED;
176
+ let status = STATUS.PASSED.toString();
177
+ if (failed_count > 0) status = STATUS.FAILED;
174
178
 
175
179
  this.tests = results.filter(t => !!t.title);
176
180
 
@@ -310,7 +314,7 @@ class XmlReader {
310
314
  const dataString = {
311
315
  ...this.stats,
312
316
  api_key: this.requestParams.apiKey,
313
- status_event: 'finish',
317
+ status: 'finished',
314
318
  tests: this.tests,
315
319
  };
316
320
 
@@ -345,9 +349,9 @@ function reduceTestCases(prev, item) {
345
349
  // prepend system output
346
350
  stack = `${testCaseItem['system-out'] || testCaseItem.output || testCaseItem.log || ''}\n\n${stack}`.trim()
347
351
 
348
- let status = PASSED;
349
- if ('failure' in testCaseItem || 'error' in testCaseItem) status = FAILED;
350
- if ('skipped' in testCaseItem) status = SKIPPED;
352
+ let status = STATUS.PASSED.toString();
353
+ if ('failure' in testCaseItem || 'error' in testCaseItem) status = STATUS.FAILED;
354
+ if ('skipped' in testCaseItem) status = STATUS.SKIPPED;
351
355
 
352
356
  prev.push({
353
357
  create: true,
package/package.json CHANGED
@@ -1,20 +1,23 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "0.8.0-beta.30",
3
+ "version": "0.8.0-beta.32",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "main": "./lib/reporter.js",
6
+ "typings": "typings/index.d.ts",
6
7
  "repository": "git@github.com:testomatio/reporter.git",
7
8
  "author": "Michael Bodnarchuk <davert@testomat.io>,Koushik Mohan <koushikmohan1996@gmail.com>",
8
9
  "license": "MIT",
9
10
  "dependencies": {
10
- "@octokit/rest": "^19.0.5",
11
- "aws-sdk": "^2.1072.0",
12
11
  "@aws-sdk/client-s3": "^3.279.0",
13
12
  "@aws-sdk/lib-storage": "^3.279.0",
13
+ "@octokit/rest": "^19.0.5",
14
+ "aws-sdk": "^2.1072.0",
14
15
  "axios": "^0.25.0",
15
16
  "callsite-record": "^4.1.4",
16
17
  "chalk": "^4.1.0",
17
18
  "commander": "^4.1.1",
19
+ "csv-writer": "^1.6.0",
20
+ "debug": "^4.3.4",
18
21
  "dotenv": "^16.0.1",
19
22
  "fast-xml-parser": "^4.0.8",
20
23
  "glob": "^8.0.3",
@@ -24,7 +27,7 @@
24
27
  "json-cycle": "^1.3.0",
25
28
  "lodash.memoize": "^4.1.2",
26
29
  "lodash.merge": "^4.6.2",
27
- "csv-writer": "^1.6.0"
30
+ "uuid": "^9.0.0"
28
31
  },
29
32
  "files": [
30
33
  "bin",
@@ -49,6 +52,7 @@
49
52
  },
50
53
  "devDependencies": {
51
54
  "@cucumber/cucumber": "^8.6.0",
55
+ "@redocly/cli": "^1.0.0-beta.125",
52
56
  "@wdio/reporter": "^7.16.13",
53
57
  "chai": "^4.3.6",
54
58
  "codeceptjs": "^3.2.3",