testbeats 2.0.6 → 2.0.8
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/package.json +1 -1
- package/src/beats/beats.js +6 -17
- package/src/extensions/ci-info.extension.js +45 -15
- package/src/extensions/custom.extension.js +47 -0
- package/src/extensions/index.js +2 -2
- package/src/extensions/smart-analysis.extension.js +6 -6
- package/src/helpers/ci.js +22 -0
- package/src/index.d.ts +1 -0
- package/src/targets/chat.js +7 -5
- package/src/targets/slack.js +20 -16
- package/src/targets/teams.js +10 -8
- package/src/extensions/custom.js +0 -29
package/package.json
CHANGED
package/src/beats/beats.js
CHANGED
|
@@ -20,10 +20,14 @@ class Beats {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async publish() {
|
|
23
|
+
this.#setApiKey();
|
|
24
|
+
if (!this.config.api_key) {
|
|
25
|
+
logger.warn('😿 No API key provided, skipping publishing results to TestBeats Portal...');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
23
28
|
this.#setCIInfo();
|
|
24
29
|
this.#setProjectName();
|
|
25
30
|
this.#setRunName();
|
|
26
|
-
this.#setApiKey();
|
|
27
31
|
await this.#publishTestResults();
|
|
28
32
|
await this.#uploadAttachments();
|
|
29
33
|
this.#updateTitleLink();
|
|
@@ -45,13 +49,10 @@ class Beats {
|
|
|
45
49
|
|
|
46
50
|
#setRunName() {
|
|
47
51
|
this.config.run = this.config.run || process.env.TEST_BEATS_RUN || (this.ci && this.ci.build_name) || 'demo-run';
|
|
52
|
+
this.result.name = this.config.run;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
async #publishTestResults() {
|
|
51
|
-
if (!this.config.api_key) {
|
|
52
|
-
logger.warn('😿 No API key provided, skipping publishing results to TestBeats Portal...');
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
56
|
logger.info("🚀 Publishing results to TestBeats Portal...");
|
|
56
57
|
try {
|
|
57
58
|
const payload = this.#getPayload();
|
|
@@ -89,18 +90,6 @@ class Beats {
|
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
#getAllFailedTestCases() {
|
|
93
|
-
const test_cases = [];
|
|
94
|
-
for (const suite of this.result.suites) {
|
|
95
|
-
for (const test of suite.cases) {
|
|
96
|
-
if (test.status === 'FAIL') {
|
|
97
|
-
test_cases.push(test);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return test_cases;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
93
|
#updateTitleLink() {
|
|
105
94
|
if (!this.test_run_id) {
|
|
106
95
|
return;
|
|
@@ -3,6 +3,8 @@ const { getCIInformation } = require('../helpers/ci');
|
|
|
3
3
|
const { getMetaDataText } = require("../helpers/metadata.helper");
|
|
4
4
|
const { STATUS, HOOK } = require("../helpers/constants");
|
|
5
5
|
|
|
6
|
+
const COMMON_BRANCH_NAMES = ['main', 'master', 'dev', 'develop', 'qa', 'test'];
|
|
7
|
+
|
|
6
8
|
class CIInfoExtension extends BaseExtension {
|
|
7
9
|
|
|
8
10
|
constructor(target, extension, result, payload, root_payload) {
|
|
@@ -17,23 +19,24 @@ class CIInfoExtension extends BaseExtension {
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
#setDefaultOptions() {
|
|
20
|
-
this.default_options.hook = HOOK.AFTER_SUMMARY
|
|
22
|
+
this.default_options.hook = HOOK.AFTER_SUMMARY;
|
|
21
23
|
this.default_options.condition = STATUS.PASS_OR_FAIL;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
#setDefaultInputs() {
|
|
25
27
|
this.default_inputs.title = '';
|
|
26
28
|
this.default_inputs.title_link = '';
|
|
27
|
-
this.default_inputs.
|
|
28
|
-
this.default_inputs.
|
|
29
|
+
this.default_inputs.show_repository_non_common = true;
|
|
30
|
+
this.default_inputs.show_repository = false;
|
|
31
|
+
this.default_inputs.show_repository_branch = false;
|
|
29
32
|
this.default_inputs.show_build = true;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
async run() {
|
|
33
36
|
this.ci = getCIInformation();
|
|
34
37
|
|
|
35
|
-
this
|
|
36
|
-
this
|
|
38
|
+
this.#setRepositoryElements();
|
|
39
|
+
this.#setBuildElements();
|
|
37
40
|
|
|
38
41
|
const repository_text = await getMetaDataText({ elements: this.repository_elements, target: this.target, extension: this.extension, result: this.result, default_condition: this.default_options.condition });
|
|
39
42
|
const build_text = await getMetaDataText({ elements: this.build_elements, target: this.target, extension: this.extension, result: this.result, default_condition: this.default_options.condition });
|
|
@@ -41,28 +44,55 @@ class CIInfoExtension extends BaseExtension {
|
|
|
41
44
|
this.attach();
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
setRepositoryElements() {
|
|
47
|
+
#setRepositoryElements() {
|
|
45
48
|
if (!this.ci) {
|
|
46
49
|
return;
|
|
47
50
|
}
|
|
51
|
+
if (!this.ci.repository_url || !this.ci.repository_name || !this.ci.repository_ref) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
48
54
|
|
|
49
|
-
if (this.extension.inputs.show_repository
|
|
50
|
-
this
|
|
55
|
+
if (this.extension.inputs.show_repository) {
|
|
56
|
+
this.#setRepositoryElement();
|
|
57
|
+
}
|
|
58
|
+
if (this.extension.inputs.show_repository_branch) {
|
|
59
|
+
if (this.ci.repository_ref.includes('refs/pull')) {
|
|
60
|
+
this.#setPullRequestElement();
|
|
61
|
+
} else {
|
|
62
|
+
this.#setRepositoryBranchElement();
|
|
63
|
+
}
|
|
51
64
|
}
|
|
52
|
-
if (this.extension.inputs.show_repository_branch && this.
|
|
65
|
+
if (!this.extension.inputs.show_repository && !this.extension.inputs.show_repository_branch && this.extension.inputs.show_repository_non_common) {
|
|
53
66
|
if (this.ci.repository_ref.includes('refs/pull')) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.repository_elements.push({ label: 'Pull Request', key: pr_name, value: pr_url, type: 'hyperlink' });
|
|
67
|
+
this.#setRepositoryElement();
|
|
68
|
+
this.#setPullRequestElement();
|
|
57
69
|
} else {
|
|
58
|
-
const branch_url = this.ci.repository_url + this.ci.repository_ref.replace('refs/heads/', '/tree/');
|
|
59
70
|
const branch_name = this.ci.repository_ref.replace('refs/heads/', '');
|
|
60
|
-
|
|
71
|
+
if (!COMMON_BRANCH_NAMES.includes(branch_name.toLowerCase())) {
|
|
72
|
+
this.#setRepositoryElement();
|
|
73
|
+
this.#setRepositoryBranchElement();
|
|
74
|
+
}
|
|
61
75
|
}
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
|
|
65
|
-
|
|
79
|
+
#setRepositoryElement() {
|
|
80
|
+
this.repository_elements.push({ label: 'Repository', key: this.ci.repository_name, value: this.ci.repository_url, type: 'hyperlink' });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#setPullRequestElement() {
|
|
84
|
+
const pr_url = this.ci.repository_url + this.ci.repository_ref.replace('refs/pull/', '/pull/');
|
|
85
|
+
const pr_name = this.ci.repository_ref.replace('refs/pull/', '').replace('/merge', '');
|
|
86
|
+
this.repository_elements.push({ label: 'Pull Request', key: pr_name, value: pr_url, type: 'hyperlink' });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#setRepositoryBranchElement() {
|
|
90
|
+
const branch_url = this.ci.repository_url + this.ci.repository_ref.replace('refs/heads/', '/tree/');
|
|
91
|
+
const branch_name = this.ci.repository_ref.replace('refs/heads/', '');
|
|
92
|
+
this.repository_elements.push({ label: 'Branch', key: branch_name, value: branch_url, type: 'hyperlink' });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#setBuildElements() {
|
|
66
96
|
if (!this.ci) {
|
|
67
97
|
return;
|
|
68
98
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { BaseExtension } = require("./base.extension");
|
|
3
|
+
const { STATUS, HOOK } = require("../helpers/constants");
|
|
4
|
+
|
|
5
|
+
class CustomExtension extends BaseExtension {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {import('..').CustomExtension} extension
|
|
9
|
+
*/
|
|
10
|
+
constructor(target, extension, result, payload, root_payload) {
|
|
11
|
+
super(target, extension, result, payload, root_payload);
|
|
12
|
+
this.extension = extension;
|
|
13
|
+
this.#setDefaultOptions();
|
|
14
|
+
this.updateExtensionInputs();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#setDefaultOptions() {
|
|
18
|
+
this.default_options.hook = HOOK.END,
|
|
19
|
+
this.default_options.condition = STATUS.PASS_OR_FAIL;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async run() {
|
|
23
|
+
const params = this.#getParams();
|
|
24
|
+
if (typeof this.extension.inputs.load === 'string') {
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
const extension_runner = require(path.join(cwd, this.extension.inputs.load));
|
|
27
|
+
await extension_runner.run(params);
|
|
28
|
+
} else if (typeof this.extension.inputs.load === 'function') {
|
|
29
|
+
await this.extension.inputs.load(params);
|
|
30
|
+
} else {
|
|
31
|
+
throw `Invalid 'load' input in custom extension - ${this.extension.inputs.load}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#getParams() {
|
|
36
|
+
return {
|
|
37
|
+
target: this.target,
|
|
38
|
+
extension: this.extension,
|
|
39
|
+
payload: this.payload,
|
|
40
|
+
root_payload: this.root_payload,
|
|
41
|
+
result: this.result
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { CustomExtension }
|
package/src/extensions/index.js
CHANGED
|
@@ -4,11 +4,11 @@ const rp_analysis = require('./report-portal-analysis');
|
|
|
4
4
|
const rp_history = require('./report-portal-history');
|
|
5
5
|
const qc_test_summary = require('./quick-chart-test-summary');
|
|
6
6
|
const percy_analysis = require('./percy-analysis');
|
|
7
|
-
const custom = require('./custom');
|
|
8
7
|
const metadata = require('./metadata');
|
|
9
8
|
const { AIFailureSummaryExtension } = require('./ai-failure-summary.extension');
|
|
10
9
|
const { SmartAnalysisExtension } = require('./smart-analysis.extension');
|
|
11
10
|
const { CIInfoExtension } = require('./ci-info.extension');
|
|
11
|
+
const { CustomExtension } = require('./custom.extension');
|
|
12
12
|
const { EXTENSION } = require('../helpers/constants');
|
|
13
13
|
const { checkCondition } = require('../helpers/helper');
|
|
14
14
|
const logger = require('../utils/logger');
|
|
@@ -51,7 +51,7 @@ function getExtensionRunner(extension, options) {
|
|
|
51
51
|
case EXTENSION.PERCY_ANALYSIS:
|
|
52
52
|
return percy_analysis;
|
|
53
53
|
case EXTENSION.CUSTOM:
|
|
54
|
-
return
|
|
54
|
+
return new CustomExtension(options.target, extension, options.result, options.payload, options.root_payload);
|
|
55
55
|
case EXTENSION.METADATA:
|
|
56
56
|
return metadata;
|
|
57
57
|
case EXTENSION.CI_INFO:
|
|
@@ -39,19 +39,19 @@ class SmartAnalysisExtension extends BaseExtension {
|
|
|
39
39
|
|
|
40
40
|
const smart_analysis = [];
|
|
41
41
|
if (execution_metrics.newly_failed) {
|
|
42
|
-
smart_analysis.push(`⭕
|
|
42
|
+
smart_analysis.push(`⭕ Newly Failed: ${execution_metrics.newly_failed}`);
|
|
43
43
|
}
|
|
44
44
|
if (execution_metrics.always_failing) {
|
|
45
|
-
smart_analysis.push(`🔴
|
|
45
|
+
smart_analysis.push(`🔴 Always Failing: ${execution_metrics.always_failing}`);
|
|
46
46
|
}
|
|
47
|
-
if (execution_metrics.
|
|
48
|
-
smart_analysis.push(`🟠
|
|
47
|
+
if (execution_metrics.recurring_errors) {
|
|
48
|
+
smart_analysis.push(`🟠 Recurring Errors: ${execution_metrics.recurring_errors}`);
|
|
49
49
|
}
|
|
50
50
|
if (execution_metrics.flaky) {
|
|
51
|
-
smart_analysis.push(`🟡
|
|
51
|
+
smart_analysis.push(`🟡 Flaky: ${execution_metrics.flaky}`);
|
|
52
52
|
}
|
|
53
53
|
if (execution_metrics.recovered) {
|
|
54
|
-
smart_analysis.push(`🟢
|
|
54
|
+
smart_analysis.push(`🟢 Recovered: ${execution_metrics.recovered}`);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
this.text = smart_analysis.join(' | ');
|
package/src/helpers/ci.js
CHANGED
|
@@ -7,6 +7,9 @@ function getCIInformation() {
|
|
|
7
7
|
if (ENV.GITHUB_ACTIONS) {
|
|
8
8
|
return getGitHubActionsInformation();
|
|
9
9
|
}
|
|
10
|
+
if (ENV.GITLAB_CI) {
|
|
11
|
+
return getGitLabInformation();
|
|
12
|
+
}
|
|
10
13
|
if (ENV.JENKINS_URL) {
|
|
11
14
|
return getJenkinsInformation();
|
|
12
15
|
}
|
|
@@ -26,6 +29,7 @@ function getGitHubActionsInformation() {
|
|
|
26
29
|
build_url: ENV.GITHUB_SERVER_URL + '/' + ENV.GITHUB_REPOSITORY + '/actions/runs/' + ENV.GITHUB_RUN_ID,
|
|
27
30
|
build_number: ENV.GITHUB_RUN_NUMBER,
|
|
28
31
|
build_name: ENV.GITHUB_WORKFLOW,
|
|
32
|
+
build_reason: ENV.GITHUB_EVENT_NAME,
|
|
29
33
|
user: ENV.GITHUB_ACTOR,
|
|
30
34
|
}
|
|
31
35
|
}
|
|
@@ -41,6 +45,7 @@ function getAzureDevOpsInformation() {
|
|
|
41
45
|
build_url: ENV.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI + ENV.SYSTEM_TEAMPROJECT + '/_build/results?buildId=' + ENV.BUILD_BUILDID,
|
|
42
46
|
build_number: ENV.BUILD_BUILDNUMBER,
|
|
43
47
|
build_name: ENV.BUILD_DEFINITIONNAME,
|
|
48
|
+
build_reason: ENV.BUILD_REASON,
|
|
44
49
|
user: ENV.BUILD_REQUESTEDFOR
|
|
45
50
|
}
|
|
46
51
|
}
|
|
@@ -56,10 +61,27 @@ function getJenkinsInformation() {
|
|
|
56
61
|
build_url: ENV.BUILD_URL,
|
|
57
62
|
build_number: ENV.BUILD_NUMBER,
|
|
58
63
|
build_name: ENV.JOB_NAME,
|
|
64
|
+
build_reason: ENV.BUILD_CAUSE,
|
|
59
65
|
user: ENV.USER || ENV.USERNAME
|
|
60
66
|
}
|
|
61
67
|
}
|
|
62
68
|
|
|
69
|
+
function getGitLabInformation() {
|
|
70
|
+
return {
|
|
71
|
+
ci: 'GITLAB',
|
|
72
|
+
git: 'GITLAB',
|
|
73
|
+
repository_url: ENV.CI_PROJECT_URL,
|
|
74
|
+
repository_name: ENV.CI_PROJECT_NAME,
|
|
75
|
+
repository_ref: ENV.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME || ENV.CI_COMMIT_REF_NAME,
|
|
76
|
+
repository_commit_sha:ENV.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || ENV.CI_COMMIT_SHA,
|
|
77
|
+
build_url: ENV.CI_JOB_URL,
|
|
78
|
+
build_number: ENV.CI_JOB_ID,
|
|
79
|
+
build_name: ENV.CI_JOB_NAME,
|
|
80
|
+
build_reason: ENV.CI_PIPELINE_SOURCE,
|
|
81
|
+
user: ENV.GITLAB_USER_LOGIN || ENV.CI_COMMIT_AUTHOR
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
63
85
|
module.exports = {
|
|
64
86
|
getCIInformation
|
|
65
87
|
}
|
package/src/index.d.ts
CHANGED
package/src/targets/chat.js
CHANGED
|
@@ -4,6 +4,7 @@ const extension_manager = require('../extensions');
|
|
|
4
4
|
const { HOOK, STATUS } = require('../helpers/constants');
|
|
5
5
|
const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
|
|
6
6
|
const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
|
|
7
|
+
const logger = require('../utils/logger');
|
|
7
8
|
|
|
8
9
|
async function run({ result, target }) {
|
|
9
10
|
setTargetInputs(target);
|
|
@@ -14,6 +15,7 @@ async function run({ result, target }) {
|
|
|
14
15
|
} else {
|
|
15
16
|
await setFunctionalPayload({ result, target, payload, root_payload });
|
|
16
17
|
}
|
|
18
|
+
logger.info(`🔔 Publishing results to Chat...`);
|
|
17
19
|
return request.post({
|
|
18
20
|
url: target.inputs.url,
|
|
19
21
|
body: root_payload
|
|
@@ -111,7 +113,7 @@ function getFailureDetails(suite) {
|
|
|
111
113
|
for (let i = 0; i < cases.length; i++) {
|
|
112
114
|
const test_case = cases[i];
|
|
113
115
|
if (test_case.status === 'FAIL') {
|
|
114
|
-
text += `<b>Test</b>: ${test_case.name}<br><b>Error</b>: ${truncate(test_case.failure, 150)}<br><br>`;
|
|
116
|
+
text += `<b>Test</b>: ${test_case.name}<br><b>Error</b>: ${truncate(test_case.failure ?? 'N/A', 150)}<br><br>`;
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
119
|
return text;
|
|
@@ -144,9 +146,9 @@ async function setPerformancePayload({ result, target, payload, root_payload })
|
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
/**
|
|
147
|
-
*
|
|
149
|
+
*
|
|
148
150
|
* @param {object} param0
|
|
149
|
-
* @param {PerformanceTestResult} param0.result
|
|
151
|
+
* @param {PerformanceTestResult} param0.result
|
|
150
152
|
*/
|
|
151
153
|
async function setPerformanceMainBlock({ result, target, payload }) {
|
|
152
154
|
const title_text_with_emoji = getTitleTextWithEmoji({ result, target });
|
|
@@ -169,9 +171,9 @@ async function setPerformanceMainBlock({ result, target, payload }) {
|
|
|
169
171
|
}
|
|
170
172
|
|
|
171
173
|
/**
|
|
172
|
-
*
|
|
174
|
+
*
|
|
173
175
|
* @param {object} param0
|
|
174
|
-
* @param {PerformanceTestResult} param0.result
|
|
176
|
+
* @param {PerformanceTestResult} param0.result
|
|
175
177
|
*/
|
|
176
178
|
async function setTransactionBlock({ result, target, payload }) {
|
|
177
179
|
if (target.inputs.include_suites) {
|
package/src/targets/slack.js
CHANGED
|
@@ -2,12 +2,14 @@ const request = require('phin-retry');
|
|
|
2
2
|
const { getPercentage, truncate, getPrettyDuration } = require('../helpers/helper');
|
|
3
3
|
const extension_manager = require('../extensions');
|
|
4
4
|
const { HOOK, STATUS } = require('../helpers/constants');
|
|
5
|
+
const logger = require('../utils/logger');
|
|
5
6
|
|
|
6
7
|
const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
|
|
7
8
|
const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
|
|
8
9
|
const TestResult = require('test-results-parser/src/models/TestResult');
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
|
|
11
13
|
const COLORS = {
|
|
12
14
|
GOOD: '#36A64F',
|
|
13
15
|
WARNING: '#ECB22E',
|
|
@@ -22,7 +24,8 @@ async function run({ result, target }) {
|
|
|
22
24
|
} else {
|
|
23
25
|
await setFunctionalPayload({ result, target, payload });
|
|
24
26
|
}
|
|
25
|
-
const message = getRootPayload({ result, payload });
|
|
27
|
+
const message = getRootPayload({ result, target, payload });
|
|
28
|
+
logger.info(`🔔 Publishing results to Slack...`);
|
|
26
29
|
return request.post({
|
|
27
30
|
url: target.inputs.url,
|
|
28
31
|
body: message
|
|
@@ -66,12 +69,12 @@ function setMainBlock({ result, target, payload }) {
|
|
|
66
69
|
});
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
function getTitleText(result, target) {
|
|
72
|
+
function getTitleText(result, target, {allowTitleLink = true} = {}) {
|
|
70
73
|
let text = target.inputs.title ? target.inputs.title : result.name;
|
|
71
74
|
if (target.inputs.title_suffix) {
|
|
72
75
|
text = `${text} ${target.inputs.title_suffix}`;
|
|
73
76
|
}
|
|
74
|
-
if (target.inputs.title_link) {
|
|
77
|
+
if (allowTitleLink && target.inputs.title_link) {
|
|
75
78
|
text = `<${target.inputs.title_link}|${text}>`;
|
|
76
79
|
}
|
|
77
80
|
return text;
|
|
@@ -129,7 +132,7 @@ function getFailureDetails(suite) {
|
|
|
129
132
|
for (let i = 0; i < cases.length; i++) {
|
|
130
133
|
const test_case = cases[i];
|
|
131
134
|
if (test_case.status === 'FAIL') {
|
|
132
|
-
text += `*Test*: ${test_case.name}\n*Error*: ${truncate(test_case.failure, 150)}\n\n`;
|
|
135
|
+
text += `*Test*: ${test_case.name}\n*Error*: ${truncate(test_case.failure ?? 'N/A', 150)}\n\n`;
|
|
133
136
|
}
|
|
134
137
|
}
|
|
135
138
|
return {
|
|
@@ -142,12 +145,12 @@ function getFailureDetails(suite) {
|
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
/**
|
|
145
|
-
*
|
|
146
|
-
* @param {object} param0
|
|
147
|
-
* @param {PerformanceTestResult | TestResult} param0.result
|
|
148
|
-
* @returns
|
|
148
|
+
*
|
|
149
|
+
* @param {object} param0
|
|
150
|
+
* @param {PerformanceTestResult | TestResult} param0.result
|
|
151
|
+
* @returns
|
|
149
152
|
*/
|
|
150
|
-
function getRootPayload({ result, payload }) {
|
|
153
|
+
function getRootPayload({ result, target, payload }) {
|
|
151
154
|
let color = COLORS.GOOD;
|
|
152
155
|
if (result.status !== 'PASS') {
|
|
153
156
|
let somePassed = true;
|
|
@@ -166,7 +169,8 @@ function getRootPayload({ result, payload }) {
|
|
|
166
169
|
"attachments": [
|
|
167
170
|
{
|
|
168
171
|
"color": color,
|
|
169
|
-
"blocks": payload.blocks
|
|
172
|
+
"blocks": payload.blocks,
|
|
173
|
+
"fallback": `${getTitleText(result, target, {allowTitleLink: false})}\nResults: ${getResultText(result)}`,
|
|
170
174
|
}
|
|
171
175
|
]
|
|
172
176
|
};
|
|
@@ -181,9 +185,9 @@ async function setPerformancePayload({ result, target, payload }) {
|
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
/**
|
|
184
|
-
*
|
|
185
|
-
* @param {object} param0
|
|
186
|
-
* @param {PerformanceTestResult} param0.result
|
|
188
|
+
*
|
|
189
|
+
* @param {object} param0
|
|
190
|
+
* @param {PerformanceTestResult} param0.result
|
|
187
191
|
*/
|
|
188
192
|
async function setPerformanceMainBlock({ result, target, payload }) {
|
|
189
193
|
let text = `*${getTitleText(result, target)}*\n`;
|
|
@@ -205,9 +209,9 @@ async function setPerformanceMainBlock({ result, target, payload }) {
|
|
|
205
209
|
}
|
|
206
210
|
|
|
207
211
|
/**
|
|
208
|
-
*
|
|
209
|
-
* @param {object} param0
|
|
210
|
-
* @param {PerformanceTestResult} param0.result
|
|
212
|
+
*
|
|
213
|
+
* @param {object} param0
|
|
214
|
+
* @param {PerformanceTestResult} param0.result
|
|
211
215
|
*/
|
|
212
216
|
async function setTransactionBlock({ result, target, payload }) {
|
|
213
217
|
if (target.inputs.include_suites) {
|
package/src/targets/teams.js
CHANGED
|
@@ -3,14 +3,15 @@ const { getPercentage, truncate, getPrettyDuration } = require('../helpers/helpe
|
|
|
3
3
|
const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
|
|
4
4
|
const extension_manager = require('../extensions');
|
|
5
5
|
const { HOOK, STATUS } = require('../helpers/constants');
|
|
6
|
+
const logger = require('../utils/logger');
|
|
6
7
|
|
|
7
8
|
const TestResult = require('test-results-parser/src/models/TestResult');
|
|
8
9
|
const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
|
-
* @param {object} param0
|
|
12
|
-
* @param {PerformanceTestResult | TestResult} param0.result
|
|
13
|
-
* @returns
|
|
12
|
+
* @param {object} param0
|
|
13
|
+
* @param {PerformanceTestResult | TestResult} param0.result
|
|
14
|
+
* @returns
|
|
14
15
|
*/
|
|
15
16
|
async function run({ result, target }) {
|
|
16
17
|
setTargetInputs(target);
|
|
@@ -22,6 +23,7 @@ async function run({ result, target }) {
|
|
|
22
23
|
await setFunctionalPayload({ result, target, payload, root_payload });
|
|
23
24
|
}
|
|
24
25
|
setRootPayload(root_payload, payload);
|
|
26
|
+
logger.info(`🔔 Publishing results to Teams...`);
|
|
25
27
|
return request.post({
|
|
26
28
|
url: target.inputs.url,
|
|
27
29
|
body: root_payload
|
|
@@ -183,7 +185,7 @@ function getFailureDetailsFactSets(suite) {
|
|
|
183
185
|
},
|
|
184
186
|
{
|
|
185
187
|
"title": "Error:",
|
|
186
|
-
"value": truncate(test_case.failure, 150)
|
|
188
|
+
"value": truncate(test_case.failure ?? 'N/A', 150)
|
|
187
189
|
}
|
|
188
190
|
]
|
|
189
191
|
});
|
|
@@ -209,8 +211,8 @@ function setRootPayload(root_payload, payload) {
|
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
/**
|
|
212
|
-
* @param {object} param0
|
|
213
|
-
* @param {PerformanceTestResult} param0.result
|
|
214
|
+
* @param {object} param0
|
|
215
|
+
* @param {PerformanceTestResult} param0.result
|
|
214
216
|
*/
|
|
215
217
|
async function setMainBlockForPerformance({ result, target, payload }) {
|
|
216
218
|
const total = result.transactions.length;
|
|
@@ -245,8 +247,8 @@ async function getFactMetrics({ metrics, target, result }) {
|
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
/**
|
|
248
|
-
* @param {object} param0
|
|
249
|
-
* @param {PerformanceTestResult} param0.result
|
|
250
|
+
* @param {object} param0
|
|
251
|
+
* @param {PerformanceTestResult} param0.result
|
|
250
252
|
*/
|
|
251
253
|
async function setTransactionBlock({ result, target, payload }) {
|
|
252
254
|
if (target.inputs.include_suites) {
|
package/src/extensions/custom.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const { HOOK, STATUS } = require('../helpers/constants');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* @param {object} param0
|
|
7
|
-
* @param {import('../index').CustomExtension} param0.extension
|
|
8
|
-
*/
|
|
9
|
-
async function run({ target, extension, payload, root_payload, result }) {
|
|
10
|
-
if (typeof extension.inputs.load === 'string') {
|
|
11
|
-
const cwd = process.cwd();
|
|
12
|
-
const extension_runner = require(path.join(cwd, extension.inputs.load));
|
|
13
|
-
await extension_runner.run({ target, extension, payload, root_payload, result });
|
|
14
|
-
} else if (typeof extension.inputs.load === 'function') {
|
|
15
|
-
await extension.inputs.load({ target, extension, payload, root_payload, result });
|
|
16
|
-
} else {
|
|
17
|
-
throw `Invalid 'load' input in custom extension - ${extension.inputs.load}`;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const default_options = {
|
|
22
|
-
hook: HOOK.END,
|
|
23
|
-
condition: STATUS.PASS_OR_FAIL
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = {
|
|
27
|
-
run,
|
|
28
|
-
default_options
|
|
29
|
-
}
|