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

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.
package/README.md CHANGED
@@ -37,7 +37,7 @@ You can verify installed packages via `npm list` or `npm list -g`.
37
37
 
38
38
  ### CodeceptJS
39
39
 
40
- Make sure you load all your tests using [check-test](https://github.com/testomatio/check-tests#cli).
40
+ Make sure you load all your tests using [check-tests](https://github.com/testomatio/check-tests#cli).
41
41
 
42
42
  Add plugin to [codecept conf](https://github.com/testomatio/reporter/blob/master/example/codecept/codecept.conf.js#L23):
43
43
 
@@ -94,7 +94,7 @@ TESTOMATIO={API_KEY} npx playwright test
94
94
 
95
95
  ### Mocha
96
96
 
97
- Load the test using using `check-test` if not done already. Get the test id from testomat account and add it to your mocha test like in this [example](https://github.com/testomatio/reporter/blob/master/example/mocha/test/index.test.js#L4).
97
+ Load the test using using `check-tests` if not done already. Get the test id from testomat account and add it to your mocha test like in this [example](https://github.com/testomatio/reporter/blob/master/example/mocha/test/index.test.js#L4).
98
98
 
99
99
  Run the following command from you project folder:
100
100
 
@@ -104,7 +104,7 @@ mocha --reporter ./node_modules/testomat-reporter/lib/adapter/mocha.js --reporte
104
104
 
105
105
  ### Jest
106
106
 
107
- Load the test using using `check-test`. Add the test id to your tests like in this [example](https://github.com/testomatio/reporter/blob/master/example/jest/index.test.js#L1).
107
+ Load the test using using `check-tests`. Add the test id to your tests like in this [example](https://github.com/testomatio/reporter/blob/master/example/jest/index.test.js#L1).
108
108
 
109
109
  Add the following line to [jest.config.js](https://github.com/testomatio/reporter/blob/master/example/jest/jest.config.js#L100):
110
110
 
@@ -126,7 +126,7 @@ TESTOMATIO={API_KEY} ./node_modules/.bin/cucumber-js --format ./node_modules/@te
126
126
 
127
127
  ### TestCafe
128
128
 
129
- Load the test using using `check-test`.
129
+ Load the test using using `check-tests`.
130
130
 
131
131
  Run the following command from you project folder:
132
132
 
@@ -138,14 +138,16 @@ TESTOMATIO={API_KEY} npx testcafe chrome -r testomatio
138
138
 
139
139
  Run collection and specify `testomatio` as reporter:
140
140
 
141
- `TESTOMATIO={API_KEY} npx newman run {collection_name.json} -r testomatio`
141
+ ```bash
142
+ TESTOMATIO={API_KEY} npx newman run {collection_name.json} -r testomatio
143
+ ```
142
144
 
143
- > _`check-test` not supported for newman for now, tests will be created on testomatio by default_
145
+ > _`check-tests` not supported for newman for now, tests will be created on testomatio by default_
144
146
 
145
147
 
146
148
  ### Cypress
147
149
 
148
- Load the test using using `check-test`.
150
+ Load the test using using `check-tests`.
149
151
 
150
152
  Register our `cypress-plugin` in `cypress/plugins/index.js`:
151
153
 
@@ -173,7 +175,7 @@ TESTOMATIO={API_KEY} npx cypress run
173
175
 
174
176
  ### Protractor
175
177
 
176
- Load the test using using `check-test`.
178
+ Load the test using using `check-tests`.
177
179
 
178
180
  Add the following lines to [conf.js](https://github.com/angular/protractor/blob/5.4.1/example/conf.js):
179
181
 
@@ -195,7 +197,7 @@ TESTOMATIO={API_KEY} npx start-test-run -c 'npx protractor conf.js'
195
197
 
196
198
  ### WebdriverIO
197
199
 
198
- Load the test using using `check-test`.
200
+ Load the test using using `check-tests`.
199
201
 
200
202
  Add the following lines to [wdio.conf.js](https://webdriver.io/docs/configurationfile/):
201
203
 
@@ -583,3 +585,8 @@ If you want to finish a run started by `--launch` use `--finish` option. `TESTOM
583
585
  ```bash
584
586
  TESTOMATIO={API_KEY} TESTOMATIO_RUN={RUN_ID} npx start-test-run --finish
585
587
  ```
588
+
589
+ ### Debug logs
590
+ Pass `DEBUG` variable with module name e.g. `DEBUG=@testomatio/reporter:pipe:github`.
591
+ (Module name could be taken directly from the required module code).
592
+ To log all debug info pass `DEBUG=*`.
@@ -0,0 +1,132 @@
1
+ const debug = require('debug')('@testomatio/reporter:storage');
2
+ const { join, resolve } = require('path');
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const uuid = require('uuid');
6
+
7
+ const { TESTOMAT_ARTIFACT_SUFFIX } = require('./constants');
8
+ const { specificTestInfo } = require('./util');
9
+
10
+ class ArtifactStorage {
11
+ _tmpPrefix = "tsmt_reporter";
12
+
13
+ constructor(params) {
14
+ this.isFile = false;
15
+ this.isMemory = true;
16
+ this.storage = params?.toFile;
17
+
18
+ if (this.storage) {
19
+ this.isFile = true;
20
+ this.isMemory = false;
21
+ this.tmpDirFullpath = this.createTestomatTmpDir(this._tmpPrefix);
22
+ debug('SAVE to tmp folder mode enabled!');
23
+ }
24
+ }
25
+
26
+ static async storeToFile(tmpDirName, artifact, testSuffix = "test") {
27
+ const suffix = TESTOMAT_ARTIFACT_SUFFIX + uuid.v4() + testSuffix;
28
+ const dirpath = join(os.tmpdir(), tmpDirName);
29
+ const filepath = resolve(dirpath, suffix + ".json");
30
+
31
+ return await fs.promises.appendFile(filepath, JSON.stringify(artifact));
32
+ }
33
+
34
+ static async artifact(artifact, context) {
35
+ //TODO: mode for different pre-hooks. As variant - "all-tests" || "only_fail"
36
+ // const mode = process.env.TESTOMAT_ARTIFACTS || "only_fail";
37
+
38
+ if (Array.isArray(global.testomatioArtifacts)) {
39
+ debug("Saving artifacts to global storage");
40
+
41
+ global.testomatioArtifacts.push(artifact);
42
+ }
43
+
44
+ if (global?.testomatioArtifacts === undefined) {
45
+ const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
46
+
47
+ const testSuffix = specificTestInfo(context.test);
48
+
49
+ if (Array.isArray(tmpDirNames) && tmpDirNames.length) {
50
+ debug("Saving artifacts to memory tmp folder");
51
+
52
+ return await ArtifactStorage.storeToFile(tmpDirNames[tmpDirNames.length - 1], artifact, testSuffix);
53
+ }
54
+ }
55
+ }
56
+
57
+ async artifactByTestName(test) {
58
+ const list = [];
59
+
60
+ if (this.isFile && this.tmpDirFullpath) {
61
+ const files = fs.readdirSync(this.tmpDirFullpath);
62
+
63
+ for (const file of files) {
64
+ if (file.includes(test)) {
65
+ const buff = await fs.promises.readFile(this.tmpDirFullpath + "/" + file);
66
+
67
+ list.push(JSON.parse(buff.toString()));
68
+ }
69
+ }
70
+ }
71
+
72
+ return list;
73
+ }
74
+
75
+ async tmpContents() {
76
+ const contents = [];
77
+
78
+ if (this.isFile && this.tmpDirFullpath) {
79
+ const files = fs.readdirSync(this.tmpDirFullpath);
80
+
81
+ for (const file of files) {
82
+ const buff = await fs.promises.readFile(this.tmpDirFullpath + "/" + file);
83
+ const content = buff.toString();
84
+
85
+ contents.push(content);
86
+ }
87
+ }
88
+
89
+ return contents;
90
+ }
91
+
92
+ createTestomatTmpDir(clientPrefix) {
93
+ return fs.mkdtempSync(join(os.tmpdir(), clientPrefix));
94
+ }
95
+
96
+ clearTmpDirByName(name) {
97
+ const tmpDirPath = join(os.tmpdir(), name);
98
+
99
+ if (fs.existsSync(tmpDirPath)) {
100
+ fs.rmSync(tmpDirPath, { recursive: true });
101
+ debug(` Testomat tmpDir = ${tmpDirPath} was deleted successfully!`);
102
+
103
+ return;
104
+ }
105
+ }
106
+
107
+ static tmpTestomatDirNames() {
108
+ const subname = this._tmpPrefix || "tsmt_reporter";
109
+
110
+ return fs.readdirSync(os.tmpdir(), { withFileTypes: true })
111
+ .filter((item) => item.isDirectory())
112
+ .map((item) => item.name)
113
+ .filter((name) => name.includes(subname));
114
+ }
115
+
116
+ cleanup() {
117
+ if (this.isFile && this.tmpDirFullpath) {
118
+ const tmpDirNames = ArtifactStorage.tmpTestomatDirNames();
119
+
120
+ if (Array.isArray(tmpDirNames) && tmpDirNames.length) {
121
+ for (const name of tmpDirNames) {
122
+ this.clearTmpDirByName(name);
123
+ }
124
+ }
125
+ }
126
+ else {
127
+ debug("The tmp folder has not been created! Nothing to delete");
128
+ }
129
+ }
130
+ }
131
+
132
+ module.exports = ArtifactStorage;
@@ -1,36 +1,58 @@
1
1
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
2
+ const debug = require('debug')('@testomatio/reporter:adapter:mocha');
2
3
  const Mocha = require('mocha');
3
4
  const chalk = require('chalk');
4
5
  const TestomatClient = require('../client');
5
6
  const TRConstants = require('../constants');
6
- const { parseTest } = require('../util');
7
+ const { parseTest, specificTestInfo } = require('../util');
8
+ const ArtifactStorage = require('../ArtifactStorage');
7
9
 
8
10
  const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } = Mocha.Runner.constants;
9
11
 
10
12
  function MochaReporter(runner, opts) {
11
13
  Mocha.reporters.Base.call(this, runner);
12
- let passes = 0; let failures = 0; let skipped = 0; // eslint-disable-line no-unused-vars
14
+ let passes = 0; let failures = 0; let skipped = 0;
15
+ let artifactStore;
13
16
 
14
17
  const apiKey = opts?.reporterOptions?.apiKey || process.env.TESTOMATIO;
15
18
 
16
19
  if (!apiKey) {
17
- console.log('TESTOMATIO key is empty, ignoring reports');
20
+ debug('TESTOMATIO key is empty, ignoring reports');
18
21
  return;
19
22
  }
20
23
  const client = new TestomatClient({ apiKey });
21
24
 
22
25
  runner.on(EVENT_RUN_BEGIN, () => {
23
26
  client.createRun();
27
+
28
+ const params = {
29
+ "toFile": true
30
+ };
31
+
32
+ (runner._workerReporter !== undefined)
33
+ ? artifactStore = new ArtifactStorage(params)
34
+ : artifactStore = new ArtifactStorage();
24
35
  });
25
36
 
26
- runner.on(EVENT_TEST_PASS, test => {
37
+ runner.on(EVENT_TEST_PASS, async(test) => {
27
38
  passes += 1;
28
39
  console.log(chalk.bold.green('✔'), test.fullTitle());
29
40
  const testId = parseTest(test.title);
30
- client.addTestRun(testId, TRConstants.PASSED, {
31
- title: test.title,
32
- time: test.duration,
33
- });
41
+
42
+ const specificTest = specificTestInfo(test);
43
+ const content = await artifactStore.artifactByTestName(specificTest);
44
+
45
+ debug(`test=${specificTest} content = `, content);
46
+
47
+ client.addTestRun(
48
+ testId,
49
+ TRConstants.PASSED,
50
+ {
51
+ title: test.title,
52
+ time: test.duration,
53
+ },
54
+ content
55
+ );
34
56
  });
35
57
 
36
58
  runner.on(EVENT_TEST_PENDING, test => {
@@ -43,21 +65,33 @@ function MochaReporter(runner, opts) {
43
65
  });
44
66
  });
45
67
 
46
- runner.on(EVENT_TEST_FAIL, (test, err) => {
68
+ runner.on(EVENT_TEST_FAIL, async(test, err) => {
47
69
  failures += 1;
48
70
  console.log(chalk.bold.red('✖'), test.fullTitle(), chalk.gray(err.message));
49
71
  const testId = parseTest(test.title);
50
- client.addTestRun(testId, TRConstants.FAILED, {
51
- error: err,
52
- title: test.title,
53
- time: test.duration,
54
- });
72
+
73
+ const specificTest = specificTestInfo(test);
74
+ const content = await artifactStore.artifactByTestName(specificTest);
75
+
76
+ debug(`fail test=${specificTest} content = `, content);
77
+
78
+ client.addTestRun(
79
+ testId,
80
+ TRConstants.FAILED, {
81
+ error: err,
82
+ title: test.title,
83
+ time: test.duration,
84
+ },
85
+ content
86
+ );
55
87
  });
56
88
 
57
89
  runner.on(EVENT_RUN_END, () => {
58
90
  const status = failures === 0 ? TRConstants.PASSED : TRConstants.FAILED;
59
- console.log(chalk.bold(status), `${passes} passed, ${failures} failed`);
91
+ console.log(chalk.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
60
92
  client.updateRunStatus(status);
93
+
94
+ artifactStore.cleanup();
61
95
  });
62
96
  }
63
97
 
package/lib/client.js CHANGED
@@ -1,3 +1,4 @@
1
+ const debug = require('debug')('@testomatio/reporter:client');
1
2
  const createCallsiteRecord = require('callsite-record');
2
3
  const { sep, join } = require('path');
3
4
  const fs = require('fs');
@@ -48,7 +49,7 @@ class TestomatClient {
48
49
  this.queue = this.queue
49
50
  .then(() => Promise.all(this.pipes.map(p => p.createRun(runParams))))
50
51
  .catch(err => console.log(APP_PREFIX, err));
51
-
52
+ debug('Run', this.queue);
52
53
  return this.queue;
53
54
  }
54
55
 
@@ -57,7 +58,7 @@ class TestomatClient {
57
58
  *
58
59
  * @returns {Promise}
59
60
  */
60
- async addTestRun(testId, status, testData = {}) {
61
+ async addTestRun(testId, status, testData = {}, storeArtifacts = []) {
61
62
  // all pipes disabled, skipping
62
63
  if (!this.pipes.filter(p => p.isEnabled).length) return;
63
64
 
@@ -68,6 +69,7 @@ class TestomatClient {
68
69
  files = [],
69
70
  filesBuffers = [],
70
71
  steps,
72
+ code = null,
71
73
  title,
72
74
  suite_title,
73
75
  suite_id,
@@ -89,7 +91,13 @@ class TestomatClient {
89
91
  stack = this.formatSteps(stack, steps);
90
92
  }
91
93
 
94
+ if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
95
+ debug("CLIENT storeArtefact", storeArtifacts);
96
+ files.push(...storeArtifacts);
97
+ }
98
+
92
99
  if (Array.isArray(global.testomatioArtifacts)) {
100
+ debug("CLIENT global[testomatioArtifacts]", global.testomatioArtifacts);
93
101
  files.push(...global.testomatioArtifacts);
94
102
  global.testomatioArtifacts = [];
95
103
  }
@@ -115,6 +123,7 @@ class TestomatClient {
115
123
  status,
116
124
  stack,
117
125
  example,
126
+ code,
118
127
  title,
119
128
  suite_title,
120
129
  suite_id,
@@ -148,16 +157,20 @@ class TestomatClient {
148
157
 
149
158
  this.queue = this.queue
150
159
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
160
+ .then(() => {
161
+ debug("TOTAL uploaded files", this.totalUploaded);
162
+
163
+ if (upload.isArtifactsEnabled() && this.totalUploaded > 0) {
164
+ console.log(
165
+ APP_PREFIX,
166
+ `🗄️ Total ${this.totalUploaded} artifacts ${
167
+ process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
168
+ } uploaded to S3 bucket `,
169
+ );
170
+ }
171
+ })
151
172
  .catch(err => console.log(APP_PREFIX, err));
152
173
 
153
- if (upload.isArtifactsEnabled() && this.totalUploaded > 0) {
154
- console.log(
155
- APP_PREFIX,
156
- `🗄️ Total ${this.totalUploaded} artifacts ${
157
- process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
158
- } uploaded to S3 bucket `,
159
- );
160
- }
161
174
  return this.queue;
162
175
  }
163
176
 
package/lib/constants.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const chalk = require('chalk');
2
2
 
3
3
  const APP_PREFIX = chalk.gray('[TESTOMATIO]');
4
+ const TESTOMAT_ARTIFACT_SUFFIX = "testomatio_artifact_";
4
5
 
5
6
  const CSV_HEADERS = [
6
7
  { id: 'suite_title', title: 'Suite_title' },
@@ -16,5 +17,6 @@ module.exports = Object.freeze({
16
17
  SKIPPED: 'skipped',
17
18
  FINISHED: 'finished',
18
19
  APP_PREFIX,
19
- CSV_HEADERS
20
+ CSV_HEADERS,
21
+ TESTOMAT_ARTIFACT_SUFFIX
20
22
  });
@@ -1,4 +1,4 @@
1
- const debug = require('debug')('@testomatio/reporter:upload');
1
+ const debug = require('debug')('@testomatio/reporter:file-uploader');
2
2
  const { S3 } = require('@aws-sdk/client-s3');
3
3
  const { Upload } = require("@aws-sdk/lib-storage");
4
4
  const fs = require('fs');
@@ -88,7 +88,9 @@ const uploadUsingS3 = async (filePath, runId) => {
88
88
  return;
89
89
  }
90
90
 
91
- const { S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, TESTOMATIO_PRIVATE_ARTIFACTS, S3_BUCKET } = getConfig();
91
+ const {
92
+ S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, TESTOMATIO_PRIVATE_ARTIFACTS, S3_BUCKET
93
+ } = getConfig();
92
94
 
93
95
  const file = fs.readFileSync(filePath);
94
96
 
@@ -139,7 +141,9 @@ const uploadUsingS3 = async (filePath, runId) => {
139
141
 
140
142
  const uploadUsingS3AsBuffer = async (buffer, fileName, runId) => {
141
143
 
142
- const { S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, TESTOMATIO_PRIVATE_ARTIFACTS, S3_BUCKET } = getConfig();
144
+ const {
145
+ S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, TESTOMATIO_PRIVATE_ARTIFACTS, S3_BUCKET
146
+ } = getConfig();
143
147
 
144
148
  const ACL = TESTOMATIO_PRIVATE_ARTIFACTS ? 'private' : 'public-read';
145
149
 
package/lib/pipe/csv.js CHANGED
@@ -1,3 +1,4 @@
1
+ const debug = require('debug')('@testomatio/reporter:pipe:csv');
1
2
  const path = require('path');
2
3
  const fs = require('fs');
3
4
  const csvWriter = require('csv-writer');
@@ -54,6 +55,7 @@ class CsvPipe {
54
55
  * @param {Object} headers - csv file headers. Example: [{ id: 'suite_title', title: 'Suite_title' }]
55
56
  */
56
57
  async saveToCsv(data, headers) {
58
+ debug('Data', data);
57
59
  // First, we check whether the export directory exists: if yes - OK, no - create it.
58
60
  this.checkExportDir();
59
61
 
@@ -1,3 +1,4 @@
1
+ const debug = require('debug')('@testomatio/reporter:pipe:github');
1
2
  const path = require('path');
2
3
  const chalk = require('chalk');
3
4
  const humanizeDuration = require('humanize-duration');
@@ -16,9 +17,7 @@ class GitHubPipe {
16
17
  this.repo = process.env.GITHUB_REPOSITORY;
17
18
  this.hiddenCommentData = `<!--- testomat.io report ${process.env.GITHUB_WORKFLOW || ''} -->`;
18
19
 
19
- if (process.env.DEBUG) {
20
- console.log(APP_PREFIX, 'GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', this.ref, this.repo);
21
- }
20
+ debug('GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', 'Ref:', this.ref, 'Repo:', this.repo);
22
21
 
23
22
  if (!this.token || !this.ref || !this.repo) return;
24
23
  this.isEnabled = true;
@@ -27,9 +26,7 @@ class GitHubPipe {
27
26
  this.issue = matchedIssue[1];
28
27
  this.start = new Date();
29
28
 
30
- if (process.env.DEBUG) {
31
- console.log(APP_PREFIX, 'GitHub Pipe: Enabled');
32
- }
29
+ debug('GitHub Pipe: Enabled');
33
30
  }
34
31
 
35
32
  async createRun() {}
@@ -37,6 +34,7 @@ class GitHubPipe {
37
34
  updateRun() {}
38
35
 
39
36
  addTest(test) {
37
+ debug('Adding test:', test);
40
38
  if (!this.isEnabled) return;
41
39
 
42
40
  const index = this.tests.findIndex(t => isSameTest(t, test));
@@ -69,7 +67,7 @@ class GitHubPipe {
69
67
  let summary = `${this.hiddenCommentData}
70
68
 
71
69
  | [![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)} |
70
+ statusEmoji(runParams.status,)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
73
71
  | --- | --- |
74
72
  | Tests | ✔️ **${this.tests.length}** tests run |
75
73
  | Summary | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji(
@@ -155,6 +153,7 @@ class GitHubPipe {
155
153
 
156
154
  // add report as comment
157
155
  try {
156
+ debug('Adding comment\n', body);
158
157
  const resp = await this.octokit.rest.issues.createComment({
159
158
  owner,
160
159
  repo,
@@ -163,6 +162,7 @@ class GitHubPipe {
163
162
  });
164
163
 
165
164
  const url = resp.data?.html_url;
165
+ debug('Comment URL:', url);
166
166
  this.store.githubUrl = url;
167
167
 
168
168
  console.log(APP_PREFIX, chalk.yellow('GitHub'), `Report created: ${chalk.magenta(url)}`);
@@ -221,7 +221,7 @@ async function deletePreviousReport(octokit, owner, repo, issue, hiddenCommentDa
221
221
  comment_id: comment.id,
222
222
  });
223
223
  } catch (e) {
224
- console.error(`Can't delete previously added comment with testomat.io report. Ignore.`);
224
+ console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
225
225
  }
226
226
 
227
227
  // pass next env var if need to clear all previous reports;
@@ -1,3 +1,4 @@
1
+ const debug = require('debug')('@testomatio/reporter:pipe:gitlab');
1
2
  const axios = require('axios');
2
3
  const chalk = require('chalk');
3
4
  const humanizeDuration = require('humanize-duration');
@@ -20,30 +21,25 @@ class GitLabPipe {
20
21
  this.hiddenCommentData = `<!--- testomat.io report ${process.env.CI_JOB_NAME || ''} -->`;
21
22
  this.axios = axios.create();
22
23
 
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
- }
24
+ debug(
25
+ chalk.yellow('GitLab Pipe:'),
26
+ this.token ? 'TOKEN passed' : '*no token*',
27
+ `Project id: ${this.ENV.CI_PROJECT_ID}, MR id: ${this.ENV.CI_MERGE_REQUEST_IID}`,
28
+ );
31
29
 
32
30
  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.`);
31
+ debug(`CI pipeline should be run in Merge Request to have ability to add the report comment.`);
34
32
  return;
35
33
  }
36
34
 
37
35
  if (!this.token) {
38
- console.warn(chalk.grey(`Hint: GitLab CI variables are unavailable for unprotected branches by default.`));
36
+ debug(`Hint: GitLab CI variables are unavailable for unprotected branches by default.`);
39
37
  return;
40
38
  }
41
39
 
42
40
  this.isEnabled = true;
43
41
 
44
- if (this.ENV.DEBUG) {
45
- console.log(APP_PREFIX, chalk.yellow('GitLab Pipe: Enabled'));
46
- }
42
+ debug('GitLab Pipe: Enabled');
47
43
  }
48
44
 
49
45
  async createRun() {}
@@ -75,8 +71,7 @@ class GitLabPipe {
75
71
  let summary = `${this.hiddenCommentData}
76
72
 
77
73
  | [![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)} |
74
+ statusEmoji(runParams.status)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
80
75
  | --- | --- |
81
76
  | Tests | ✔️ **${this.tests.length}** tests run |
82
77
  | Summary | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji(
@@ -86,8 +81,8 @@ class GitLabPipe {
86
81
  `;
87
82
 
88
83
  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}** | `;
84
+ // eslint-disable-next-line max-len
85
+ 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
86
  }
92
87
 
93
88
  const failures = this.tests
@@ -150,7 +145,8 @@ class GitLabPipe {
150
145
  await deletePreviousReport(this.axios, commentsRequestURL, this.hiddenCommentData, this.token);
151
146
 
152
147
  // add current report
153
- console.info(chalk.grey(`Adding comment via url: ${commentsRequestURL}`));
148
+ debug(`Adding comment via url: ${commentsRequestURL}`);
149
+
154
150
  try {
155
151
  const addCommentResponse = await this.axios.post(`${commentsRequestURL}?access_token=${this.token}`, { body });
156
152
 
@@ -160,7 +156,7 @@ class GitLabPipe {
160
156
 
161
157
  console.log(APP_PREFIX, chalk.yellow('GitLab'), `Report created: ${chalk.magenta(commentURL)}`);
162
158
  } catch (err) {
163
- console.log(
159
+ console.error(
164
160
  APP_PREFIX,
165
161
  chalk.yellow('GitLab'),
166
162
  `Couldn't create GitLab report\n${err}.
@@ -215,7 +211,7 @@ async function deletePreviousReport(axiosInstance, commentsRequestURL, hiddenCom
215
211
  const deleteCommentURL = `${commentsRequestURL}/${comment.id}?access_token=${token}`;
216
212
  await axiosInstance.delete(deleteCommentURL);
217
213
  } catch (e) {
218
- console.error(`Can't delete previously added comment with testomat.io report. Ignore.`);
214
+ console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
219
215
  }
220
216
 
221
217
  // pass next env var if need to clear all previous reports;
@@ -1,3 +1,4 @@
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');
@@ -6,25 +7,21 @@ const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_RUN } = process.env;
6
7
  const { APP_PREFIX } = require('../constants');
7
8
  const { isValidUrl } = require('../util');
8
9
 
10
+
9
11
  if (TESTOMATIO_RUN) {
10
12
  process.env.runId = TESTOMATIO_RUN;
11
13
  }
12
14
 
13
15
  class TestomatioPipe {
14
-
15
- constructor(params, store = {}) {
16
+ constructor(params, store = {}) {
16
17
  this.isEnabled = false;
17
18
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
18
19
  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
- }
20
+ debug('Testomatio Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
22
21
  if (!this.apiKey) {
23
22
  return;
24
23
  }
25
- if (process.env.DEBUG) {
26
- console.log(APP_PREFIX, 'Testomatio Pipe: Enabled');
27
- }
24
+ debug('Testomatio Pipe: Enabled');
28
25
  this.store = store;
29
26
  this.title = params.title || process.env.TESTOMATIO_TITLE;
30
27
  this.axios = axios.create();
@@ -35,11 +32,7 @@ class TestomatioPipe {
35
32
 
36
33
  if (!isValidUrl(this.url.trim())) {
37
34
  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
-
35
+ console.error(APP_PREFIX, chalk.red(`Error creating report on Testomat.io, report url '${this.url}' is invalid`));
43
36
  }
44
37
  }
45
38
 
@@ -48,47 +41,46 @@ class TestomatioPipe {
48
41
 
49
42
  runParams.api_key = this.apiKey.trim();
50
43
  runParams.group_title = TESTOMATIO_RUNGROUP_TITLE;
51
-
44
+
52
45
  if (this.runId) {
53
- return this.axios.put(`${this.url.trim()}/api/reporter/${this.runId}`, runParams)
46
+ return this.axios.put(`${this.url.trim()}/api/reporter/${this.runId}`, runParams);
54
47
  }
55
-
48
+
56
49
  try {
57
50
  const resp = await this.axios.post(`${this.url.trim()}/api/reporter`, runParams, {
58
51
  maxContentLength: Infinity,
59
52
  maxBodyLength: Infinity,
60
- })
53
+ });
61
54
  this.runId = resp.data.uid;
62
55
  this.runUrl = `${this.url}/${resp.data.url.split('/').splice(3).join('/')}`;
63
56
  this.store.runUrl = this.runUrl;
64
- this.store.runId = this.runId;
57
+ this.store.runId = this.runId;
65
58
  console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId);
66
59
  process.env.runId = this.runId;
67
60
  } catch (err) {
68
- console.log(
61
+ console.error(
69
62
  APP_PREFIX,
70
63
  'Error creating Testomat.io report, please check if your API key is valid. Skipping report',
71
64
  );
72
65
  }
73
66
  }
74
67
 
75
- async addTest(data) {
68
+ addTest(data) {
76
69
  if (!this.isEnabled) return;
77
70
  if (!this.runId) return;
78
71
  data.api_key = this.apiKey;
79
72
  data.create = this.createNewTests;
80
73
  const json = JsonCycle.stringify(data);
81
74
 
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) {
75
+ return this.axios.post(`${this.url}/api/reporter/${this.runId}/testrun`, json, {
76
+ maxContentLength: Infinity,
77
+ maxBodyLength: Infinity,
78
+ headers: {
79
+ // Overwrite Axios's automatically set Content-Type
80
+ 'Content-Type': 'application/json',
81
+ },
82
+ })
83
+ .catch((err) => {
92
84
  if (err.response) {
93
85
  if (err.response.status >= 400) {
94
86
  const responseData = err.response.data || { message: '' };
@@ -103,8 +95,7 @@ class TestomatioPipe {
103
95
  } else {
104
96
  console.log(APP_PREFIX, chalk.blue(this.title), "Report couldn't be processed", err);
105
97
  }
106
- }
107
-
98
+ });
108
99
  }
109
100
 
110
101
  async finishRun(params) {
@@ -136,4 +127,4 @@ class TestomatioPipe {
136
127
  }
137
128
  }
138
129
 
139
- module.exports = TestomatioPipe;
130
+ 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');
@@ -153,6 +153,23 @@ const getCurrentDateTime = () => {
153
153
  today.getHours() }_${ today.getMinutes() }_${ today.getSeconds()}`;
154
154
  }
155
155
 
156
+ /**
157
+ * @param {String} test - Test adapter object
158
+ *
159
+ * @returns {String} 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
174
  parseTest,
158
175
  parseSuite,
@@ -162,5 +179,6 @@ module.exports = {
162
179
  fetchSourceCode,
163
180
  fetchSourceCodeFromStackTrace,
164
181
  fetchFilesFromStackTrace,
165
- getCurrentDateTime
182
+ getCurrentDateTime,
183
+ specificTestInfo
166
184
  };
package/lib/xmlReader.js CHANGED
@@ -127,12 +127,13 @@ class XmlReader {
127
127
  const title = td.name.replace(/\(.*?\)/, '').trim();
128
128
  let example = td.name.match(/\((.*?)\)/);
129
129
  if (example) example = { ...example[1].split(',')};
130
- const suite = td.TestMethod.className.split('.');
130
+ const suite = td.TestMethod.className.split(', ')[0].split('.');
131
131
  const suite_title = suite.pop();
132
132
  return {
133
133
  title,
134
134
  example,
135
135
  file: suite.join('/'),
136
+ description: td.Description,
136
137
  suite_title,
137
138
  id: td.Execution.id,
138
139
  }
@@ -154,6 +155,8 @@ class XmlReader {
154
155
  const test = tests.find(t => t.id === r.id) || { };
155
156
  r.suite_title = test.suite_title;
156
157
  r.title = test.title?.trim();
158
+ if (test.code) r.code = test.code;
159
+ if (test.description) r.description = test.description;
157
160
  if (test.example) r.example = test.example;
158
161
  if (test.file) r.file = test.file;
159
162
  r.create = true;
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "0.8.0-beta.30",
3
+ "version": "0.8.0-beta.31",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "main": "./lib/reporter.js",
6
6
  "repository": "git@github.com:testomatio/reporter.git",
7
7
  "author": "Michael Bodnarchuk <davert@testomat.io>,Koushik Mohan <koushikmohan1996@gmail.com>",
8
8
  "license": "MIT",
9
9
  "dependencies": {
10
- "@octokit/rest": "^19.0.5",
11
- "aws-sdk": "^2.1072.0",
12
10
  "@aws-sdk/client-s3": "^3.279.0",
13
11
  "@aws-sdk/lib-storage": "^3.279.0",
12
+ "@octokit/rest": "^19.0.5",
13
+ "aws-sdk": "^2.1072.0",
14
14
  "axios": "^0.25.0",
15
15
  "callsite-record": "^4.1.4",
16
16
  "chalk": "^4.1.0",
@@ -24,7 +24,8 @@
24
24
  "json-cycle": "^1.3.0",
25
25
  "lodash.memoize": "^4.1.2",
26
26
  "lodash.merge": "^4.6.2",
27
- "csv-writer": "^1.6.0"
27
+ "csv-writer": "^1.6.0",
28
+ "uuid": "^9.0.0"
28
29
  },
29
30
  "files": [
30
31
  "bin",