testbeats 2.0.9 → 2.1.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.
package/README.md CHANGED
@@ -9,11 +9,9 @@
9
9
 
10
10
  <br />
11
11
 
12
- ![Build](https://github.com/test-results-reporter/testbeats/workflows/Build/badge.svg?branch=main)
13
- ![Downloads](https://img.shields.io/npm/dt/test-results-reporter?logo=npm&label=downloads-old)
14
- ![Downloads](https://img.shields.io/npm/dt/testbeats?logo=npm)
15
- ![Size](https://img.shields.io/bundlephobia/minzip/testbeats)
16
- ![NodeJs](https://img.shields.io/badge/NodeJS-%3E%3D14.0.0-brightgreen?logo=node.js)
12
+ [![Build](https://github.com/test-results-reporter/testbeats/actions/workflows/build.yml/badge.svg)](https://github.com/test-results-reporter/testbeats/actions/workflows/build.yml)
13
+ [![Downloads](https://img.shields.io/npm/dt/test-results-parser?logo=npm&label=downloads)](https://www.npmjs.com/package/test-results-parser)
14
+ [![Size](https://img.shields.io/bundlephobia/minzip/testbeats)](https://bundlephobia.com/result?p=testbeats)
17
15
 
18
16
 
19
17
  [![Stars](https://img.shields.io/github/stars/test-results-reporter/testbeats?style=social)](https://github.com/test-results-reporter/testbeats/stargazers)
@@ -23,9 +21,11 @@
23
21
 
24
22
  </span>
25
23
 
26
- ### Get Started
24
+ <br />
25
+
26
+ **TestBeats** is a tool designed to streamline the process of publishing test results from various automation testing frameworks to communication platforms like **slack**, **teams** and more for easy access and collaboration. It unifies your test reporting to build quality insights and make faster decisions.
27
27
 
28
- TestBeats is a tool designed to streamline the process of publishing test results from various automation testing frameworks to communication platforms like **slack**, **teams** and more for easy access and collaboration. It unifies your test reporting to build quality insights and make faster decisions.
28
+ It supports all major automation testing frameworks and tools.
29
29
 
30
30
  Read more about the project at [https://testbeats.com](https://testbeats.com)
31
31
 
@@ -47,4 +47,8 @@ We use [Github Discussions](https://github.com/test-results-reporter/testbeats/d
47
47
 
48
48
  ## Support Us
49
49
 
50
- Like this project! Star it on [Github](https://github.com/test-results-reporter/testbeats) ⭐. Your support means a lot to us.
50
+ Like this project! Star it on [Github](https://github.com/test-results-reporter/testbeats) ⭐. Your support means a lot to us.
51
+
52
+ <br />
53
+
54
+ > Read more about the project at [https://testbeats.com](https://testbeats.com)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testbeats",
3
- "version": "2.0.9",
3
+ "version": "2.1.1",
4
4
  "description": "Publish test results to Microsoft Teams, Google Chat, Slack and InfluxDB",
5
5
  "main": "src/index.js",
6
6
  "types": "./src/index.d.ts",
@@ -55,7 +55,7 @@
55
55
  "pretty-ms": "^7.0.1",
56
56
  "rosters": "0.0.1",
57
57
  "sade": "^1.8.1",
58
- "test-results-parser": "latest"
58
+ "test-results-parser": "0.2.4"
59
59
  },
60
60
  "devDependencies": {
61
61
  "c8": "^7.12.0",
@@ -33,11 +33,9 @@ class ErrorClustersExtension extends BaseExtension {
33
33
 
34
34
  const clusters = data;
35
35
 
36
- this.extension.inputs.title = `Top ${clusters.length} Errors`;
37
-
38
36
  const texts = [];
39
37
  for (const cluster of clusters) {
40
- texts.push(`${this.bold(`(${cluster.count})`)} - ${cluster.failure}`);
38
+ texts.push(`${cluster.failure} - ${this.bold(`(x${cluster.count})`)}`);
41
39
  }
42
40
  this.text = this.mergeTexts(texts);
43
41
  }
@@ -0,0 +1,118 @@
1
+ const { getPercentage, getPrettyDuration } = require('../helpers/helper')
2
+
3
+ class BasePlatform {
4
+
5
+ /**
6
+ * @param {string|number} text
7
+ */
8
+ bold(text) {
9
+ throw new Error('Not Implemented');
10
+ }
11
+
12
+ break() {
13
+ throw new Error('Not Implemented');
14
+ }
15
+
16
+ /**
17
+ *
18
+ * @param {import('..').Target} target
19
+ * @param {import('test-results-parser').ITestSuite} suite
20
+ */
21
+ getSuiteSummaryText(target, suite) {
22
+ const suite_title = this.getSuiteTitle(suite);
23
+ const suite_results_text = this.#getSuiteResultsText(suite);
24
+ const duration_text = this.#getSuiteDurationText(target, suite);
25
+
26
+ const texts = [
27
+ this.bold(suite_title),
28
+ this.break(),
29
+ this.break(),
30
+ suite_results_text,
31
+ this.break(),
32
+ duration_text,
33
+ ];
34
+
35
+ const metadata_text = this.getSuiteMetaDataText(suite);
36
+
37
+ if (metadata_text) {
38
+ texts.push(this.break());
39
+ texts.push(this.break());
40
+ texts.push(metadata_text);
41
+ }
42
+
43
+ return texts.join('');
44
+ }
45
+
46
+ /**
47
+ *
48
+ * @param {import('test-results-parser').ITestSuite} suite
49
+ * @returns {string}
50
+ */
51
+ getSuiteTitle(suite) {
52
+ const emoji = suite.status === 'PASS' ? '✅' : suite.total === suite.skipped ? '⏭️' : '❌';
53
+ return `${emoji} ${suite.name}`;
54
+ }
55
+
56
+ /**
57
+ *
58
+ * @param {import('test-results-parser').ITestSuite} suite
59
+ * @returns {string}
60
+ */
61
+ #getSuiteResultsText(suite) {
62
+ const suite_results = this.getSuiteResults(suite);
63
+ return `${this.bold('Results')}: ${suite_results}`;
64
+ }
65
+
66
+ /**
67
+ *
68
+ * @param {import('test-results-parser').ITestSuite} suite
69
+ * @returns {string}
70
+ */
71
+ getSuiteResults(suite) {
72
+ return `${suite.passed} / ${suite.total} Passed (${getPercentage(suite.passed, suite.total)}%)`;
73
+ }
74
+
75
+ /**
76
+ *
77
+ * @param {import('..').Target} target
78
+ * @param {import('test-results-parser').ITestSuite} suite
79
+ */
80
+ #getSuiteDurationText(target, suite) {
81
+ const duration = this.getSuiteDuration(target, suite);
82
+ return `${this.bold('Duration')}: ${duration}`
83
+ }
84
+
85
+ /**
86
+ *
87
+ * @param {import('..').Target} target
88
+ * @param {import('test-results-parser').ITestSuite} suite
89
+ */
90
+ getSuiteDuration(target, suite) {
91
+ return getPrettyDuration(suite.duration, target.inputs.duration);
92
+ }
93
+
94
+ /**
95
+ *
96
+ * @param {import('test-results-parser').ITestSuite} suite
97
+ * @returns {string}
98
+ */
99
+ getSuiteMetaDataText(suite) {
100
+ if (!suite || !suite.metadata) {
101
+ return;
102
+ }
103
+
104
+ const texts = [];
105
+
106
+ if (suite.metadata.platform && suite.metadata.platform.name && suite.metadata.platform.version) {
107
+ texts.push(`${suite.metadata.platform.name} ${suite.metadata.platform.version}`)
108
+ }
109
+
110
+ if (suite.metadata.browser && suite.metadata.browser.name && suite.metadata.browser.version) {
111
+ texts.push(`${suite.metadata.browser.name} ${suite.metadata.browser.version}`)
112
+ }
113
+
114
+ return texts.join(' • ');
115
+ }
116
+ }
117
+
118
+ module.exports = { BasePlatform }
@@ -0,0 +1,18 @@
1
+ const { BasePlatform } = require("./base.platform");
2
+
3
+ class ChatPlatform extends BasePlatform {
4
+
5
+ /**
6
+ * @param {string|number} text
7
+ */
8
+ bold(text) {
9
+ return `<b>${text}</b>`;
10
+ }
11
+
12
+ break() {
13
+ return '<br>';
14
+ }
15
+
16
+ }
17
+
18
+ module.exports = { ChatPlatform }
@@ -0,0 +1,25 @@
1
+ const { TARGET } = require("../helpers/constants");
2
+ const { SlackPlatform } = require('./slack.platform');
3
+ const { TeamsPlatform } = require('./teams.platform');
4
+ const { ChatPlatform } = require('./chat.platform');
5
+
6
+ /**
7
+ *
8
+ * @param {string} name
9
+ */
10
+ function getPlatform(name) {
11
+ switch (name) {
12
+ case TARGET.SLACK:
13
+ return new SlackPlatform();
14
+ case TARGET.TEAMS:
15
+ return new TeamsPlatform();
16
+ case TARGET.CHAT:
17
+ return new ChatPlatform();
18
+ default:
19
+ throw new Error('Invalid Platform');
20
+ }
21
+ }
22
+
23
+ module.exports = {
24
+ getPlatform
25
+ }
@@ -0,0 +1,17 @@
1
+ const { BasePlatform } = require("./base.platform");
2
+
3
+ class SlackPlatform extends BasePlatform {
4
+
5
+ /**
6
+ * @param {string|number} text
7
+ */
8
+ bold(text) {
9
+ return `*${text}*`;
10
+ }
11
+
12
+ break() {
13
+ return '\n';
14
+ }
15
+ }
16
+
17
+ module.exports = { SlackPlatform }
@@ -0,0 +1,16 @@
1
+ const { BasePlatform } = require("./base.platform");
2
+
3
+ class TeamsPlatform extends BasePlatform {
4
+ /**
5
+ * @param {string|number} text
6
+ */
7
+ bold(text) {
8
+ return `**${text}**`;
9
+ }
10
+
11
+ break() {
12
+ return '\n\n';
13
+ }
14
+ }
15
+
16
+ module.exports = { TeamsPlatform }
@@ -1,10 +1,11 @@
1
1
  const request = require('phin-retry');
2
2
  const { getTitleText, getResultText, truncate, getPrettyDuration } = require('../helpers/helper');
3
3
  const extension_manager = require('../extensions');
4
- const { HOOK, STATUS } = require('../helpers/constants');
4
+ const { HOOK, STATUS, TARGET } = require('../helpers/constants');
5
5
  const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
6
6
  const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
7
7
  const logger = require('../utils/logger');
8
+ const { getPlatform } = require('../platforms');
8
9
 
9
10
  async function run({ result, target }) {
10
11
  setTargetInputs(target);
@@ -100,11 +101,9 @@ function setSuiteBlock({ result, target, payload }) {
100
101
  }
101
102
 
102
103
  function getSuiteSummary({ target, suite }) {
103
- const emoji = suite.status === 'PASS' ? '✅' : '❌';
104
- const suite_title = `${emoji} ${suite.name}`;
105
- const result_text = getResultText({ result: suite });
106
- const duration_text = getPrettyDuration(suite.duration, target.inputs.duration);
107
- return `<b>${suite_title}</b><br><br><b>Results</b>: ${result_text}<br><b>Duration</b>: ${duration_text}`;
104
+ const platform = getPlatform(TARGET.CHAT);
105
+ const text = platform.getSuiteSummaryText(target, suite);
106
+ return text;
108
107
  }
109
108
 
110
109
  function getFailureDetails(suite) {
@@ -223,7 +222,7 @@ const default_inputs = {
223
222
  publish: 'test-summary',
224
223
  include_suites: true,
225
224
  max_suites: 10,
226
- only_failures: false,
225
+ only_failures: true,
227
226
  include_failure_details: false,
228
227
  duration: '',
229
228
  metrics: [
@@ -1,12 +1,13 @@
1
1
  const request = require('phin-retry');
2
2
  const { getPercentage, truncate, getPrettyDuration } = require('../helpers/helper');
3
3
  const extension_manager = require('../extensions');
4
- const { HOOK, STATUS } = require('../helpers/constants');
4
+ const { HOOK, STATUS, TARGET } = require('../helpers/constants');
5
5
  const logger = require('../utils/logger');
6
6
 
7
7
  const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
8
8
  const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
9
9
  const TestResult = require('test-results-parser/src/models/TestResult');
10
+ const { getPlatform } = require('../platforms');
10
11
 
11
12
 
12
13
 
@@ -109,9 +110,8 @@ function setSuiteBlock({ result, target, payload }) {
109
110
  }
110
111
 
111
112
  function getSuiteSummary({ target, suite }) {
112
- let text = `*${getSuiteTitle(suite)}*\n`;
113
- text += `\n*Results*: ${getResultText(suite)}`;
114
- text += `\n*Duration*: ${getPrettyDuration(suite.duration, target.inputs.duration)}`;
113
+ const platform = getPlatform(TARGET.SLACK);
114
+ const text = platform.getSuiteSummaryText(target, suite);
115
115
  return {
116
116
  "type": "section",
117
117
  "text": {
@@ -121,11 +121,6 @@ function getSuiteSummary({ target, suite }) {
121
121
  };
122
122
  }
123
123
 
124
- function getSuiteTitle(suite) {
125
- const emoji = suite.status === 'PASS' ? '✅' : suite.total === suite.skipped ? '⏭️' : '❌';
126
- return `${emoji} ${suite.name}`;
127
- }
128
-
129
124
  function getFailureDetails(suite) {
130
125
  let text = '';
131
126
  const cases = suite.cases;
@@ -249,7 +244,7 @@ const default_inputs = {
249
244
  publish: 'test-summary',
250
245
  include_suites: true,
251
246
  max_suites: 10,
252
- only_failures: false,
247
+ only_failures: true,
253
248
  include_failure_details: false,
254
249
  duration: '',
255
250
  metrics: [
@@ -2,11 +2,12 @@ const request = require('phin-retry');
2
2
  const { getPercentage, truncate, getPrettyDuration } = require('../helpers/helper');
3
3
  const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
4
4
  const extension_manager = require('../extensions');
5
- const { HOOK, STATUS } = require('../helpers/constants');
5
+ const { HOOK, STATUS, TARGET } = require('../helpers/constants');
6
6
  const logger = require('../utils/logger');
7
7
 
8
8
  const TestResult = require('test-results-parser/src/models/TestResult');
9
9
  const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
10
+ const { getPlatform } = require('../platforms');
10
11
 
11
12
  /**
12
13
  * @param {object} param0
@@ -144,12 +145,16 @@ function setSuiteBlock({ result, target, payload }) {
144
145
  }
145
146
 
146
147
  function getSuiteSummary({ suite, target }) {
147
- const percentage = getPercentage(suite.passed, suite.total);
148
- const emoji = suite.status === 'PASS' ? '✅' : '❌';
149
- return [
148
+
149
+ const platform = getPlatform(TARGET.TEAMS);
150
+ const suite_title = platform.getSuiteTitle(suite);
151
+ const suite_results = platform.getSuiteResults(suite);
152
+ const duration = platform.getSuiteDuration(target, suite);
153
+
154
+ const blocks = [
150
155
  {
151
156
  "type": "TextBlock",
152
- "text": `${emoji} ${suite.name}`,
157
+ "text": suite_title,
153
158
  "isSubtle": true,
154
159
  "weight": "bolder",
155
160
  "wrap": true
@@ -159,15 +164,26 @@ function getSuiteSummary({ suite, target }) {
159
164
  "facts": [
160
165
  {
161
166
  "title": "Results:",
162
- "value": `${suite.passed} / ${suite.total} Passed (${percentage}%)`
167
+ "value": suite_results
163
168
  },
164
169
  {
165
170
  "title": "Duration:",
166
- "value": `${getPrettyDuration(suite.duration, target.inputs.duration)}`
171
+ "value": duration
167
172
  }
168
173
  ]
169
174
  }
170
- ]
175
+ ];
176
+
177
+ const suite_metadata_text = platform.getSuiteMetaDataText(suite);
178
+ if (suite_metadata_text) {
179
+ blocks.push({
180
+ "type": "TextBlock",
181
+ "text": suite_metadata_text,
182
+ "wrap": true
183
+ });
184
+ }
185
+
186
+ return blocks;
171
187
  }
172
188
 
173
189
  function getFailureDetailsFactSets(suite) {
@@ -284,7 +300,7 @@ const default_inputs = {
284
300
  publish: 'test-summary',
285
301
  include_suites: true,
286
302
  max_suites: 10,
287
- only_failures: false,
303
+ only_failures: true,
288
304
  include_failure_details: false,
289
305
  width: '',
290
306
  duration: '',