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 +12 -8
- package/package.json +2 -2
- package/src/extensions/error-clusters.extension.js +1 -3
- package/src/platforms/base.platform.js +118 -0
- package/src/platforms/chat.platform.js +18 -0
- package/src/platforms/index.js +25 -0
- package/src/platforms/slack.platform.js +17 -0
- package/src/platforms/teams.platform.js +16 -0
- package/src/targets/chat.js +6 -7
- package/src/targets/slack.js +5 -10
- package/src/targets/teams.js +25 -9
package/README.md
CHANGED
|
@@ -9,11 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
<br />
|
|
11
11
|
|
|
12
|
-

|
|
16
|
-

|
|
12
|
+
[](https://github.com/test-results-reporter/testbeats/actions/workflows/build.yml)
|
|
13
|
+
[](https://www.npmjs.com/package/test-results-parser)
|
|
14
|
+
[](https://bundlephobia.com/result?p=testbeats)
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
[](https://github.com/test-results-reporter/testbeats/stargazers)
|
|
@@ -23,9 +21,11 @@
|
|
|
23
21
|
|
|
24
22
|
</span>
|
|
25
23
|
|
|
26
|
-
|
|
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
|
-
|
|
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.
|
|
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": "
|
|
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})`)}
|
|
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 }
|
package/src/targets/chat.js
CHANGED
|
@@ -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
|
|
104
|
-
const
|
|
105
|
-
|
|
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:
|
|
225
|
+
only_failures: true,
|
|
227
226
|
include_failure_details: false,
|
|
228
227
|
duration: '',
|
|
229
228
|
metrics: [
|
package/src/targets/slack.js
CHANGED
|
@@ -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
|
-
|
|
113
|
-
text
|
|
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:
|
|
247
|
+
only_failures: true,
|
|
253
248
|
include_failure_details: false,
|
|
254
249
|
duration: '',
|
|
255
250
|
metrics: [
|
package/src/targets/teams.js
CHANGED
|
@@ -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
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
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":
|
|
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":
|
|
167
|
+
"value": suite_results
|
|
163
168
|
},
|
|
164
169
|
{
|
|
165
170
|
"title": "Duration:",
|
|
166
|
-
"value":
|
|
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:
|
|
303
|
+
only_failures: true,
|
|
288
304
|
include_failure_details: false,
|
|
289
305
|
width: '',
|
|
290
306
|
duration: '',
|