@testomatio/reporter 0.8.0-beta.1 → 0.8.0-beta.10

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.
@@ -35,11 +35,6 @@ function CodeceptReporter(config) {
35
35
  const testTimeMap = {};
36
36
  const { apiKey } = config;
37
37
 
38
- if (!apiKey) {
39
- console.log('TESTOMATIO key is empty, ignoring reports');
40
- return;
41
- }
42
-
43
38
  const getDuration = test => {
44
39
  if (testTimeMap[test.id]) {
45
40
  return Date.now() - testTimeMap[test.id];
@@ -18,13 +18,7 @@ class CucumberReporter extends Formatter {
18
18
  this.failures = [];
19
19
  this.cases = [];
20
20
 
21
- const apiKey = process.env.TESTOMATIO;
22
- if (!apiKey || apiKey === '') {
23
- console.log(chalk.red('TESTOMATIO key is empty, ignoring reports'));
24
- return;
25
- }
26
-
27
- this.client = new TestomatClient({ apiKey });
21
+ this.client = new TestomatClient();
28
22
  this.status = TRConstants.PASSED;
29
23
 
30
24
  }
@@ -5,14 +5,7 @@ const { PASSED, FAILED } = require('../constants');
5
5
  class JasmineReporter {
6
6
  constructor(options) {
7
7
  this.testTimeMap = {};
8
- const { apiKey } = options;
9
-
10
- if (!apiKey) {
11
- console.log('TESTOMATIO key is empty, ignoring reports');
12
- return;
13
- }
14
-
15
- this.client = new TestomatClient({ apiKey });
8
+ this.client = new TestomatClient({ apiKey: options?.apiKey });
16
9
  this.client.createRun();
17
10
  }
18
11
 
@@ -6,14 +6,8 @@ class JestReporter {
6
6
  constructor(globalConfig, options) {
7
7
  this._globalConfig = globalConfig;
8
8
  this._options = options;
9
- const { apiKey } = options;
10
9
 
11
- if (!apiKey) {
12
- console.log('TESTOMATIO key is empty, ignoring reports');
13
- return;
14
- }
15
-
16
- this.client = new TestomatClient({ apiKey });
10
+ this.client = new TestomatClient({ apiKey: options?.apiKey });
17
11
  this.client.createRun();
18
12
  }
19
13
 
@@ -1,5 +1,6 @@
1
1
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
2
2
  const Mocha = require('mocha');
3
+ const chalk = require('chalk');
3
4
  const TestomatClient = require('../client');
4
5
  const TRConstants = require('../constants');
5
6
  const { parseTest } = require('../util');
@@ -11,13 +12,7 @@ function MochaReporter(runner, opts) {
11
12
  let passes = 0;
12
13
  let failures = 0;
13
14
 
14
- const { apiKey } = opts.reporterOptions;
15
-
16
- if (!apiKey) {
17
- console.log('TESTOMATIO key is empty, ignoring reports');
18
- return;
19
- }
20
- const client = new TestomatClient({ apiKey });
15
+ const client = new TestomatClient({ apiKey: opts?.reporterOptions?.apiKey });
21
16
 
22
17
  runner.on(EVENT_RUN_BEGIN, () => {
23
18
  client.createRun();
@@ -25,7 +20,7 @@ function MochaReporter(runner, opts) {
25
20
 
26
21
  runner.on(EVENT_TEST_PASS, test => {
27
22
  passes += 1;
28
- console.log('pass: %s', test.fullTitle());
23
+ console.log(chalk.bold.green(''), test.fullTitle());
29
24
  const testId = parseTest(test.title);
30
25
  client.addTestRun(testId, TRConstants.PASSED, {
31
26
  title: test.title,
@@ -35,7 +30,7 @@ function MochaReporter(runner, opts) {
35
30
 
36
31
  runner.on(EVENT_TEST_FAIL, (test, err) => {
37
32
  failures += 1;
38
- console.log('fail: %s -- error: %s', test.fullTitle(), err.message);
33
+ console.log(chalk.bold.red(''), test.fullTitle(), chalk.gray(err.message));
39
34
  const testId = parseTest(test.title);
40
35
  client.addTestRun(testId, TRConstants.FAILED, {
41
36
  error: err,
@@ -45,8 +40,8 @@ function MochaReporter(runner, opts) {
45
40
  });
46
41
 
47
42
  runner.on(EVENT_RUN_END, () => {
48
- console.log('end: %d/%d', passes, passes + failures);
49
43
  const status = failures === 0 ? TRConstants.PASSED : TRConstants.FAILED;
44
+ console.log(chalk.bold(status), `${passes} passed, ${failures} failed`);
50
45
  client.updateRunStatus(status);
51
46
  });
52
47
  }
@@ -10,13 +10,7 @@ const { parseTest } = require('../util');
10
10
 
11
11
  class TestomatioReporter {
12
12
  constructor(config = {}) {
13
- const { apiKey } = config;
14
-
15
- if (!apiKey) {
16
- console.log('API Key is not provided. Testomat.io report is disabled');
17
- } else {
18
- this.client = new TestomatioClient({ apiKey });
19
- }
13
+ this.client = new TestomatioClient({ apiKey: config?.apiKey });
20
14
 
21
15
  this.videos = [];
22
16
  }
@@ -7,10 +7,7 @@ class WebdriverReporter extends WDIOReporter {
7
7
  constructor(options) {
8
8
  super(options);
9
9
 
10
- const { apiKey } = options;
11
- if (!apiKey) return;
12
-
13
- this.client = new TestomatClient({ apiKey });
10
+ this.client = new TestomatClient({ apiKey: options?.apiKey });
14
11
  options = Object.assign(options, { stdout: true });
15
12
 
16
13
  this._addTestPromises = [];
package/lib/client.js CHANGED
@@ -6,6 +6,7 @@ const chalk = require('chalk');
6
6
  const upload = require('./fileUploader');
7
7
  const { PASSED, FAILED, FINISHED, APP_PREFIX } = require('./constants');
8
8
  const pipesFactory = require('./pipe');
9
+
9
10
  const { TESTOMATIO_ENV } = process.env;
10
11
 
11
12
 
@@ -15,8 +16,7 @@ class TestomatClient {
15
16
  *
16
17
  * @param {*} params
17
18
  */
18
- constructor(params) {
19
- this.apiKey = params.apiKey || process.env.TESTOMATIO;
19
+ constructor(params = {}) {
20
20
  this.title = params.title || process.env.TESTOMATIO_TITLE;
21
21
  this.env = TESTOMATIO_ENV;
22
22
  this.parallel = params.parallel;
@@ -26,6 +26,7 @@ class TestomatClient {
26
26
  this.axios = axios.create();
27
27
  this.totalUploaded = 0;
28
28
  this.version = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString()).version;
29
+ console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
29
30
  }
30
31
 
31
32
  /**
@@ -34,7 +35,9 @@ class TestomatClient {
34
35
  * @returns {Promise} - resolves to Run id which should be used to update / add test
35
36
  */
36
37
  createRun() {
37
- const { runId } = process.env;
38
+ // all pipes disabled, skipping
39
+ if (!this.pipes.filter(p => p.isEnabled).length) return;
40
+
38
41
  const runParams = {
39
42
  title: this.title,
40
43
  parallel: this.parallel,
@@ -54,6 +57,9 @@ class TestomatClient {
54
57
  * @returns {Promise}
55
58
  */
56
59
  async addTestRun(testId, status, testData = {}) {
60
+ // all pipes disabled, skipping
61
+ if (!this.pipes.filter(p => p.isEnabled).length) return;
62
+
57
63
  const {
58
64
  error = '',
59
65
  time = '',
@@ -127,6 +133,9 @@ class TestomatClient {
127
133
  * @returns {Promise}
128
134
  */
129
135
  updateRunStatus(status, isParallel) {
136
+ // all pipes disabled, skipping
137
+ if (!this.pipes.filter(p => p.isEnabled).length) return;
138
+
130
139
  let statusEvent;
131
140
  if (status === FINISHED) statusEvent = 'finish';
132
141
  if (status === PASSED) statusEvent = 'pass';
@@ -14,11 +14,22 @@ class GitHubPipe {
14
14
  this.tests = []
15
15
  this.token = params.GH_PAT || process.env.GH_PAT;
16
16
  this.ref = process.env.GITHUB_REF
17
- this.repo = process.env.GITHUB_ACTION_REPOSITORY
17
+ this.repo = process.env.GITHUB_REPOSITORY
18
+
19
+ if (process.env.DEBUG) {
20
+ console.log(APP_PREFIX, 'GitHub Pipe: ', this.token ? 'TOKEN' : '*no token*', this.ref, this.repo);
21
+ }
22
+
18
23
  if (!this.token || !this.ref || !this.repo) return;
19
24
  this.isEnabled = true;
20
- this.issue = this.ref.match(/refs\/pull\/(\d+)\/merge/)[1]
25
+ const matchedIssue = this.ref.match(/refs\/pull\/(\d+)\/merge/);
26
+ if (!matchedIssue) return;
27
+ this.issue = matchedIssue[1]
21
28
  this.start = new Date();
29
+
30
+ if (process.env.DEBUG) {
31
+ console.log(APP_PREFIX, 'GitHub Pipe: Enabled');
32
+ }
22
33
  }
23
34
 
24
35
  async createRun() {}
@@ -27,7 +38,7 @@ class GitHubPipe {
27
38
 
28
39
  addTest(test) {
29
40
  if (!this.isEnabled) return;
30
-
41
+
31
42
  const index = this.tests.findIndex(t => isSameTest(t, test))
32
43
  // update if they were already added
33
44
  if (index >= 0) {
@@ -105,19 +116,19 @@ class GitHubPipe {
105
116
  let body = summary;
106
117
 
107
118
  if (failures.length) {
108
- body += `\n### 🟥 Failures (${failures.length})\n${failures.join('\n')}`;
109
-
110
- }
111
- if (failures.length > 20) {
112
- body += "\n> Notice\n> Only first 20 failures shown*"
119
+ body += `\n<details>\n<summary><h3>🟥 Failures (${failures.length})</h4></summary>\n\n${failures.join('\n')}\n`;
120
+ if (failures.length > 20) {
121
+ body += "\n> Notice\n> Only first 20 failures shown*"
122
+ }
123
+ body += "\n\n</details>\n";
113
124
  }
114
125
 
115
126
  if (this.tests.length > 0) {
116
- body += "\n### 🐢 Slowest Tests\n\n"
117
-
127
+ body += "\n<details>\n<summary><h3>🐢 Slowest Tests</h3>\n\n"
118
128
  body += this.tests.sort((a, b) => b?.run_time - a?.run_time).slice(0, 5).map(t => {
119
129
  return `* ${fullName(t)} (${parseFloat(t.run_time).toFixed(2)}ms)`
120
130
  }).join('\n')
131
+ body += "\n</details>"
121
132
  }
122
133
 
123
134
  try {
@@ -144,6 +155,10 @@ class GitHubPipe {
144
155
  );
145
156
  }
146
157
  }
158
+
159
+ toString() {
160
+ return 'GitHub Reporter'
161
+ }
147
162
  }
148
163
 
149
164
  function statusEmoji(status) {
package/lib/pipe/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const chalk = require('chalk');
3
4
  const { APP_PREFIX } = require('../constants');
4
5
  const TestomatioPipe = require('./testomatio');
5
6
  const GitHubPipe = require('./github');
@@ -36,10 +37,13 @@ module.exports = function(params, opts) {
36
37
  }
37
38
 
38
39
 
39
- const defaultPipes = [
40
+ const pipes = [
40
41
  new TestomatioPipe(params, opts),
41
42
  new GitHubPipe(params, opts),
43
+ ...extraPipes
42
44
  ];
43
45
 
44
- return [...defaultPipes, ...extraPipes];
46
+ console.log(APP_PREFIX, chalk.cyan('Pipes:'), chalk.cyan(pipes.filter(p => p.isEnabled).map(p => p.toString()).join(', ') || "No pipes enabled"));
47
+
48
+ return pipes;
45
49
  }
@@ -15,9 +15,15 @@ class TestomatioPipe {
15
15
  constructor(params, store = {}) {
16
16
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
17
17
  this.apiKey = params.apiKey || process.env.TESTOMATIO;
18
+ if (process.env.DEBUG) {
19
+ console.log(APP_PREFIX, 'Testomatio Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
20
+ }
18
21
  if (!this.apiKey) {
19
22
  return;
20
23
  }
24
+ if (process.env.DEBUG) {
25
+ console.log(APP_PREFIX, 'Testomatio Pipe: Enabled');
26
+ }
21
27
  this.store = store;
22
28
  this.title = params.title || process.env.TESTOMATIO_TITLE;
23
29
  this.axios = axios.create();
@@ -26,7 +32,6 @@ class TestomatioPipe {
26
32
  this.runId = params.runId || process.env.runId;
27
33
  this.createNewTests = !!process.env.TESTOMATIO_CREATE;
28
34
 
29
-
30
35
  if (!isValidUrl(this.url.trim())) {
31
36
  this.isEnabled = false;
32
37
  console.log(
@@ -56,7 +61,7 @@ class TestomatioPipe {
56
61
  this.runUrl = `${this.url}/${resp.data.url.split('/').splice(3).join('/')}`;
57
62
  this.store.runUrl = this.runUrl;
58
63
  this.store.runId = this.runId;
59
- console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId, chalk.gray(`v${this.version}`));
64
+ console.log(APP_PREFIX, '📊 Report created. Report ID:', this.runId);
60
65
  process.env.runId = this.runId;
61
66
  } catch (err) {
62
67
  console.log(
@@ -122,7 +127,11 @@ class TestomatioPipe {
122
127
  } catch (err) {
123
128
  console.log(APP_PREFIX, 'Error updating status, skipping...', err);
124
129
  }
125
- }
130
+ }
131
+
132
+ toString() {
133
+ return 'Testomatio Reporter';
134
+ }
126
135
  }
127
136
 
128
137
  module.exports = TestomatioPipe;
package/lib/util.js CHANGED
@@ -137,9 +137,7 @@ const fetchSourceCode = (contents, opts = {}) => {
137
137
  }
138
138
  }
139
139
 
140
- const isSameTest = (test, t) => {
141
- return t.title == test.title && t.suite_title == test.suite_title && Object.values(t.example) == Object.values(test.example) && t.test_id == test.test_id;
142
- }
140
+ const isSameTest = (test, t) => t.title == test.title && t.suite_title == test.suite_title && Object.values(t.example) == Object.values(test.example) && t.test_id == test.test_id
143
141
 
144
142
  module.exports = {
145
143
  parseTest,
package/lib/xmlReader.js CHANGED
@@ -4,7 +4,7 @@ const fs = require("fs");
4
4
 
5
5
  // const util = require("util"); // you can see a result
6
6
  const { XMLParser } = require("fast-xml-parser");
7
- const { PASSED, FAILED, SKIPPED } = require('./constants');
7
+ const { APP_PREFIX, PASSED, FAILED, SKIPPED } = require('./constants');
8
8
  const { fetchFilesFromStackTrace, fetchSourceCode, fetchSourceCodeFromStackTrace } = require('./util');
9
9
  const upload = require('./fileUploader');
10
10
  const pipesFactory = require('./pipe');
@@ -45,6 +45,9 @@ class XmlReader {
45
45
  this.stats = {}
46
46
  this.stats.language = opts.lang?.toLowerCase();
47
47
  this.filesToUpload = {}
48
+
49
+ this.version = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json')).toString()).version;
50
+ console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
48
51
  }
49
52
 
50
53
  connectAdapter() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "0.8.0-beta.1",
3
+ "version": "0.8.0-beta.10",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "main": "./lib/reporter.js",
6
6
  "repository": "git@github.com:testomatio/reporter.git",
@@ -19,7 +19,8 @@
19
19
  "has-flag": "^5.0.1",
20
20
  "is-valid-path": "^0.1.1",
21
21
  "json-cycle": "^1.3.0",
22
- "lodash.memoize": "^4.1.2"
22
+ "lodash.memoize": "^4.1.2",
23
+ "lodash.merge": "^4.6.2"
23
24
  },
24
25
  "files": [
25
26
  "bin",