@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,63 +1,98 @@
1
1
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
2
2
  const Mocha = require('mocha');
3
+ const debug = require('debug')('@testomatio/reporter:adapter:mocha');
3
4
  const chalk = require('chalk');
4
5
  const TestomatClient = require('../client');
5
- const TRConstants = require('../constants');
6
- const { parseTest } = require('../util');
6
+ const { STATUS } = require('../constants');
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
+ artifactStore = runner._workerReporter !== undefined
33
+ ? new ArtifactStorage(params)
34
+ : 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
+ STATUS.PASSED,
49
+ {
50
+ test_id: testId,
51
+ title: test.title,
52
+ time: test.duration,
53
+ },
54
+ content
55
+ );
34
56
  });
35
57
 
36
58
  runner.on(EVENT_TEST_PENDING, test => {
37
59
  skipped += 1;
38
60
  console.log('skip: %s', test.fullTitle());
39
61
  const testId = parseTest(test.title);
40
- client.addTestRun(testId, TRConstants.SKIPPED, {
62
+ client.addTestRun(STATUS.SKIPPED, {
41
63
  title: test.title,
64
+ test_id: testId,
42
65
  time: test.duration,
43
66
  });
44
67
  });
45
68
 
46
- runner.on(EVENT_TEST_FAIL, (test, err) => {
69
+ runner.on(EVENT_TEST_FAIL, async(test, err) => {
47
70
  failures += 1;
48
71
  console.log(chalk.bold.red('✖'), test.fullTitle(), chalk.gray(err.message));
49
72
  const testId = parseTest(test.title);
50
- client.addTestRun(testId, TRConstants.FAILED, {
51
- error: err,
52
- title: test.title,
53
- time: test.duration,
54
- });
73
+
74
+ const specificTest = specificTestInfo(test);
75
+ const content = await artifactStore.artifactByTestName(specificTest);
76
+
77
+ debug(`fail test=${specificTest} content = `, content);
78
+
79
+ client.addTestRun(
80
+ STATUS.FAILED, {
81
+ error: err,
82
+ test_id: testId,
83
+ title: test.title,
84
+ time: test.duration,
85
+ },
86
+ content
87
+ );
55
88
  });
56
89
 
57
90
  runner.on(EVENT_RUN_END, () => {
58
- const status = failures === 0 ? TRConstants.PASSED : TRConstants.FAILED;
59
- console.log(chalk.bold(status), `${passes} passed, ${failures} failed`);
91
+ const status = failures === 0 ? STATUS.PASSED : STATUS.FAILED;
92
+ console.log(chalk.bold(status), `${passes} passed, ${failures} failed, ${skipped} skipped`);
60
93
  client.updateRunStatus(status);
94
+
95
+ artifactStore.cleanup();
61
96
  });
62
97
  }
63
98
 
@@ -3,11 +3,12 @@ const crypto = require('crypto');
3
3
  const os = require('os');
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
- const Status = require('../constants');
6
+ const { APP_PREFIX, STATUS: Status } = require('../constants');
7
7
  const TestomatioClient = require('../client');
8
8
  const upload = require('../fileUploader');
9
9
  const { parseTest } = require('../util');
10
10
 
11
+
11
12
  class TestomatioReporter {
12
13
  constructor(config = {}) {
13
14
  this.client = new TestomatioClient({ apiKey: config?.apiKey });
@@ -56,8 +57,9 @@ class TestomatioReporter {
56
57
  files.push({ path: fileName, type: attachment.contentType });
57
58
  }
58
59
 
59
- this.client.addTestRun(testId, checkStatus(result.status), {
60
+ this.client.addTestRun(checkStatus(result.status), {
60
61
  error,
62
+ test_id: testId,
61
63
  suite_title,
62
64
  title,
63
65
  files,
@@ -70,14 +72,15 @@ class TestomatioReporter {
70
72
  if (!this.client) return;
71
73
 
72
74
  if (this.videos.length && upload.isArtifactsEnabled()) {
73
- console.log(Status.APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
75
+ console.log(APP_PREFIX, `🎞️ Uploading ${this.videos.length} videos...`);
74
76
 
75
77
  const promises = [];
76
78
  for (const video of this.videos) {
77
79
  const { testId, title, attachment, suite_title } = video;
78
80
  const file = { path: attachment.path, title, type: attachment.contentType };
79
81
  promises.push(
80
- this.client.addTestRun(testId, undefined, {
82
+ this.client.addTestRun(undefined, {
83
+ test_id: testId,
81
84
  title,
82
85
  suite_title,
83
86
  files: [file],
@@ -43,9 +43,10 @@ class WebdriverReporter extends WDIOReporter {
43
43
  .filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
44
44
  .map(el => Buffer.from(el.result.value, 'base64'));
45
45
 
46
- await this.client.addTestRun(testId, state, {
46
+ await this.client.addTestRun(state, {
47
47
  error,
48
48
  title,
49
+ test_id: testId,
49
50
  time: duration,
50
51
  filesBuffers: screenshotsBuffers,
51
52
  });
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  const program = require("commander");
4
3
  const chalk = require("chalk");
5
4
  const glob = require('glob');
@@ -3,7 +3,7 @@ const { spawn } = require('child_process');
3
3
  const program = require('commander');
4
4
  const chalk = require('chalk');
5
5
  const TestomatClient = require('../client');
6
- const { APP_PREFIX, FINISHED } = require('../constants');
6
+ const { APP_PREFIX, STATUS } = require('../constants');
7
7
  const { version } = require('../../package.json');
8
8
 
9
9
  console.log(chalk.cyan.bold(` 🤩 Testomat.io Reporter v${version}`));
@@ -42,7 +42,7 @@ program
42
42
 
43
43
  const client = new TestomatClient({ apiKey });
44
44
 
45
- client.updateRunStatus(FINISHED, true).then(() => {
45
+ client.updateRunStatus(STATUS.FINISHED, true).then(() => {
46
46
  console.log(chalk.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
47
47
  process.exit(0);
48
48
  });
package/lib/client.js CHANGED
@@ -1,26 +1,28 @@
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');
4
5
  const chalk = require('chalk');
6
+ const { randomUUID } = require('crypto');
5
7
  const upload = require('./fileUploader');
6
- const { PASSED, FAILED, FINISHED, APP_PREFIX } = require('./constants');
8
+ const { APP_PREFIX } = require('./constants');
7
9
  const pipesFactory = require('./pipe');
8
10
 
9
- const { TESTOMATIO_ENV } = process.env;
11
+ /**
12
+ * @typedef {import('../types').TestData} TestData
13
+ * @typedef {import('../types').RunStatus} RunStatus
14
+ */
10
15
 
11
- class TestomatClient {
16
+ class Client {
12
17
  /**
13
18
  * Create a Testomat client instance
14
19
  *
15
20
  * @param {*} params
16
21
  */
17
22
  constructor(params = {}) {
18
- this.title = params.title || process.env.TESTOMATIO_TITLE;
19
- this.createNewTests = params.createNewTests ?? !!process.env.TESTOMATIO_CREATE;
20
- this.proceed = process.env.TESTOMATIO_PROCEED;
21
- this.env = TESTOMATIO_ENV;
22
23
  this.parallel = params.parallel;
23
24
  const store = {};
25
+ this.uuid = randomUUID();
24
26
  this.pipes = pipesFactory(params, store);
25
27
  this.queue = Promise.resolve();
26
28
  this.totalUploaded = 0;
@@ -31,11 +33,11 @@ class TestomatClient {
31
33
  /**
32
34
  * Used to create a new Test run
33
35
  *
34
- * @returns {Promise} - resolves to Run id which should be used to update / add test
36
+ * @returns {Promise<void>} - resolves to Run id which should be used to update / add test
35
37
  */
36
38
  createRun() {
37
39
  // all pipes disabled, skipping
38
- if (!this.pipes.filter(p => p.isEnabled).length) return;
40
+ if (!this.pipes.filter(p => p.isEnabled).length) return Promise.resolve();
39
41
 
40
42
  const runParams = {
41
43
  title: this.title,
@@ -47,27 +49,37 @@ class TestomatClient {
47
49
 
48
50
  this.queue = this.queue
49
51
  .then(() => Promise.all(this.pipes.map(p => p.createRun(runParams))))
50
- .catch(err => console.log(APP_PREFIX, err));
51
-
52
+ .catch(err => console.log(APP_PREFIX, err))
53
+ .then(() => undefined); // fixes return type
54
+ debug('Run', this.queue);
52
55
  return this.queue;
53
56
  }
54
57
 
55
58
  /**
56
- * Used to add a new test to Run instance
57
- *
58
- * @returns {Promise}
59
+ * Updates test status and its data
60
+ *
61
+ * @param {string|undefined} status
62
+ * @param {TestData} [testData]
63
+ * @param {string[]} [storeArtifacts]
64
+ * @returns {Promise<void>}
59
65
  */
60
- async addTestRun(testId, status, testData = {}) {
66
+ async addTestRun(status, testData, storeArtifacts = []) {
61
67
  // all pipes disabled, skipping
62
68
  if (!this.pipes.filter(p => p.isEnabled).length) return;
63
69
 
70
+ if (!testData) testData = {
71
+ title: 'Unknown test',
72
+ suite_title: 'Unknown suite',
73
+ }
74
+
64
75
  const {
65
- error = '',
76
+ error = null,
66
77
  time = '',
67
78
  example = null,
68
79
  files = [],
69
80
  filesBuffers = [],
70
81
  steps,
82
+ code = null,
71
83
  title,
72
84
  suite_title,
73
85
  suite_id,
@@ -77,30 +89,34 @@ class TestomatClient {
77
89
 
78
90
  const uploadedFiles = [];
79
91
 
80
- if (testId) testData.test_id = testId;
81
-
82
92
  let stack = '';
83
93
 
84
94
  if (error) {
85
- stack = this.formatError(error);
86
- message = error.message;
95
+ stack = this.formatError(error) || '';
96
+ message = error?.message;
87
97
  }
88
98
  if (steps) {
89
99
  stack = this.formatSteps(stack, steps);
90
100
  }
91
101
 
102
+ if (Array.isArray(storeArtifacts) && storeArtifacts.length) {
103
+ debug("CLIENT storeArtifact", storeArtifacts);
104
+ files.push(...storeArtifacts);
105
+ }
106
+
92
107
  if (Array.isArray(global.testomatioArtifacts)) {
108
+ debug("CLIENT global[testomatioArtifacts]", global.testomatioArtifacts);
93
109
  files.push(...global.testomatioArtifacts);
94
110
  global.testomatioArtifacts = [];
95
111
  }
96
112
 
97
113
  for (const file of files) {
98
- uploadedFiles.push(upload.uploadFileByPath(file, this.runId));
114
+ uploadedFiles.push(upload.uploadFileByPath(file, this.uuid));
99
115
  }
100
116
 
101
117
  for (const [idx, buffer] of filesBuffers.entries()) {
102
118
  const fileName = `${idx + 1}-${title.replace(/\s+/g, '-')}`;
103
- uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.runId));
119
+ uploadedFiles.push(upload.uploadFileAsBuffer(buffer, fileName, this.uuid));
104
120
  }
105
121
 
106
122
  const artifacts = await Promise.all(uploadedFiles);
@@ -115,6 +131,7 @@ class TestomatClient {
115
131
  status,
116
132
  stack,
117
133
  example,
134
+ code,
118
135
  title,
119
136
  suite_title,
120
137
  suite_id,
@@ -126,38 +143,40 @@ class TestomatClient {
126
143
 
127
144
  this.queue = this.queue
128
145
  .then(() => Promise.all(this.pipes.map(p => p.addTest(data))))
129
- .catch(err => console.log(APP_PREFIX, err));
146
+ .catch(err => console.log(APP_PREFIX, err))
147
+ .then(() => undefined);
130
148
  return this.queue;
131
149
  }
132
150
 
133
151
  /**
134
- * Update run status
135
152
  *
136
- * @returns {Promise}
153
+ * Updates the status of the current test run and finishes the run.
154
+ * @param {RunStatus} status - The status of the current test run. Must be one of "passed", "failed", or "finished"
155
+ * @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
156
+ * @returns {Promise<void>} - A Promise that resolves when finishes the run.
137
157
  */
138
- updateRunStatus(status, isParallel) {
158
+ updateRunStatus(status, isParallel = false) {
139
159
  // all pipes disabled, skipping
140
- if (!this.pipes.filter(p => p.isEnabled).length) return;
160
+ if (!this.pipes.filter(p => p.isEnabled).length) return Promise.resolve();
141
161
 
142
- let statusEvent;
143
- if (status === FINISHED) statusEvent = 'finish';
144
- if (status === PASSED) statusEvent = 'pass';
145
- if (status === FAILED) statusEvent = 'fail';
146
- if (isParallel) statusEvent += '_parallel';
147
- const runParams = { status, statusEvent };
162
+ const runParams = { status, parallel: isParallel };
148
163
 
149
164
  this.queue = this.queue
150
165
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
166
+ .then(() => {
167
+ debug("TOTAL uploaded files", this.totalUploaded);
168
+
169
+ if (upload.isArtifactsEnabled() && this.totalUploaded > 0) {
170
+ console.log(
171
+ APP_PREFIX,
172
+ `🗄️ Total ${this.totalUploaded} artifacts ${
173
+ process.env.TESTOMATIO_PRIVATE_ARTIFACTS ? 'privately' : chalk.bold('publicly')
174
+ } uploaded to S3 bucket `,
175
+ );
176
+ }
177
+ })
151
178
  .catch(err => console.log(APP_PREFIX, err));
152
179
 
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
180
  return this.queue;
162
181
  }
163
182
 
@@ -198,4 +217,4 @@ class TestomatClient {
198
217
  }
199
218
  }
200
219
 
201
- module.exports = TestomatClient;
220
+ module.exports = Client;
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' },
@@ -10,11 +11,16 @@ const CSV_HEADERS = [
10
11
  { id: 'stack', title: 'Stack' },
11
12
  ];
12
13
 
13
- module.exports = Object.freeze({
14
+ const STATUS = {
14
15
  PASSED: 'passed',
15
16
  FAILED: 'failed',
16
17
  SKIPPED: 'skipped',
17
18
  FINISHED: 'finished',
19
+ };
20
+
21
+ module.exports = {
18
22
  APP_PREFIX,
19
- CSV_HEADERS
20
- });
23
+ TESTOMAT_ARTIFACT_SUFFIX,
24
+ CSV_HEADERS,
25
+ STATUS,
26
+ }
@@ -1,6 +1,6 @@
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
- const { Upload } = require("@aws-sdk/lib-storage");
3
+ const { Upload } = require('@aws-sdk/lib-storage');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const chalk = require('chalk');
@@ -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
 
@@ -14,5 +14,4 @@ class CSharpAdapter extends Adapter {
14
14
  }
15
15
  }
16
16
 
17
-
18
17
  module.exports = CSharpAdapter;
@@ -5,8 +5,7 @@ const PythonAdapter = require('./python');
5
5
  const RubyAdapter = require('./ruby');
6
6
  const CSharpAdapter = require('./csharp');
7
7
 
8
-
9
- module.exports = function (lang, opts) {
8
+ function AdapterFactory(lang, opts) {
10
9
  if (!lang) return new Adapter(opts);
11
10
 
12
11
  if (lang === 'java') {
@@ -25,3 +24,5 @@ module.exports = function (lang, opts) {
25
24
  return new CSharpAdapter(opts);
26
25
  }
27
26
  }
27
+
28
+ module.exports = AdapterFactory;
package/lib/pipe/csv.js CHANGED
@@ -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');
@@ -6,9 +7,16 @@ const merge = require('lodash.merge');
6
7
  const { isSameTest, getCurrentDateTime } = require('../util');
7
8
  const { CSV_HEADERS } = require('../constants');
8
9
 
10
+ /**
11
+ * @typedef {import('../../types').Pipe} Pipe
12
+ * @typedef {import('../../types').TestData} TestData
13
+ * @class CsvPipe
14
+ * @implements {Pipe}
15
+ */
9
16
  class CsvPipe {
10
- constructor(params, store = {}) {
11
- this.store = store;
17
+
18
+ constructor(params, store) {
19
+ this.store = store || {};
12
20
  this.title = params.title || process.env.TESTOMATIO_TITLE;
13
21
  this.isEnabled = true;
14
22
  this.results = [];
@@ -54,10 +62,16 @@ class CsvPipe {
54
62
  * @param {Object} headers - csv file headers. Example: [{ id: 'suite_title', title: 'Suite_title' }]
55
63
  */
56
64
  async saveToCsv(data, headers) {
65
+ debug('Data', data);
57
66
  // First, we check whether the export directory exists: if yes - OK, no - create it.
58
67
  this.checkExportDir();
59
68
 
60
- console.log(chalk.yellow(`The test results will be added to the csv. It will take some time...`));
69
+ if (!this.outputFile) {
70
+ console.log(this, chalk.yellow(`CSV file is not set, ignoring`));
71
+ return;
72
+ }
73
+
74
+ console.log(this, chalk.yellow(`The test results will be added to the csv. It will take some time...`));
61
75
  // Create csv writer object
62
76
  const writer = csvWriter.createObjectCsvWriter({
63
77
  path: this.outputFile,
@@ -66,7 +80,7 @@ class CsvPipe {
66
80
  // Save csv file based on the current data
67
81
  try {
68
82
  await writer.writeRecords(data);
69
- console.log(chalk.green(`Recording completed! You can check the result in file = ${this.outputFile}`));
83
+ console.log(this, chalk.green(`Recording completed! You can check the result in file = ${this.outputFile}`));
70
84
  } catch (e) {
71
85
  console.log('Unknown error: ', e);
72
86
  }
@@ -98,8 +112,8 @@ class CsvPipe {
98
112
  }
99
113
 
100
114
  /**
101
- * Save short tests data to the csv file.
102
- * @param {Object} runParams - run params.
115
+ * @param {{ tests?: TestData[] }} runParams
116
+ * @returns {Promise<void>}
103
117
  */
104
118
  async finishRun(runParams) {
105
119
  if (!this.isEnabled) return;
@@ -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');
@@ -6,6 +7,12 @@ const { Octokit } = require('@octokit/rest');
6
7
  const { APP_PREFIX } = require('../constants');
7
8
  const { ansiRegExp, isSameTest } = require('../util');
8
9
 
10
+ /**
11
+ * @typedef {import('../../types').Pipe} Pipe
12
+ * @typedef {import('../../types').TestData} TestData
13
+ * @class GitHubPipe
14
+ * @implements {Pipe}
15
+ */
9
16
  class GitHubPipe {
10
17
  constructor(params, store = {}) {
11
18
  this.isEnabled = false;
@@ -16,27 +23,23 @@ class GitHubPipe {
16
23
  this.repo = process.env.GITHUB_REPOSITORY;
17
24
  this.hiddenCommentData = `<!--- testomat.io report ${process.env.GITHUB_WORKFLOW || ''} -->`;
18
25
 
19
- if (process.env.DEBUG) {
20
- console.log(APP_PREFIX, 'GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', this.ref, this.repo);
21
- }
26
+ debug('GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', 'Ref:', this.ref, 'Repo:', this.repo);
22
27
 
23
28
  if (!this.token || !this.ref || !this.repo) return;
24
29
  this.isEnabled = true;
25
30
  const matchedIssue = this.ref.match(/refs\/pull\/(\d+)\/merge/);
26
31
  if (!matchedIssue) return;
27
- this.issue = matchedIssue[1];
32
+ this.issue = parseInt(matchedIssue[1], 10);
33
+
28
34
  this.start = new Date();
29
35
 
30
- if (process.env.DEBUG) {
31
- console.log(APP_PREFIX, 'GitHub Pipe: Enabled');
32
- }
36
+ debug('GitHub Pipe: Enabled');
33
37
  }
34
38
 
35
39
  async createRun() {}
36
40
 
37
- updateRun() {}
38
-
39
41
  addTest(test) {
42
+ debug('Adding test:', test);
40
43
  if (!this.isEnabled) return;
41
44
 
42
45
  const index = this.tests.findIndex(t => isSameTest(t, test));
@@ -51,6 +54,7 @@ class GitHubPipe {
51
54
 
52
55
  async finishRun(runParams) {
53
56
  if (!this.isEnabled) return;
57
+ if (!this.issue) return;
54
58
 
55
59
  if (runParams.tests) runParams.tests.forEach(t => this.addTest(t));
56
60
 
@@ -58,7 +62,7 @@ class GitHubPipe {
58
62
  auth: this.token,
59
63
  });
60
64
 
61
- const [owner, repo] = this.repo.split('/');
65
+ const [owner, repo] = (this.repo || '').split('/');
62
66
  if (!(owner || repo)) return;
63
67
 
64
68
  // ... create a comment on GitHub
@@ -69,7 +73,7 @@ class GitHubPipe {
69
73
  let summary = `${this.hiddenCommentData}
70
74
 
71
75
  | [![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)} |
76
+ statusEmoji(runParams.status,)} ${runParams.status.toUpperCase()} ${statusEmoji(runParams.status)} |
73
77
  | --- | --- |
74
78
  | Tests | ✔️ **${this.tests.length}** tests run |
75
79
  | Summary | ${statusEmoji('failed')} **${failedCount}** failed; ${statusEmoji(
@@ -150,11 +154,13 @@ class GitHubPipe {
150
154
  .join('\n');
151
155
  body += '\n</details>';
152
156
  }
157
+
153
158
 
154
159
  await deletePreviousReport(this.octokit, owner, repo, this.issue, this.hiddenCommentData);
155
160
 
156
161
  // add report as comment
157
162
  try {
163
+ debug('Adding comment\n', body);
158
164
  const resp = await this.octokit.rest.issues.createComment({
159
165
  owner,
160
166
  repo,
@@ -163,6 +169,7 @@ class GitHubPipe {
163
169
  });
164
170
 
165
171
  const url = resp.data?.html_url;
172
+ debug('Comment URL:', url);
166
173
  this.store.githubUrl = url;
167
174
 
168
175
  console.log(APP_PREFIX, chalk.yellow('GitHub'), `Report created: ${chalk.magenta(url)}`);
@@ -221,7 +228,7 @@ async function deletePreviousReport(octokit, owner, repo, issue, hiddenCommentDa
221
228
  comment_id: comment.id,
222
229
  });
223
230
  } catch (e) {
224
- console.error(`Can't delete previously added comment with testomat.io report. Ignore.`);
231
+ console.warn(`Can't delete previously added comment with testomat.io report. Ignore.`);
225
232
  }
226
233
 
227
234
  // pass next env var if need to clear all previous reports;