testbeats 2.0.0
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/LICENSE +21 -0
- package/README.md +60 -0
- package/package.json +65 -0
- package/src/beats/index.js +74 -0
- package/src/cli.js +23 -0
- package/src/commands/publish.js +54 -0
- package/src/extensions/ci-info.js +134 -0
- package/src/extensions/custom.js +29 -0
- package/src/extensions/hyperlinks.js +60 -0
- package/src/extensions/index.js +63 -0
- package/src/extensions/mentions.js +112 -0
- package/src/extensions/metadata.js +89 -0
- package/src/extensions/percy-analysis.js +203 -0
- package/src/extensions/quick-chart-test-summary.js +82 -0
- package/src/extensions/report-portal-analysis.js +95 -0
- package/src/extensions/report-portal-history.js +105 -0
- package/src/helpers/ci.js +62 -0
- package/src/helpers/constants.js +45 -0
- package/src/helpers/extension.helper.js +107 -0
- package/src/helpers/helper.js +102 -0
- package/src/helpers/metadata.helper.js +115 -0
- package/src/helpers/percy.js +60 -0
- package/src/helpers/performance.js +141 -0
- package/src/helpers/report-portal.js +47 -0
- package/src/index.d.ts +243 -0
- package/src/index.js +14 -0
- package/src/targets/chat.js +242 -0
- package/src/targets/custom.js +28 -0
- package/src/targets/delay.js +19 -0
- package/src/targets/index.js +39 -0
- package/src/targets/influx.js +208 -0
- package/src/targets/slack.js +266 -0
- package/src/targets/teams.js +304 -0
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { PerformanceParseOptions } from 'performance-results-parser';
|
|
2
|
+
import PerformanceTestResult from 'performance-results-parser/src/models/PerformanceTestResult';
|
|
3
|
+
import { Schedule, User } from 'rosters';
|
|
4
|
+
import { ParseOptions } from 'test-results-parser';
|
|
5
|
+
import TestResult from 'test-results-parser/src/models/TestResult';
|
|
6
|
+
|
|
7
|
+
export type ExtensionName = 'report-portal-analysis' | 'hyperlinks' | 'mentions' | 'report-portal-history' | 'quick-chart-test-summary' | 'metadata' | 'ci-info' | 'custom';
|
|
8
|
+
export type Hook = 'start' | 'end' | 'after-summary';
|
|
9
|
+
export type TargetName = 'slack' | 'teams' | 'chat' | 'custom' | 'delay';
|
|
10
|
+
export type PublishReportType = 'test-summary' | 'test-summary-slim' | 'failure-details';
|
|
11
|
+
|
|
12
|
+
export interface ConditionFunctionContext {
|
|
13
|
+
target: Target;
|
|
14
|
+
extension?: Extension,
|
|
15
|
+
result: TestResult;
|
|
16
|
+
}
|
|
17
|
+
export type ConditionFunction = (ctx: ConditionFunctionContext) => boolean | Promise<boolean>;
|
|
18
|
+
export type Condition = 'pass' | 'fail' | 'passOrFail' | 'always' | 'never' | ConditionFunction;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Extensions
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export interface ExtensionInputs {
|
|
25
|
+
title?: string;
|
|
26
|
+
title_link?: string;
|
|
27
|
+
separator?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ReportPortalAnalysisInputs extends ExtensionInputs {
|
|
31
|
+
url: string;
|
|
32
|
+
api_key: string;
|
|
33
|
+
project: string;
|
|
34
|
+
launch_id?: string;
|
|
35
|
+
launch_name?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ReportPortalHistoryInputs extends ExtensionInputs {
|
|
39
|
+
url: string;
|
|
40
|
+
api_key: string;
|
|
41
|
+
project: string;
|
|
42
|
+
launch_id?: string;
|
|
43
|
+
launch_name?: string;
|
|
44
|
+
history_depth?: number;
|
|
45
|
+
link_history_via?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface QuickChartTestSummaryInputs {
|
|
49
|
+
url: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface MentionInputs extends ExtensionInputs {
|
|
53
|
+
users?: User[];
|
|
54
|
+
schedule?: Schedule;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface CIInfoInputs extends ExtensionInputs {
|
|
58
|
+
show_repository?: boolean;
|
|
59
|
+
show_repository_branch?: boolean;
|
|
60
|
+
show_build?: boolean;
|
|
61
|
+
data?: Metadata[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface Extension {
|
|
65
|
+
name: ExtensionName;
|
|
66
|
+
condition?: Condition;
|
|
67
|
+
hook?: Hook;
|
|
68
|
+
inputs?: ReportPortalAnalysisInputs | ReportPortalHistoryInputs | HyperlinkInputs | MentionInputs | QuickChartTestSummaryInputs | PercyAnalysisInputs | CustomExtensionInputs | MetadataInputs | CIInfoInputs;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface PercyAnalysisInputs extends ExtensionInputs {
|
|
72
|
+
url?: string;
|
|
73
|
+
token?: string;
|
|
74
|
+
retries?: number;
|
|
75
|
+
build_id?: string;
|
|
76
|
+
project_id?: string;
|
|
77
|
+
project_name?: string;
|
|
78
|
+
organization_uid?: string;
|
|
79
|
+
title_link_to_build?: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface PercyAnalysisOutputs {
|
|
83
|
+
build?: object;
|
|
84
|
+
project?: object;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface PercyAnalysisExtension extends Extension {
|
|
88
|
+
inputs?: PercyAnalysisInputs;
|
|
89
|
+
outputs?: PercyAnalysisOutputs;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface CustomExtensionFunctionContext {
|
|
93
|
+
target: Target;
|
|
94
|
+
extension: Extension,
|
|
95
|
+
result: TestResult;
|
|
96
|
+
payload: any;
|
|
97
|
+
root_payload: any;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type CustomExtensionFunction = (ctx: CustomExtensionFunctionContext) => void | Promise<void>;
|
|
101
|
+
|
|
102
|
+
export interface CustomExtensionInputs extends ExtensionInputs {
|
|
103
|
+
load: string | CustomExtensionFunction;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface CustomExtension extends Extension {
|
|
107
|
+
inputs?: CustomExtensionInputs;
|
|
108
|
+
outputs?: any;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface LinkUrlFunctionContext {
|
|
112
|
+
target: Target;
|
|
113
|
+
extension: HyperlinksExtension,
|
|
114
|
+
result: TestResult;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export type LinkUrlFunction = (ctx: LinkUrlFunctionContext) => string | Promise<string>;
|
|
118
|
+
|
|
119
|
+
export interface Link {
|
|
120
|
+
text: string;
|
|
121
|
+
url: string | LinkUrlFunction;
|
|
122
|
+
condition?: Condition;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface HyperlinkInputs extends ExtensionInputs {
|
|
126
|
+
links: Link[];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface HyperlinksExtension extends Extension {
|
|
130
|
+
inputs?: HyperlinkInputs;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface Metadata {
|
|
134
|
+
label?: string;
|
|
135
|
+
key?: string;
|
|
136
|
+
value: string;
|
|
137
|
+
type?: string;
|
|
138
|
+
condition?: Condition;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface MetadataInputs extends ExtensionInputs {
|
|
142
|
+
data?: Metadata[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface MetadataExtension extends Extension {
|
|
146
|
+
inputs?: MetadataInputs;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Targets
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
export interface MetricConfig {
|
|
154
|
+
name: string;
|
|
155
|
+
condition: Condition;
|
|
156
|
+
fields: string[];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface TargetInputs {
|
|
160
|
+
url: string;
|
|
161
|
+
title?: string;
|
|
162
|
+
title_suffix?: string;
|
|
163
|
+
title_link?: string;
|
|
164
|
+
duration?: string;
|
|
165
|
+
publish?: PublishReportType;
|
|
166
|
+
only_failures?: boolean;
|
|
167
|
+
max_suites?: number;
|
|
168
|
+
metrics?: MetricConfig[];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface SlackInputs extends TargetInputs { }
|
|
172
|
+
|
|
173
|
+
export interface TeamsInputs extends TargetInputs {
|
|
174
|
+
width?: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface ChatInputs extends TargetInputs { }
|
|
178
|
+
|
|
179
|
+
export interface InfluxDBTargetInputs {
|
|
180
|
+
url: string;
|
|
181
|
+
version?: string;
|
|
182
|
+
db: string;
|
|
183
|
+
username?: string;
|
|
184
|
+
password?: string;
|
|
185
|
+
org?: string;
|
|
186
|
+
bucket?: string;
|
|
187
|
+
precision?: string;
|
|
188
|
+
token?: string;
|
|
189
|
+
measurement_perf_run?: string;
|
|
190
|
+
measurement_perf_transaction?: string;
|
|
191
|
+
measurement_test_run?: string;
|
|
192
|
+
measurement_test_suite?: string;
|
|
193
|
+
measurement_test_case?: string;
|
|
194
|
+
tags?: object;
|
|
195
|
+
fields?: object;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface CustomTargetFunctionContext {
|
|
199
|
+
target: Target;
|
|
200
|
+
result: TestResult;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export type CustomTargetFunction = (ctx: CustomTargetFunctionContext) => void | Promise<void>;
|
|
204
|
+
|
|
205
|
+
export interface CustomTargetInputs {
|
|
206
|
+
load: string | CustomTargetFunction;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface Target {
|
|
210
|
+
name: TargetName;
|
|
211
|
+
condition: Condition;
|
|
212
|
+
inputs: SlackInputs | TeamsInputs | ChatInputs | CustomTargetInputs | InfluxDBTargetInputs;
|
|
213
|
+
extensions?: Extension[];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface CustomResultOptions {
|
|
217
|
+
type: string;
|
|
218
|
+
result: TestResult | PerformanceTestResult;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export interface PublishReport {
|
|
222
|
+
api_key?: string;
|
|
223
|
+
project?: string;
|
|
224
|
+
run?: string;
|
|
225
|
+
targets?: Target[];
|
|
226
|
+
results?: ParseOptions[] | PerformanceParseOptions[] | CustomResultOptions[];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface PublishConfig {
|
|
230
|
+
api_key?: string;
|
|
231
|
+
project?: string;
|
|
232
|
+
run?: string;
|
|
233
|
+
targets?: Target[];
|
|
234
|
+
results?: ParseOptions[] | PerformanceParseOptions[] | CustomResultOptions[];
|
|
235
|
+
reports?: PublishReport[];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface PublishOptions {
|
|
239
|
+
config: string | PublishConfig;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function publish(options: PublishOptions): Promise<any>
|
|
243
|
+
export function defineConfig(config: PublishConfig): PublishConfig
|
package/src/index.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
const request = require('phin-retry');
|
|
2
|
+
const { getTitleText, getResultText, truncate, getPrettyDuration } = require('../helpers/helper');
|
|
3
|
+
const extension_manager = require('../extensions');
|
|
4
|
+
const { HOOK, STATUS } = require('../helpers/constants');
|
|
5
|
+
const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult');
|
|
6
|
+
const { getValidMetrics, getMetricValuesText } = require('../helpers/performance');
|
|
7
|
+
|
|
8
|
+
async function run({ result, target }) {
|
|
9
|
+
setTargetInputs(target);
|
|
10
|
+
const root_payload = getRootPayload();
|
|
11
|
+
const payload = root_payload.cards[0];
|
|
12
|
+
if (result instanceof PerformanceTestResult) {
|
|
13
|
+
await setPerformancePayload({ result, target, payload, root_payload });
|
|
14
|
+
} else {
|
|
15
|
+
await setFunctionalPayload({ result, target, payload, root_payload });
|
|
16
|
+
}
|
|
17
|
+
return request.post({
|
|
18
|
+
url: target.inputs.url,
|
|
19
|
+
body: root_payload
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function setFunctionalPayload({ result, target, payload, root_payload }) {
|
|
24
|
+
await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.START });
|
|
25
|
+
setMainBlock({ result, target, payload });
|
|
26
|
+
await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.AFTER_SUMMARY });
|
|
27
|
+
setSuiteBlock({ result, target, payload });
|
|
28
|
+
await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.END });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function setTargetInputs(target) {
|
|
32
|
+
target.inputs = Object.assign({}, default_inputs, target.inputs);
|
|
33
|
+
if (target.inputs.publish === 'test-summary-slim') {
|
|
34
|
+
target.inputs.include_suites = false;
|
|
35
|
+
}
|
|
36
|
+
if (target.inputs.publish === 'failure-details') {
|
|
37
|
+
target.inputs.include_failure_details = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getRootPayload() {
|
|
42
|
+
return {
|
|
43
|
+
"cards": [
|
|
44
|
+
{
|
|
45
|
+
"sections": []
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function setMainBlock({ result, target, payload }) {
|
|
52
|
+
const title_text_with_emoji = getTitleTextWithEmoji({ result, target });
|
|
53
|
+
const result_text = getResultText({ result });
|
|
54
|
+
const duration_text = getPrettyDuration(result.duration, target.inputs.duration);
|
|
55
|
+
|
|
56
|
+
const text = `<b>${title_text_with_emoji}</b><br><br><b>Results</b>: ${result_text}<br><b>Duration</b>: ${duration_text}`;
|
|
57
|
+
payload.sections.push({
|
|
58
|
+
"widgets": [
|
|
59
|
+
{
|
|
60
|
+
"textParagraph": {
|
|
61
|
+
text
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function setSuiteBlock({ result, target, payload }) {
|
|
69
|
+
let suite_attachments_length = 0;
|
|
70
|
+
if (target.inputs.include_suites) {
|
|
71
|
+
let texts = [];
|
|
72
|
+
for (let i = 0; i < result.suites.length && suite_attachments_length < target.inputs.max_suites; i++) {
|
|
73
|
+
const suite = result.suites[i];
|
|
74
|
+
if (target.inputs.only_failures && suite.status !== 'FAIL') {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// if suites length eq to 1 then main block will include suite summary
|
|
78
|
+
if (result.suites.length > 1) {
|
|
79
|
+
texts.push(getSuiteSummary({ target, suite }));
|
|
80
|
+
suite_attachments_length += 1;
|
|
81
|
+
}
|
|
82
|
+
if (target.inputs.include_failure_details) {
|
|
83
|
+
texts.push(getFailureDetails(suite));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (texts.length > 0) {
|
|
87
|
+
payload.sections.push({
|
|
88
|
+
"widgets": [
|
|
89
|
+
{
|
|
90
|
+
"textParagraph": {
|
|
91
|
+
"text": texts.join("<br><br>")
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getSuiteSummary({ target, suite }) {
|
|
101
|
+
const emoji = suite.status === 'PASS' ? '✅' : '❌';
|
|
102
|
+
const suite_title = `${emoji} ${suite.name}`;
|
|
103
|
+
const result_text = getResultText({ result: suite });
|
|
104
|
+
const duration_text = getPrettyDuration(suite.duration, target.inputs.duration);
|
|
105
|
+
return `<b>${suite_title}</b><br><br><b>Results</b>: ${result_text}<br><b>Duration</b>: ${duration_text}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getFailureDetails(suite) {
|
|
109
|
+
let text = '';
|
|
110
|
+
const cases = suite.cases;
|
|
111
|
+
for (let i = 0; i < cases.length; i++) {
|
|
112
|
+
const test_case = cases[i];
|
|
113
|
+
if (test_case.status === 'FAIL') {
|
|
114
|
+
text += `<b>Test</b>: ${test_case.name}<br><b>Error</b>: ${truncate(test_case.failure, 150)}<br><br>`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return text;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getTitleTextWithEmoji({ result, target }) {
|
|
121
|
+
const emoji = result.status === 'PASS' ? '✅' : '❌';
|
|
122
|
+
const title_text = getTitleText({ result, target });
|
|
123
|
+
|
|
124
|
+
let title_text_with_emoji = '';
|
|
125
|
+
if (target.inputs.include_suites === false) {
|
|
126
|
+
title_text_with_emoji = `${emoji} ${title_text}`;
|
|
127
|
+
} else if (result.suites && result.suites.length > 1 || result.transactions && result.transactions.length > 1) {
|
|
128
|
+
title_text_with_emoji = title_text;
|
|
129
|
+
} else {
|
|
130
|
+
title_text_with_emoji = `${emoji} ${title_text}`;
|
|
131
|
+
}
|
|
132
|
+
if (target.inputs.title_link) {
|
|
133
|
+
title_text_with_emoji = `<a href="${target.inputs.title_link}">${title_text_with_emoji}</a>`;
|
|
134
|
+
}
|
|
135
|
+
return title_text_with_emoji;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function setPerformancePayload({ result, target, payload, root_payload }) {
|
|
139
|
+
await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.START });
|
|
140
|
+
await setPerformanceMainBlock({ result, target, payload });
|
|
141
|
+
await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.AFTER_SUMMARY });
|
|
142
|
+
await setTransactionBlock({ result, target, payload });
|
|
143
|
+
await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.END });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
*
|
|
148
|
+
* @param {object} param0
|
|
149
|
+
* @param {PerformanceTestResult} param0.result
|
|
150
|
+
*/
|
|
151
|
+
async function setPerformanceMainBlock({ result, target, payload }) {
|
|
152
|
+
const title_text_with_emoji = getTitleTextWithEmoji({ result, target });
|
|
153
|
+
const result_text = getResultText({ result });
|
|
154
|
+
let text = `<b>${title_text_with_emoji}</b><br><br><b>Results</b>: ${result_text}<br>`;
|
|
155
|
+
const valid_metrics = await getValidMetrics({ metrics: result.metrics, target, result });
|
|
156
|
+
for (let i = 0; i < valid_metrics.length; i++) {
|
|
157
|
+
const metric = valid_metrics[i];
|
|
158
|
+
text += `<br><b>${metric.name}</b>: ${getMetricValuesText({ metric, target, result })}`;
|
|
159
|
+
}
|
|
160
|
+
payload.sections.push({
|
|
161
|
+
"widgets": [
|
|
162
|
+
{
|
|
163
|
+
"textParagraph": {
|
|
164
|
+
text
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
*
|
|
173
|
+
* @param {object} param0
|
|
174
|
+
* @param {PerformanceTestResult} param0.result
|
|
175
|
+
*/
|
|
176
|
+
async function setTransactionBlock({ result, target, payload }) {
|
|
177
|
+
if (target.inputs.include_suites) {
|
|
178
|
+
let texts = [];
|
|
179
|
+
for (let i = 0; i < result.transactions.length; i++) {
|
|
180
|
+
const transaction = result.transactions[i];
|
|
181
|
+
if (target.inputs.only_failures && transaction.status !== 'FAIL') {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
// if transactions length eq to 1 then main block will include suite summary
|
|
185
|
+
if (result.transactions.length > 1) {
|
|
186
|
+
texts.push(await getTransactionSummary({ target, transaction, }));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (texts.length > 0) {
|
|
190
|
+
payload.sections.push({
|
|
191
|
+
"widgets": [
|
|
192
|
+
{
|
|
193
|
+
"textParagraph": {
|
|
194
|
+
"text": texts.join("<br><br>")
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function getTransactionSummary({ target, transaction }) {
|
|
204
|
+
const emoji = transaction.status === 'PASS' ? '✅' : '❌';
|
|
205
|
+
const suite_title = `${emoji} ${transaction.name}`;
|
|
206
|
+
let text = `<b>${suite_title}</b><br>`;
|
|
207
|
+
const valid_metrics = await getValidMetrics({ metrics: transaction.metrics, target, result: transaction });
|
|
208
|
+
for (let i = 0; i < valid_metrics.length; i++) {
|
|
209
|
+
const metric = valid_metrics[i];
|
|
210
|
+
text += `<br><b>${metric.name}</b>: ${getMetricValuesText({ metric, target })}`;
|
|
211
|
+
}
|
|
212
|
+
return text;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
const default_options = {
|
|
217
|
+
condition: STATUS.PASS_OR_FAIL
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const default_inputs = {
|
|
221
|
+
publish: 'test-summary',
|
|
222
|
+
include_suites: true,
|
|
223
|
+
max_suites: 10,
|
|
224
|
+
only_failures: false,
|
|
225
|
+
include_failure_details: false,
|
|
226
|
+
duration: '',
|
|
227
|
+
metrics: [
|
|
228
|
+
{
|
|
229
|
+
"name": "Samples",
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"name": "Duration",
|
|
233
|
+
"condition": "always",
|
|
234
|
+
"fields": ["avg", "p95"]
|
|
235
|
+
}
|
|
236
|
+
]
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
module.exports = {
|
|
240
|
+
run,
|
|
241
|
+
default_options
|
|
242
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { STATUS } = require('../helpers/constants');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {object} param0
|
|
7
|
+
* @param {import('../index').Target} param0.target
|
|
8
|
+
*/
|
|
9
|
+
async function run({result, target}) {
|
|
10
|
+
if (typeof target.inputs.load === 'string') {
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const target_runner = require(path.join(cwd, target.inputs.load));
|
|
13
|
+
await target_runner.run({ target, result });
|
|
14
|
+
} else if (typeof target.inputs.load === 'function') {
|
|
15
|
+
await target.inputs.load({ target, result });
|
|
16
|
+
} else {
|
|
17
|
+
throw `Invalid 'load' input in custom target - ${target.inputs.load}`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const default_options = {
|
|
22
|
+
condition: STATUS.PASS_OR_FAIL
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
run,
|
|
27
|
+
default_options
|
|
28
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { STATUS } = require("../helpers/constants");
|
|
2
|
+
|
|
3
|
+
async function run({ target }) {
|
|
4
|
+
target.inputs = Object.assign({}, default_inputs, target.inputs);
|
|
5
|
+
await new Promise(resolve => setTimeout(resolve, target.inputs.seconds * 1000));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const default_options = {
|
|
9
|
+
condition: STATUS.PASS_OR_FAIL
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const default_inputs = {
|
|
13
|
+
seconds: 5
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
run,
|
|
18
|
+
default_options
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const teams = require('./teams');
|
|
2
|
+
const slack = require('./slack');
|
|
3
|
+
const chat = require('./chat');
|
|
4
|
+
const custom = require('./custom');
|
|
5
|
+
const delay = require('./delay');
|
|
6
|
+
const influx = require('./influx');
|
|
7
|
+
const { TARGET } = require('../helpers/constants');
|
|
8
|
+
const { checkCondition } = require('../helpers/helper');
|
|
9
|
+
|
|
10
|
+
function getTargetRunner(target) {
|
|
11
|
+
switch (target.name) {
|
|
12
|
+
case TARGET.TEAMS:
|
|
13
|
+
return teams;
|
|
14
|
+
case TARGET.SLACK:
|
|
15
|
+
return slack;
|
|
16
|
+
case TARGET.CHAT:
|
|
17
|
+
return chat;
|
|
18
|
+
case TARGET.CUSTOM:
|
|
19
|
+
return custom;
|
|
20
|
+
case TARGET.DELAY:
|
|
21
|
+
return delay;
|
|
22
|
+
case TARGET.INFLUX:
|
|
23
|
+
return influx;
|
|
24
|
+
default:
|
|
25
|
+
return require(target.name);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function run(target, result) {
|
|
30
|
+
const target_runner = getTargetRunner(target);
|
|
31
|
+
const target_options = Object.assign({}, target_runner.default_options, target);
|
|
32
|
+
if (await checkCondition({ condition: target_options.condition, result, target })) {
|
|
33
|
+
await target_runner.run({result, target});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
run
|
|
39
|
+
}
|