testbeats 2.2.5 → 2.2.7
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/commands/publish.command.js +30 -11
- package/src/extensions/ai-failure-summary.extension.js +1 -1
- package/src/extensions/base.extension.js +1 -1
- package/src/helpers/constants.js +1 -0
- package/src/index.d.ts +16 -2
- package/src/platforms/base.platform.js +10 -0
- package/src/platforms/index.js +2 -1
- package/src/platforms/slack.platform.js +8 -1
- package/src/targets/base.target.js +45 -0
- package/src/targets/custom.target.js +31 -0
- package/src/targets/delay.target.js +24 -0
- package/src/targets/http.target.js +36 -0
- package/src/targets/index.js +10 -6
- package/src/targets/slack.js +25 -4
- package/src/targets/custom.js +0 -28
- package/src/targets/delay.js +0 -19
package/package.json
CHANGED
|
@@ -173,21 +173,40 @@ class PublishCommand {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
if (target.inputs) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
176
|
+
this.#validateURL(target);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
logger.debug("Validating targets - Successful!")
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
#validateURL(target) {
|
|
183
|
+
const inputs = target.inputs;
|
|
184
|
+
if (target.name === 'slack' || target.name === 'teams' || target.name === 'chat') {
|
|
185
|
+
if (inputs.token) {
|
|
186
|
+
if (!Array.isArray(inputs.channels)) {
|
|
187
|
+
throw new Error(`channels in ${target.name} target inputs must be an array`);
|
|
188
|
+
}
|
|
189
|
+
if (!inputs.channels.length) {
|
|
190
|
+
throw new Error(`at least one channel must be defined in ${target.name} target inputs`);
|
|
191
|
+
}
|
|
192
|
+
for (const channel of inputs.channels) {
|
|
193
|
+
if (typeof channel !== 'string') {
|
|
194
|
+
throw new Error(`channel in ${target.name} target inputs must be a string`);
|
|
186
195
|
}
|
|
187
196
|
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!inputs.url) {
|
|
201
|
+
throw new Error(`missing url in ${target.name} target inputs`);
|
|
202
|
+
}
|
|
203
|
+
if (typeof inputs.url !== 'string') {
|
|
204
|
+
throw new Error(`url in ${target.name} target inputs must be a string`);
|
|
205
|
+
}
|
|
206
|
+
if (!inputs.url.startsWith('http')) {
|
|
207
|
+
throw new Error(`url in ${target.name} target inputs must start with 'http' or 'https'`);
|
|
188
208
|
}
|
|
189
209
|
}
|
|
190
|
-
logger.debug("Validating targets - Successful!")
|
|
191
210
|
}
|
|
192
211
|
|
|
193
212
|
#processResults() {
|
|
@@ -36,7 +36,7 @@ class AIFailureSummaryExtension extends BaseExtension {
|
|
|
36
36
|
* @type {import('../beats/beats.types').IBeatExecutionMetric}
|
|
37
37
|
*/
|
|
38
38
|
const execution_metrics = data.execution_metrics[0];
|
|
39
|
-
this.text = execution_metrics.failure_summary;
|
|
39
|
+
this.text = this.platform.code(execution_metrics.failure_summary);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
package/src/helpers/constants.js
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface ITarget {
|
|
|
10
10
|
name: TargetName;
|
|
11
11
|
enable?: string | boolean;
|
|
12
12
|
condition?: Condition;
|
|
13
|
-
inputs?: SlackInputs | TeamsInputs | ChatInputs | GitHubInputs |
|
|
13
|
+
inputs?: SlackInputs | TeamsInputs | ChatInputs | GitHubInputs | ICustomTargetInputs | InfluxDBTargetInputs;
|
|
14
14
|
extensions?: IExtension[];
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -234,6 +234,8 @@ export interface TargetInputs {
|
|
|
234
234
|
|
|
235
235
|
export interface SlackInputs extends TargetInputs {
|
|
236
236
|
message_format?: 'blocks' | 'attachments';
|
|
237
|
+
token?: string;
|
|
238
|
+
channels?: string[];
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
export interface TeamsInputs extends TargetInputs {
|
|
@@ -275,11 +277,19 @@ export interface CustomTargetFunctionContext {
|
|
|
275
277
|
|
|
276
278
|
export type CustomTargetFunction = (ctx: CustomTargetFunctionContext) => void | Promise<void>;
|
|
277
279
|
|
|
278
|
-
export interface
|
|
280
|
+
export interface ICustomTargetInputs {
|
|
279
281
|
load: string | CustomTargetFunction;
|
|
280
282
|
}
|
|
281
283
|
|
|
284
|
+
export interface IDelayTargetInputs {
|
|
285
|
+
seconds: number;
|
|
286
|
+
}
|
|
282
287
|
|
|
288
|
+
export interface IHttpTargetInputs {
|
|
289
|
+
url: string;
|
|
290
|
+
method: string;
|
|
291
|
+
headers: object;
|
|
292
|
+
}
|
|
283
293
|
|
|
284
294
|
export interface CustomResultOptions {
|
|
285
295
|
type: string;
|
|
@@ -337,5 +347,9 @@ export type IExtensionDefaultOptions = {
|
|
|
337
347
|
condition: Condition
|
|
338
348
|
}
|
|
339
349
|
|
|
350
|
+
export type ITargetDefaultOptions = {
|
|
351
|
+
condition: Condition
|
|
352
|
+
}
|
|
353
|
+
|
|
340
354
|
export function publish(options: PublishOptions): Promise<any>
|
|
341
355
|
export function defineConfig(config: PublishConfig): PublishConfig
|
|
@@ -31,6 +31,16 @@ class BasePlatform {
|
|
|
31
31
|
return this.merge(items.map(item => `- ${item}`));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} text
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
code(text) {
|
|
39
|
+
return text;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
34
44
|
/**
|
|
35
45
|
*
|
|
36
46
|
* @param {import('..').ITarget} target
|
package/src/platforms/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const { SlackPlatform } = require('./slack.platform');
|
|
|
3
3
|
const { TeamsPlatform } = require('./teams.platform');
|
|
4
4
|
const { ChatPlatform } = require('./chat.platform');
|
|
5
5
|
const { GitHubPlatform } = require('./github.platform');
|
|
6
|
+
const { BasePlatform } = require('./base.platform');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
@@ -19,7 +20,7 @@ function getPlatform(name) {
|
|
|
19
20
|
case TARGET.GITHUB:
|
|
20
21
|
return new GitHubPlatform();
|
|
21
22
|
default:
|
|
22
|
-
|
|
23
|
+
return new BasePlatform();
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -19,6 +19,13 @@ class SlackPlatform extends BasePlatform {
|
|
|
19
19
|
}
|
|
20
20
|
return this.merge(items.map(item => `• ${item}`));
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
code(text) {
|
|
24
|
+
if (text) {
|
|
25
|
+
return `\`\`\`${text}\`\`\``;
|
|
26
|
+
}
|
|
27
|
+
return text;
|
|
28
|
+
}
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
module.exports = { SlackPlatform }
|
|
31
|
+
module.exports = { SlackPlatform }
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { getPlatform } = require('../platforms');
|
|
2
|
+
const { STATUS } = require('../helpers/constants');
|
|
3
|
+
|
|
4
|
+
class BaseTarget {
|
|
5
|
+
|
|
6
|
+
constructor({ target }) {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @type {import('../index').ITarget}
|
|
10
|
+
*/
|
|
11
|
+
this.target = target;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @type {string}
|
|
15
|
+
*/
|
|
16
|
+
this.name = target.name;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {string | boolean}
|
|
20
|
+
*/
|
|
21
|
+
this.enable = target.enable;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @type {import('../index').Condition}
|
|
25
|
+
*/
|
|
26
|
+
this.condition = target.condition || STATUS.PASS_OR_FAIL;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @type {import('../index').IExtension[]}
|
|
30
|
+
*/
|
|
31
|
+
this.extensions = target.extensions || [];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @type {import('../platforms/base.platform').BasePlatform}
|
|
35
|
+
*/
|
|
36
|
+
this.platform = getPlatform(this.name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async run({ result }) {
|
|
40
|
+
// throw new Error('Not implemented');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { BaseTarget};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { BaseTarget } = require('./base.target');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_INPUTS = {};
|
|
5
|
+
|
|
6
|
+
class CustomTarget extends BaseTarget {
|
|
7
|
+
|
|
8
|
+
constructor({ target }) {
|
|
9
|
+
super({ target });
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @type {import('../index').ICustomTargetInputs}
|
|
13
|
+
*/
|
|
14
|
+
this.inputs = Object.assign({}, DEFAULT_INPUTS, target.inputs);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run({ result }) {
|
|
18
|
+
if (typeof this.inputs.load === 'string') {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const target_runner = require(path.join(cwd, this.inputs.load));
|
|
21
|
+
await target_runner.run({ target: this.target, result });
|
|
22
|
+
} else if (typeof this.inputs.load === 'function') {
|
|
23
|
+
await this.inputs.load({ target: this.target, result });
|
|
24
|
+
} else {
|
|
25
|
+
throw `Invalid 'load' input in custom target - ${this.inputs.load}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { CustomTarget };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { BaseTarget } = require('./base.target');
|
|
2
|
+
|
|
3
|
+
const DEFAULT_INPUTS = {
|
|
4
|
+
seconds: 5
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
class DelayTarget extends BaseTarget {
|
|
8
|
+
|
|
9
|
+
constructor({ target }) {
|
|
10
|
+
super({ target });
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @type {import('../index').IDelayTargetInputs}
|
|
14
|
+
*/
|
|
15
|
+
this.inputs = Object.assign({}, DEFAULT_INPUTS, target.inputs);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async run() {
|
|
19
|
+
await new Promise(resolve => setTimeout(resolve, this.inputs.seconds * 1000));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { DelayTarget };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { BaseTarget } = require('./base.target');
|
|
2
|
+
const request = require('phin-retry');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_INPUTS = {
|
|
5
|
+
url: '',
|
|
6
|
+
method: 'POST',
|
|
7
|
+
headers: {}
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
class HttpTarget extends BaseTarget {
|
|
11
|
+
|
|
12
|
+
constructor({ target }) {
|
|
13
|
+
super({ target });
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type {import('../index').IHttpTargetInputs}
|
|
17
|
+
*/
|
|
18
|
+
this.inputs = Object.assign({}, DEFAULT_INPUTS, target.inputs);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async run({ result }) {
|
|
22
|
+
const { url, method, headers } = this.inputs;
|
|
23
|
+
await request.__fetch({
|
|
24
|
+
url,
|
|
25
|
+
method,
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'application/json',
|
|
28
|
+
...headers
|
|
29
|
+
},
|
|
30
|
+
body: { result }
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { HttpTarget };
|
package/src/targets/index.js
CHANGED
|
@@ -2,8 +2,9 @@ const teams = require('./teams');
|
|
|
2
2
|
const slack = require('./slack');
|
|
3
3
|
const chat = require('./chat');
|
|
4
4
|
const github = require('./github');
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const { CustomTarget } = require('./custom.target');
|
|
6
|
+
const { DelayTarget } = require('./delay.target');
|
|
7
|
+
const { HttpTarget } = require('./http.target');
|
|
7
8
|
const influx = require('./influx');
|
|
8
9
|
const { TARGET } = require('../helpers/constants');
|
|
9
10
|
const { checkCondition } = require('../helpers/helper');
|
|
@@ -19,11 +20,13 @@ function getTargetRunner(target) {
|
|
|
19
20
|
case TARGET.GITHUB:
|
|
20
21
|
return github;
|
|
21
22
|
case TARGET.CUSTOM:
|
|
22
|
-
return
|
|
23
|
+
return new CustomTarget({ target });
|
|
23
24
|
case TARGET.DELAY:
|
|
24
|
-
return
|
|
25
|
+
return new DelayTarget({ target });
|
|
25
26
|
case TARGET.INFLUX:
|
|
26
27
|
return influx;
|
|
28
|
+
case TARGET.HTTP:
|
|
29
|
+
return new HttpTarget({ target });
|
|
27
30
|
default:
|
|
28
31
|
return require(target.name);
|
|
29
32
|
}
|
|
@@ -31,8 +34,9 @@ function getTargetRunner(target) {
|
|
|
31
34
|
|
|
32
35
|
async function run(target, result) {
|
|
33
36
|
const target_runner = getTargetRunner(target);
|
|
34
|
-
const target_options = Object.assign({}, target_runner.default_options, target);
|
|
35
|
-
|
|
37
|
+
// const target_options = Object.assign({}, target_runner.default_options, target);
|
|
38
|
+
const condition = target.condition || target_runner.default_options?.condition || target_runner.condition;
|
|
39
|
+
if (await checkCondition({ condition, result, target })) {
|
|
36
40
|
await target_runner.run({result, target});
|
|
37
41
|
}
|
|
38
42
|
}
|
package/src/targets/slack.js
CHANGED
|
@@ -9,6 +9,8 @@ const { getValidMetrics, getMetricValuesText } = require('../helpers/performance
|
|
|
9
9
|
const TestResult = require('test-results-parser/src/models/TestResult');
|
|
10
10
|
const { getPlatform } = require('../platforms');
|
|
11
11
|
|
|
12
|
+
const SLACK_BASE_URL = 'https://slack.com';
|
|
13
|
+
|
|
12
14
|
const STATUSES = {
|
|
13
15
|
GOOD: ':white_check_mark:',
|
|
14
16
|
WARNING: ':warning:',
|
|
@@ -31,10 +33,7 @@ async function run({ result, target }) {
|
|
|
31
33
|
}
|
|
32
34
|
const message = getRootPayload({ result, target, payload });
|
|
33
35
|
logger.info(`🔔 Publishing results to Slack...`);
|
|
34
|
-
return
|
|
35
|
-
url: target.inputs.url,
|
|
36
|
-
body: message
|
|
37
|
-
});
|
|
36
|
+
return publish({ inputs: target.inputs, message });
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
async function setFunctionalPayload({ result, target, payload }) {
|
|
@@ -325,6 +324,28 @@ async function handleErrors({ target, errors }) {
|
|
|
325
324
|
});
|
|
326
325
|
}
|
|
327
326
|
|
|
327
|
+
async function publish({ inputs, message}) {
|
|
328
|
+
const { url, token, channels } = inputs;
|
|
329
|
+
if (token) {
|
|
330
|
+
for (let i = 0; i < channels.length; i++) {
|
|
331
|
+
message.channel = channels[i];
|
|
332
|
+
return request.post({
|
|
333
|
+
url: url ? url : `${SLACK_BASE_URL}/api/chat.postMessage`,
|
|
334
|
+
headers: {
|
|
335
|
+
'Authorization': `Bearer ${token}`
|
|
336
|
+
},
|
|
337
|
+
body: message
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
} else {
|
|
342
|
+
return request.post({
|
|
343
|
+
url,
|
|
344
|
+
body: message
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
328
349
|
module.exports = {
|
|
329
350
|
run,
|
|
330
351
|
handleErrors,
|
package/src/targets/custom.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const { STATUS } = require('../helpers/constants');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* @param {object} param0
|
|
7
|
-
* @param {import('../index').ITarget} 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
|
-
}
|
package/src/targets/delay.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
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
|
-
}
|