@elastic/synthetics 1.14.0 → 1.16.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/dist/cli.js +23 -4
- package/dist/cli.js.map +1 -1
- package/dist/common_types.d.ts +9 -16
- package/dist/common_types.d.ts.map +1 -1
- package/dist/core/gatherer.d.ts +3 -1
- package/dist/core/gatherer.d.ts.map +1 -1
- package/dist/core/gatherer.js +42 -35
- package/dist/core/gatherer.js.map +1 -1
- package/dist/core/globals.d.ts +27 -0
- package/dist/core/globals.d.ts.map +1 -0
- package/dist/core/globals.js +41 -0
- package/dist/core/globals.js.map +1 -0
- package/dist/core/index.d.ts +0 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +13 -25
- package/dist/core/index.js.map +1 -1
- package/dist/core/mfa.d.ts +4 -0
- package/dist/core/mfa.d.ts.map +1 -1
- package/dist/core/mfa.js.map +1 -1
- package/dist/core/runner.d.ts +30 -39
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +174 -179
- package/dist/core/runner.js.map +1 -1
- package/dist/dsl/journey.d.ts +24 -16
- package/dist/dsl/journey.d.ts.map +1 -1
- package/dist/dsl/journey.js +28 -15
- package/dist/dsl/journey.js.map +1 -1
- package/dist/dsl/monitor.d.ts +1 -0
- package/dist/dsl/monitor.d.ts.map +1 -1
- package/dist/dsl/monitor.js.map +1 -1
- package/dist/dsl/step.d.ts +12 -6
- package/dist/dsl/step.d.ts.map +1 -1
- package/dist/dsl/step.js +11 -3
- package/dist/dsl/step.js.map +1 -1
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +1 -0
- package/dist/helpers.js.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +1 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +18 -0
- package/dist/options.js.map +1 -1
- package/dist/push/index.d.ts.map +1 -1
- package/dist/push/index.js +1 -1
- package/dist/push/index.js.map +1 -1
- package/dist/push/monitor.d.ts +1 -0
- package/dist/push/monitor.d.ts.map +1 -1
- package/dist/push/monitor.js +18 -1
- package/dist/push/monitor.js.map +1 -1
- package/dist/reporters/base.d.ts +3 -3
- package/dist/reporters/base.d.ts.map +1 -1
- package/dist/reporters/base.js +6 -6
- package/dist/reporters/base.js.map +1 -1
- package/dist/reporters/build_kite_cli.d.ts +2 -4
- package/dist/reporters/build_kite_cli.d.ts.map +1 -1
- package/dist/reporters/build_kite_cli.js +8 -10
- package/dist/reporters/build_kite_cli.js.map +1 -1
- package/dist/reporters/json.d.ts +4 -9
- package/dist/reporters/json.d.ts.map +1 -1
- package/dist/reporters/json.js +31 -40
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/junit.d.ts +2 -2
- package/dist/reporters/junit.d.ts.map +1 -1
- package/dist/reporters/junit.js +7 -7
- package/dist/reporters/junit.js.map +1 -1
- package/package.json +2 -2
- package/src/cli.ts +24 -5
- package/src/common_types.ts +9 -16
- package/src/core/gatherer.ts +44 -37
- package/src/core/globals.ts +37 -0
- package/src/core/index.ts +12 -25
- package/src/core/mfa.ts +5 -0
- package/src/core/runner.ts +201 -202
- package/src/dsl/journey.ts +42 -23
- package/src/dsl/monitor.ts +1 -0
- package/src/dsl/step.ts +16 -7
- package/src/helpers.ts +4 -3
- package/src/index.ts +2 -2
- package/src/options.ts +22 -0
- package/src/push/index.ts +3 -4
- package/src/push/monitor.ts +20 -0
- package/src/reporters/base.ts +8 -12
- package/src/reporters/build_kite_cli.ts +13 -18
- package/src/reporters/json.ts +35 -52
- package/src/reporters/junit.ts +8 -10
package/src/dsl/journey.ts
CHANGED
|
@@ -31,9 +31,10 @@ import {
|
|
|
31
31
|
APIRequestContext,
|
|
32
32
|
} from 'playwright-core';
|
|
33
33
|
import { Step } from './step';
|
|
34
|
-
import { VoidCallback, HooksCallback, Params, Location } from '../common_types';
|
|
34
|
+
import { VoidCallback, HooksCallback, Params, Location, StatusValue } from '../common_types';
|
|
35
35
|
import { Monitor, MonitorConfig } from './monitor';
|
|
36
36
|
import { isMatch } from '../helpers';
|
|
37
|
+
import { RunnerInfo } from '../core/runner';
|
|
37
38
|
|
|
38
39
|
export type JourneyOptions = {
|
|
39
40
|
name: string;
|
|
@@ -43,69 +44,87 @@ export type JourneyOptions = {
|
|
|
43
44
|
|
|
44
45
|
type HookType = 'before' | 'after';
|
|
45
46
|
export type Hooks = Record<HookType, Array<HooksCallback>>;
|
|
46
|
-
|
|
47
|
+
type JourneyCallbackOpts = {
|
|
47
48
|
page: Page;
|
|
48
49
|
context: BrowserContext;
|
|
49
50
|
browser: Browser;
|
|
50
51
|
client: CDPSession;
|
|
51
52
|
params: Params;
|
|
52
53
|
request: APIRequestContext;
|
|
53
|
-
|
|
54
|
+
info: RunnerInfo;
|
|
55
|
+
};
|
|
56
|
+
export type JourneyCallback = (options: JourneyCallbackOpts) => void;
|
|
54
57
|
|
|
55
58
|
export class Journey {
|
|
56
|
-
name: string;
|
|
57
|
-
id?: string;
|
|
58
|
-
tags?: string[];
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
hooks: Hooks = { before: [], after: [] };
|
|
63
|
-
monitor: Monitor;
|
|
59
|
+
readonly name: string;
|
|
60
|
+
readonly id?: string;
|
|
61
|
+
readonly tags?: string[];
|
|
62
|
+
readonly location?: Location;
|
|
63
|
+
readonly steps: Step[] = [];
|
|
64
|
+
#cb: JourneyCallback;
|
|
65
|
+
#hooks: Hooks = { before: [], after: [] };
|
|
66
|
+
#monitor: Monitor;
|
|
64
67
|
skip = false;
|
|
65
68
|
only = false;
|
|
69
|
+
_startTime = 0;
|
|
70
|
+
duration = -1;
|
|
71
|
+
status: StatusValue = 'pending';
|
|
72
|
+
error?: Error;
|
|
66
73
|
|
|
67
74
|
constructor(
|
|
68
75
|
options: JourneyOptions,
|
|
69
|
-
|
|
76
|
+
cb: JourneyCallback,
|
|
70
77
|
location?: Location
|
|
71
78
|
) {
|
|
72
79
|
this.name = options.name;
|
|
73
80
|
this.id = options.id || options.name;
|
|
74
81
|
this.tags = options.tags;
|
|
75
|
-
this
|
|
82
|
+
this.#cb = cb;
|
|
76
83
|
this.location = location;
|
|
77
|
-
this.
|
|
84
|
+
this._updateMonitor({});
|
|
78
85
|
}
|
|
79
86
|
|
|
80
|
-
|
|
81
|
-
const step = new Step(name, this.steps.length + 1,
|
|
87
|
+
_addStep(name: string, cb: VoidCallback, location?: Location) {
|
|
88
|
+
const step = new Step(name, this.steps.length + 1, cb, location);
|
|
82
89
|
this.steps.push(step);
|
|
83
90
|
return step;
|
|
84
91
|
}
|
|
85
92
|
|
|
86
|
-
|
|
87
|
-
this
|
|
93
|
+
_addHook(type: HookType, cb: HooksCallback) {
|
|
94
|
+
this.#hooks[type].push(cb);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_getHook(type: HookType) {
|
|
98
|
+
return this.#hooks[type];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_getMonitor() {
|
|
102
|
+
return this.#monitor;
|
|
88
103
|
}
|
|
89
104
|
|
|
90
|
-
|
|
105
|
+
_updateMonitor(config: MonitorConfig) {
|
|
91
106
|
/**
|
|
92
107
|
* Use defaults values from journey for monitor object (id, name and tags)
|
|
93
108
|
*/
|
|
94
|
-
this
|
|
109
|
+
this.#monitor = new Monitor({
|
|
95
110
|
name: this.name,
|
|
96
111
|
id: this.id,
|
|
97
112
|
type: 'browser',
|
|
98
113
|
tags: this.tags ?? [],
|
|
99
114
|
...config,
|
|
100
115
|
});
|
|
101
|
-
this
|
|
102
|
-
this
|
|
116
|
+
this.#monitor.setSource(this.location);
|
|
117
|
+
this.#monitor.setFilter({ match: this.name });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get cb() {
|
|
121
|
+
return this.#cb;
|
|
103
122
|
}
|
|
104
123
|
|
|
105
124
|
/**
|
|
106
125
|
* Matches journeys based on the provided args. Proitize tags over match
|
|
107
126
|
*/
|
|
108
|
-
|
|
127
|
+
_isMatch(matchPattern: string, tagsPattern: Array<string>) {
|
|
109
128
|
return isMatch(this.tags, this.name, tagsPattern, matchPattern);
|
|
110
129
|
}
|
|
111
130
|
}
|
package/src/dsl/monitor.ts
CHANGED
package/src/dsl/step.ts
CHANGED
|
@@ -23,28 +23,37 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { Location, VoidCallback } from '../common_types';
|
|
26
|
+
import { Location, StatusValue, VoidCallback } from '../common_types';
|
|
27
27
|
|
|
28
28
|
export class Step {
|
|
29
|
-
name: string;
|
|
30
|
-
index: number;
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly index: number;
|
|
31
|
+
readonly location?: Location;
|
|
32
|
+
#cb: VoidCallback;
|
|
33
33
|
skip = false;
|
|
34
34
|
soft = false;
|
|
35
35
|
only = false;
|
|
36
|
+
_startTime = 0;
|
|
37
|
+
duration = -1;
|
|
38
|
+
status: StatusValue = 'pending';
|
|
39
|
+
error?: Error;
|
|
40
|
+
url?: string;
|
|
36
41
|
|
|
37
42
|
constructor(
|
|
38
43
|
name: string,
|
|
39
44
|
index: number,
|
|
40
|
-
|
|
45
|
+
cb: VoidCallback,
|
|
41
46
|
location: Location
|
|
42
47
|
) {
|
|
43
48
|
this.name = name;
|
|
44
49
|
this.index = index;
|
|
45
|
-
this
|
|
50
|
+
this.#cb = cb;
|
|
46
51
|
this.location = location;
|
|
47
52
|
}
|
|
53
|
+
|
|
54
|
+
get cb() {
|
|
55
|
+
return this.#cb;
|
|
56
|
+
}
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
type StepType = (name: string, callback: VoidCallback) => Step;
|
package/src/helpers.ts
CHANGED
|
@@ -41,7 +41,7 @@ import micromatch from 'micromatch';
|
|
|
41
41
|
|
|
42
42
|
const SEPARATOR = '\n';
|
|
43
43
|
|
|
44
|
-
export function noop() {}
|
|
44
|
+
export function noop() { }
|
|
45
45
|
|
|
46
46
|
export function indent(lines: string, tab = ' ') {
|
|
47
47
|
return lines.replace(/^/gm, tab);
|
|
@@ -54,6 +54,7 @@ export function indent(lines: string, tab = ' ') {
|
|
|
54
54
|
const NO_UTF8_SUPPORT = process.platform === 'win32';
|
|
55
55
|
export const symbols = {
|
|
56
56
|
warning: yellow(NO_UTF8_SUPPORT ? '!' : '⚠'),
|
|
57
|
+
pending: yellow(NO_UTF8_SUPPORT ? '!' : '⚠'),
|
|
57
58
|
skipped: cyan('-'),
|
|
58
59
|
progress: cyan('>'),
|
|
59
60
|
succeeded: green(NO_UTF8_SUPPORT ? 'ok' : '✓'),
|
|
@@ -151,8 +152,8 @@ export function findPkgJsonByTraversing(resolvePath, cwd) {
|
|
|
151
152
|
if (resolvePath === parentDirectory) {
|
|
152
153
|
throw red(
|
|
153
154
|
`Could not find package.json file in: "${cwd}"\n` +
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
`It is recommended to run the agent in an NPM project.\n` +
|
|
156
|
+
`You can create one by running "npm init -y" in the project folder.`
|
|
156
157
|
);
|
|
157
158
|
}
|
|
158
159
|
return findPkgJsonByTraversing(parentDirectory, cwd);
|
package/src/index.ts
CHANGED
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { runner } from './core';
|
|
26
|
+
import { runner } from './core/globals';
|
|
27
27
|
import { RunOptions } from './common_types';
|
|
28
28
|
|
|
29
29
|
export async function run(options: RunOptions) {
|
|
30
|
-
return runner.
|
|
30
|
+
return runner._run(options);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
package/src/options.ts
CHANGED
|
@@ -70,6 +70,9 @@ export async function normalizeOptions(
|
|
|
70
70
|
: {};
|
|
71
71
|
|
|
72
72
|
options.params = Object.freeze(merge(config.params, cliArgs.params || {}));
|
|
73
|
+
options.fields = Object.freeze(
|
|
74
|
+
merge(config.monitor?.fields ?? {}, cliArgs?.fields || {})
|
|
75
|
+
);
|
|
73
76
|
|
|
74
77
|
/**
|
|
75
78
|
* Merge playwright options from CLI and Synthetics config
|
|
@@ -233,6 +236,24 @@ export function getCommonCommandOpts() {
|
|
|
233
236
|
'--match <name>',
|
|
234
237
|
'run/push tests with a name or tags that matches a pattern'
|
|
235
238
|
);
|
|
239
|
+
const fields = createOption(
|
|
240
|
+
'--fields <jsonstring>',
|
|
241
|
+
'add fields to the monitor(s) in the format { "key": "value"}'
|
|
242
|
+
).argParser((fieldsStr: string) => {
|
|
243
|
+
const fields = JSON.parse(fieldsStr);
|
|
244
|
+
if (typeof fields !== 'object') {
|
|
245
|
+
throw new Error('Invalid fields format');
|
|
246
|
+
}
|
|
247
|
+
// make sure all values are strings
|
|
248
|
+
return Object.entries(fields).reduce((acc, [key, value]) => {
|
|
249
|
+
if (typeof value !== 'string') {
|
|
250
|
+
acc[key] = JSON.stringify(value);
|
|
251
|
+
} else {
|
|
252
|
+
acc[key] = value;
|
|
253
|
+
}
|
|
254
|
+
return acc;
|
|
255
|
+
}, {});
|
|
256
|
+
});
|
|
236
257
|
|
|
237
258
|
return {
|
|
238
259
|
auth,
|
|
@@ -243,6 +264,7 @@ export function getCommonCommandOpts() {
|
|
|
243
264
|
configOpt,
|
|
244
265
|
tags,
|
|
245
266
|
match,
|
|
267
|
+
fields,
|
|
246
268
|
};
|
|
247
269
|
}
|
|
248
270
|
|
package/src/push/index.ts
CHANGED
|
@@ -223,11 +223,10 @@ export function validateSettings(opts: PushOptions) {
|
|
|
223
223
|
- CLI '--schedule <mins>'
|
|
224
224
|
- Config file 'monitors.schedule' field`;
|
|
225
225
|
} else if (opts.schedule && !ALLOWED_SCHEDULES.includes(opts.schedule)) {
|
|
226
|
-
reason = `Set default schedule(${
|
|
227
|
-
|
|
228
|
-
}) to one of the allowed values - ${ALLOWED_SCHEDULES.join(',')}`;
|
|
226
|
+
reason = `Set default schedule(${opts.schedule
|
|
227
|
+
}) to one of the allowed values - ${ALLOWED_SCHEDULES.join(',')}`;
|
|
229
228
|
} else if (
|
|
230
|
-
opts.locations.length > 0 &&
|
|
229
|
+
(opts.locations ?? []).length > 0 &&
|
|
231
230
|
(opts?.playwrightOptions?.clientCertificates ?? []).filter(cert => {
|
|
232
231
|
return cert.certPath || cert.keyPath || cert.pfxPath;
|
|
233
232
|
}).length > 0
|
package/src/push/monitor.ts
CHANGED
|
@@ -268,6 +268,7 @@ export function buildMonitorFromYaml(
|
|
|
268
268
|
enabled: config.enabled ?? options.enabled,
|
|
269
269
|
locations: options.locations,
|
|
270
270
|
tags: options.tags,
|
|
271
|
+
fields: parseFields(config, options.fields),
|
|
271
272
|
...normalizeConfig(config),
|
|
272
273
|
retestOnFailure,
|
|
273
274
|
privateLocations,
|
|
@@ -311,6 +312,25 @@ export const parseAlertConfig = (
|
|
|
311
312
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
312
313
|
};
|
|
313
314
|
|
|
315
|
+
export const parseFields = (
|
|
316
|
+
config: MonitorConfig,
|
|
317
|
+
gFields?: Record<string, string>
|
|
318
|
+
) => {
|
|
319
|
+
// get all keys starting with `label.`
|
|
320
|
+
const keys = Object.keys(config).filter(key => key.startsWith('fields.'));
|
|
321
|
+
const fields = {};
|
|
322
|
+
for (const key of keys) {
|
|
323
|
+
fields[key.replace('fields.', '')] = config[key];
|
|
324
|
+
delete config[key];
|
|
325
|
+
}
|
|
326
|
+
if (gFields) {
|
|
327
|
+
for (const key of Object.keys(gFields)) {
|
|
328
|
+
fields[key] = gFields[key];
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return Object.keys(fields).length > 0 ? fields : undefined;
|
|
332
|
+
};
|
|
333
|
+
|
|
314
334
|
export function getAlertKeyValue(
|
|
315
335
|
key: 'status' | 'tls',
|
|
316
336
|
config: MonitorConfig,
|
package/src/reporters/base.ts
CHANGED
|
@@ -28,12 +28,8 @@ import { green, red, cyan, gray } from 'kleur/colors';
|
|
|
28
28
|
import { renderError, serializeError } from './reporter-util';
|
|
29
29
|
import { symbols, indent, now } from '../helpers';
|
|
30
30
|
import { Reporter, ReporterOptions } from '.';
|
|
31
|
-
import {
|
|
32
|
-
JourneyEndResult,
|
|
33
|
-
JourneyStartResult,
|
|
34
|
-
StepEndResult,
|
|
35
|
-
} from '../common_types';
|
|
36
31
|
import { Journey, Step } from '../dsl';
|
|
32
|
+
import { JourneyEndResult, JourneyStartResult, StepResult } from '../common_types';
|
|
37
33
|
|
|
38
34
|
export function renderDuration(durationMs) {
|
|
39
35
|
return parseInt(durationMs);
|
|
@@ -66,14 +62,14 @@ export default class BaseReporter implements Reporter {
|
|
|
66
62
|
this.metrics.registered++;
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
onJourneyStart(journey: Journey, {}: JourneyStartResult) {
|
|
65
|
+
onJourneyStart(journey: Journey, { }: JourneyStartResult) {
|
|
70
66
|
this.write(`\nJourney: ${journey.name}`);
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
onStepEnd(_: Journey, step: Step,
|
|
74
|
-
const { status,
|
|
69
|
+
onStepEnd(_: Journey, step: Step, { }: StepResult) {
|
|
70
|
+
const { status, error } = step;
|
|
75
71
|
const message = `${symbols[status]} Step: '${step.name}' ${status} ${gray(
|
|
76
|
-
'(' + renderDuration(
|
|
72
|
+
'(' + renderDuration(step.duration * 1000) + ' ms)'
|
|
77
73
|
)}`;
|
|
78
74
|
this.write(indent(message));
|
|
79
75
|
if (error) {
|
|
@@ -84,15 +80,15 @@ export default class BaseReporter implements Reporter {
|
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
87
|
-
onJourneyEnd(
|
|
83
|
+
onJourneyEnd(journey: Journey, { }: JourneyEndResult) {
|
|
88
84
|
const { failed, succeeded, skipped } = this.metrics;
|
|
89
85
|
const total = failed + succeeded + skipped;
|
|
90
86
|
/**
|
|
91
87
|
* Render the error on the terminal only when no steps could
|
|
92
88
|
* be executed which means the error happened in one of the hooks
|
|
93
89
|
*/
|
|
94
|
-
if (total === 0 && error) {
|
|
95
|
-
const message = renderError(serializeError(error));
|
|
90
|
+
if (total === 0 && journey.error) {
|
|
91
|
+
const message = renderError(serializeError(journey.error));
|
|
96
92
|
this.write(indent(message) + '\n');
|
|
97
93
|
}
|
|
98
94
|
}
|
|
@@ -37,13 +37,13 @@ import { Journey, Step } from '../dsl';
|
|
|
37
37
|
import { renderError, serializeError } from './reporter-util';
|
|
38
38
|
|
|
39
39
|
export default class BuildKiteCLIReporter extends BaseReporter {
|
|
40
|
-
journeys: Map<string, Array<
|
|
40
|
+
journeys: Map<string, Array<Step>> = new Map();
|
|
41
41
|
|
|
42
42
|
constructor(options: ReporterOptions = {}) {
|
|
43
43
|
super(options);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
override onJourneyStart(journey: Journey, {}: JourneyStartResult) {
|
|
46
|
+
override onJourneyStart(journey: Journey, { }: JourneyStartResult) {
|
|
47
47
|
this.write(`\n--- Journey: ${journey.name}`);
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -52,15 +52,12 @@ export default class BuildKiteCLIReporter extends BaseReporter {
|
|
|
52
52
|
if (!this.journeys.has(journey.name)) {
|
|
53
53
|
this.journeys.set(journey.name, []);
|
|
54
54
|
}
|
|
55
|
-
this.journeys.get(journey.name)?.push(
|
|
55
|
+
this.journeys.get(journey.name)?.push(step);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
override async onJourneyEnd(journey: Journey,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const message = `${symbols[status]} Took (${renderDuration(
|
|
62
|
-
end - start
|
|
63
|
-
)} seconds)`;
|
|
58
|
+
override async onJourneyEnd(journey: Journey, result: JourneyEndResult) {
|
|
59
|
+
super.onJourneyEnd(journey, result);
|
|
60
|
+
const message = `${symbols[journey.status]} Took (${renderDuration(journey.duration)} seconds)`;
|
|
64
61
|
this.write(message);
|
|
65
62
|
}
|
|
66
63
|
|
|
@@ -78,16 +75,14 @@ export default class BuildKiteCLIReporter extends BaseReporter {
|
|
|
78
75
|
failedJourneys.forEach(([journeyName, steps]) => {
|
|
79
76
|
const name = red(`Journey: ${journeyName} :slightly_frowning_face:`);
|
|
80
77
|
this.write(`\n+++ ${name}`);
|
|
81
|
-
steps.forEach(
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
(end - start) * 1000
|
|
87
|
-
)} ms)`;
|
|
78
|
+
steps.forEach(step => {
|
|
79
|
+
const message = `${symbols[step.status]
|
|
80
|
+
} Step: '${step.name}' ${step.status} (${renderDuration(
|
|
81
|
+
step.duration * 1000
|
|
82
|
+
)} ms)`;
|
|
88
83
|
this.write(indent(message));
|
|
89
|
-
if (error) {
|
|
90
|
-
this.write(renderError(serializeError(error)));
|
|
84
|
+
if (step.error) {
|
|
85
|
+
this.write(renderError(serializeError(step.error)));
|
|
91
86
|
}
|
|
92
87
|
});
|
|
93
88
|
});
|
package/src/reporters/json.ts
CHANGED
|
@@ -91,13 +91,16 @@ type Duration = {
|
|
|
91
91
|
};
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
+
type JourneyInfo = Omit<Partial<Journey>, 'duration'> & Duration;
|
|
95
|
+
type StepInfo = Omit<Partial<Step>, 'duration'> & Duration;
|
|
96
|
+
|
|
94
97
|
type OutputFields = {
|
|
95
98
|
type: OutputType;
|
|
96
99
|
_id?: string;
|
|
97
|
-
journey?: Partial<Journey
|
|
100
|
+
journey?: Partial<Journey>;
|
|
98
101
|
timestamp?: number;
|
|
99
102
|
url?: string;
|
|
100
|
-
step?: Partial<Step
|
|
103
|
+
step?: Partial<Step>;
|
|
101
104
|
error?: Error;
|
|
102
105
|
root_fields?: Record<string, unknown>;
|
|
103
106
|
payload?: Payload;
|
|
@@ -251,36 +254,35 @@ function formatJSONError(error: Error | any) {
|
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
function journeyInfo(
|
|
254
|
-
journey:
|
|
257
|
+
journey: Partial<Journey>,
|
|
255
258
|
type: OutputFields['type'],
|
|
256
|
-
status: Payload['status']
|
|
257
259
|
) {
|
|
258
260
|
if (!journey) {
|
|
259
261
|
return;
|
|
260
262
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
263
|
+
const info: JourneyInfo = { name: journey.name, id: journey.id, tags: journey.tags };
|
|
264
|
+
const isEnd = type === 'journey/end';
|
|
265
|
+
if (isEnd) {
|
|
266
|
+
info.status = journey.status;
|
|
267
|
+
info.duration = { us: getDurationInUs(journey.duration) };
|
|
268
|
+
}
|
|
269
|
+
return info;
|
|
268
270
|
}
|
|
269
271
|
|
|
270
272
|
function stepInfo(
|
|
271
|
-
step:
|
|
273
|
+
step: Partial<Step>,
|
|
272
274
|
type: OutputFields['type'],
|
|
273
|
-
|
|
274
|
-
) {
|
|
275
|
+
): Omit<Partial<Step>, 'duration'> & Duration {
|
|
275
276
|
if (!step) {
|
|
276
277
|
return;
|
|
277
278
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
status
|
|
282
|
-
duration: step.duration
|
|
283
|
-
}
|
|
279
|
+
const info: StepInfo = { name: step.name, index: step.index };
|
|
280
|
+
const isEnd = type === 'step/end';
|
|
281
|
+
if (isEnd) {
|
|
282
|
+
info.status = step.status;
|
|
283
|
+
info.duration = { us: getDurationInUs(step.duration) };
|
|
284
|
+
}
|
|
285
|
+
return info;
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
export async function getScreenshotBlocks(screenshot: Buffer) {
|
|
@@ -391,7 +393,7 @@ export default class JSONReporter extends BaseReporter {
|
|
|
391
393
|
type: 'journey/start',
|
|
392
394
|
journey,
|
|
393
395
|
timestamp,
|
|
394
|
-
payload: { source: journey.
|
|
396
|
+
payload: { source: journey.cb.toString() },
|
|
395
397
|
});
|
|
396
398
|
}
|
|
397
399
|
|
|
@@ -399,11 +401,6 @@ export default class JSONReporter extends BaseReporter {
|
|
|
399
401
|
journey: Journey,
|
|
400
402
|
step: Step,
|
|
401
403
|
{
|
|
402
|
-
start,
|
|
403
|
-
end,
|
|
404
|
-
error,
|
|
405
|
-
url,
|
|
406
|
-
status,
|
|
407
404
|
pagemetrics,
|
|
408
405
|
traces,
|
|
409
406
|
metrics,
|
|
@@ -432,18 +429,13 @@ export default class JSONReporter extends BaseReporter {
|
|
|
432
429
|
this.writeJSON({
|
|
433
430
|
type: 'step/end',
|
|
434
431
|
journey,
|
|
435
|
-
step
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
us: getDurationInUs(end - start),
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
url,
|
|
442
|
-
error,
|
|
432
|
+
step,
|
|
433
|
+
url: step.url,
|
|
434
|
+
error: step.error,
|
|
443
435
|
payload: {
|
|
444
|
-
source: step.
|
|
445
|
-
url,
|
|
446
|
-
status,
|
|
436
|
+
source: step.cb.toString(),
|
|
437
|
+
url: step.url,
|
|
438
|
+
status: step.status,
|
|
447
439
|
pagemetrics,
|
|
448
440
|
},
|
|
449
441
|
});
|
|
@@ -453,20 +445,16 @@ export default class JSONReporter extends BaseReporter {
|
|
|
453
445
|
journey: Journey,
|
|
454
446
|
{
|
|
455
447
|
timestamp,
|
|
456
|
-
start,
|
|
457
|
-
end,
|
|
458
448
|
browserDelay,
|
|
459
449
|
networkinfo,
|
|
460
450
|
browserconsole,
|
|
461
|
-
status,
|
|
462
|
-
error,
|
|
463
451
|
options,
|
|
464
452
|
}: JourneyEndResult
|
|
465
453
|
) {
|
|
466
454
|
const { ssblocks, screenshots } = options;
|
|
467
455
|
const writeScreenshots =
|
|
468
456
|
screenshots === 'on' ||
|
|
469
|
-
(screenshots === 'only-on-failure' && status === 'failed');
|
|
457
|
+
(screenshots === 'only-on-failure' && journey.status === 'failed');
|
|
470
458
|
if (writeScreenshots) {
|
|
471
459
|
await gatherScreenshots(
|
|
472
460
|
join(CACHE_PATH, 'screenshots'),
|
|
@@ -522,16 +510,11 @@ export default class JSONReporter extends BaseReporter {
|
|
|
522
510
|
|
|
523
511
|
this.writeJSON({
|
|
524
512
|
type: 'journey/end',
|
|
525
|
-
journey
|
|
526
|
-
...journey,
|
|
527
|
-
duration: {
|
|
528
|
-
us: getDurationInUs(end - start),
|
|
529
|
-
},
|
|
530
|
-
},
|
|
513
|
+
journey,
|
|
531
514
|
timestamp,
|
|
532
|
-
error,
|
|
515
|
+
error: journey.error,
|
|
533
516
|
payload: {
|
|
534
|
-
status,
|
|
517
|
+
status: journey.status,
|
|
535
518
|
// convert from monotonic seconds time to microseconds
|
|
536
519
|
browser_delay_us: getDurationInUs(browserDelay),
|
|
537
520
|
// timestamp in microseconds at which the current node process began, measured in Unix time.
|
|
@@ -613,8 +596,8 @@ export default class JSONReporter extends BaseReporter {
|
|
|
613
596
|
type,
|
|
614
597
|
_id,
|
|
615
598
|
'@timestamp': timestamp || getTimestamp(),
|
|
616
|
-
journey: journeyInfo(journey, type
|
|
617
|
-
step: stepInfo(step, type
|
|
599
|
+
journey: journeyInfo(journey, type),
|
|
600
|
+
step: stepInfo(step, type),
|
|
618
601
|
root_fields: { ...(root_fields || {}), ...getMetadata() },
|
|
619
602
|
payload,
|
|
620
603
|
blob,
|
package/src/reporters/junit.ts
CHANGED
|
@@ -28,7 +28,6 @@ import { dirname } from 'path';
|
|
|
28
28
|
import {
|
|
29
29
|
JourneyEndResult,
|
|
30
30
|
JourneyStartResult,
|
|
31
|
-
StepEndResult,
|
|
32
31
|
} from '../common_types';
|
|
33
32
|
import { Journey, Step } from '../dsl';
|
|
34
33
|
import { indent, now } from '../helpers';
|
|
@@ -60,7 +59,7 @@ export default class JUnitReporter extends BaseReporter {
|
|
|
60
59
|
private totalSkipped = 0;
|
|
61
60
|
#journeyMap = new Map<string, XMLEntry>();
|
|
62
61
|
|
|
63
|
-
override onJourneyStart(journey: Journey, {}: JourneyStartResult) {
|
|
62
|
+
override onJourneyStart(journey: Journey, { }: JourneyStartResult) {
|
|
64
63
|
if (!this.#journeyMap.has(journey.name)) {
|
|
65
64
|
const entry = {
|
|
66
65
|
name: 'testsuite',
|
|
@@ -80,7 +79,6 @@ export default class JUnitReporter extends BaseReporter {
|
|
|
80
79
|
override onStepEnd(
|
|
81
80
|
journey: Journey,
|
|
82
81
|
step: Step,
|
|
83
|
-
{ status, error, start, end }: StepEndResult
|
|
84
82
|
) {
|
|
85
83
|
if (!this.#journeyMap.has(journey.name)) {
|
|
86
84
|
return;
|
|
@@ -91,23 +89,23 @@ export default class JUnitReporter extends BaseReporter {
|
|
|
91
89
|
attributes: {
|
|
92
90
|
name: step.name,
|
|
93
91
|
classname: journey.name + ' ' + step.name,
|
|
94
|
-
time:
|
|
92
|
+
time: step.duration,
|
|
95
93
|
},
|
|
96
94
|
children: [],
|
|
97
95
|
};
|
|
98
96
|
|
|
99
97
|
entry.attributes.tests++;
|
|
100
|
-
if (status === 'failed') {
|
|
98
|
+
if (step.status === 'failed') {
|
|
101
99
|
caseEntry.children.push({
|
|
102
100
|
name: 'failure',
|
|
103
101
|
attributes: {
|
|
104
|
-
message: error
|
|
105
|
-
type: error
|
|
102
|
+
message: step.error?.message,
|
|
103
|
+
type: step.error?.name,
|
|
106
104
|
},
|
|
107
|
-
text: stripAnsiCodes(serializeError(error).stack),
|
|
105
|
+
text: stripAnsiCodes(serializeError(step.error).stack),
|
|
108
106
|
});
|
|
109
107
|
entry.attributes.failures++;
|
|
110
|
-
} else if (status === 'skipped') {
|
|
108
|
+
} else if (step.status === 'skipped') {
|
|
111
109
|
caseEntry.children.push({
|
|
112
110
|
name: 'skipped',
|
|
113
111
|
attributes: {
|
|
@@ -119,7 +117,7 @@ export default class JUnitReporter extends BaseReporter {
|
|
|
119
117
|
entry.children.push(caseEntry);
|
|
120
118
|
}
|
|
121
119
|
|
|
122
|
-
override onJourneyEnd(journey: Journey, {}: JourneyEndResult) {
|
|
120
|
+
override onJourneyEnd(journey: Journey, { }: JourneyEndResult) {
|
|
123
121
|
if (!this.#journeyMap.has(journey.name)) {
|
|
124
122
|
return;
|
|
125
123
|
}
|