@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/dist/core/runner.d.ts
CHANGED
|
@@ -23,51 +23,42 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
import { Journey } from '../dsl/journey';
|
|
26
|
-
import {
|
|
27
|
-
import { HooksCallback, Params, HooksArgs, Driver, RunOptions, JourneyResult, StepResult, PushOptions } from '../common_types';
|
|
28
|
-
import { PluginManager } from '../plugins';
|
|
26
|
+
import { HooksCallback, RunOptions, JourneyResult, PushOptions } from '../common_types';
|
|
29
27
|
import { Monitor, MonitorConfig } from '../dsl/monitor';
|
|
30
28
|
type HookType = 'beforeAll' | 'afterAll';
|
|
31
29
|
export type SuiteHooks = Record<HookType, Array<HooksCallback>>;
|
|
32
|
-
type JourneyContext = {
|
|
33
|
-
params?: Params;
|
|
34
|
-
browserDelay: number;
|
|
35
|
-
start: number;
|
|
36
|
-
driver: Driver;
|
|
37
|
-
pluginManager: PluginManager;
|
|
38
|
-
};
|
|
39
30
|
type RunResult = Record<string, JourneyResult>;
|
|
40
|
-
export
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
monitor?: Monitor;
|
|
46
|
-
static screenshotPath: string;
|
|
47
|
-
static createContext(options: RunOptions): Promise<JourneyContext>;
|
|
48
|
-
captureScreenshot(page: Driver['page'], step: Step): Promise<void>;
|
|
49
|
-
get currentJourney(): Journey;
|
|
50
|
-
addHook(type: HookType, callback: HooksCallback): void;
|
|
51
|
-
updateMonitor(config: MonitorConfig): void;
|
|
52
|
-
addJourney(journey: Journey): void;
|
|
53
|
-
setReporter(options: RunOptions): void;
|
|
54
|
-
runBeforeAllHook(args: HooksArgs): Promise<void>;
|
|
55
|
-
runAfterAllHook(args: HooksArgs): Promise<void>;
|
|
56
|
-
runBeforeHook(journey: Journey, args: HooksArgs): Promise<void>;
|
|
57
|
-
runAfterHook(journey: Journey, args: HooksArgs): Promise<void>;
|
|
58
|
-
runStep(step: Step, context: JourneyContext, options: RunOptions): Promise<StepResult>;
|
|
59
|
-
runSteps(journey: Journey, context: JourneyContext, options: RunOptions): Promise<StepResult[]>;
|
|
60
|
-
registerJourney(journey: Journey, context: JourneyContext): void;
|
|
61
|
-
endJourney(journey: any, result: JourneyContext & JourneyResult, options: RunOptions): Promise<void>;
|
|
31
|
+
export interface RunnerInfo {
|
|
32
|
+
/**
|
|
33
|
+
* Processed configuration from the CLI args and the config file
|
|
34
|
+
*/
|
|
35
|
+
readonly config: RunOptions;
|
|
62
36
|
/**
|
|
63
|
-
*
|
|
37
|
+
* Currently active journey
|
|
64
38
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
39
|
+
readonly journey: Journey | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* All registerd journeys
|
|
42
|
+
*/
|
|
43
|
+
readonly journeys: Journey[];
|
|
44
|
+
}
|
|
45
|
+
export default class Runner implements RunnerInfo {
|
|
46
|
+
#private;
|
|
47
|
+
config: RunOptions;
|
|
48
|
+
get journey(): Journey;
|
|
49
|
+
get journeys(): Journey[];
|
|
50
|
+
get hooks(): SuiteHooks;
|
|
51
|
+
private captureScreenshot;
|
|
52
|
+
_addHook(type: HookType, callback: HooksCallback): void;
|
|
53
|
+
private buildHookArgs;
|
|
54
|
+
_updateMonitor(config: MonitorConfig): void;
|
|
55
|
+
_addJourney(journey: Journey): void;
|
|
56
|
+
private setReporter;
|
|
57
|
+
_runJourney(journey: Journey, options: RunOptions): Promise<JourneyResult>;
|
|
58
|
+
_buildMonitors(options: PushOptions): Monitor[];
|
|
59
|
+
_run(options: RunOptions): Promise<RunResult>;
|
|
60
|
+
_runJourneys(options: RunOptions): Promise<RunResult>;
|
|
61
|
+
_reset(): Promise<void>;
|
|
71
62
|
}
|
|
72
63
|
export {};
|
|
73
64
|
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAUzC,OAAO,EACL,aAAa,EAIb,UAAU,EACV,aAAa,EAEb,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAExD,KAAK,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;AACzC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;AAEhE,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;CAC9B;AAED,MAAM,CAAC,OAAO,OAAO,MAAO,YAAW,UAAU;;IAW/C,MAAM,EAAE,UAAU,CAAC;IAEnB,IAAI,OAAO,YAEV;IAED,IAAI,QAAQ,cAEX;IAED,IAAI,KAAK,eAER;YAEa,iBAAiB;IA6B/B,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa;IAIhD,OAAO,CAAC,aAAa;IAIrB,cAAc,CAAC,MAAM,EAAE,aAAa;IAQpC,WAAW,CAAC,OAAO,EAAE,OAAO;IAK5B,OAAO,CAAC,WAAW;IAiNb,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU;IAmCvD,cAAc,CAAC,OAAO,EAAE,WAAW;IA+D7B,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAiC7C,YAAY,CAAC,OAAO,EAAE,UAAU;IAgBhC,MAAM;CAWb"}
|
package/dist/core/runner.js
CHANGED
|
@@ -36,32 +36,22 @@ class Runner {
|
|
|
36
36
|
#active = false;
|
|
37
37
|
#reporter;
|
|
38
38
|
#currentJourney = null;
|
|
39
|
-
journeys = [];
|
|
40
|
-
hooks = { beforeAll: [], afterAll: [] };
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* caching all screenshots and clear them at end of each journey
|
|
56
|
-
*/
|
|
57
|
-
await (0, promises_1.mkdir)(this.screenshotPath, { recursive: true });
|
|
58
|
-
return {
|
|
59
|
-
start,
|
|
60
|
-
browserDelay: start - browserStart,
|
|
61
|
-
params: options.params,
|
|
62
|
-
driver,
|
|
63
|
-
pluginManager,
|
|
64
|
-
};
|
|
39
|
+
#journeys = [];
|
|
40
|
+
#hooks = { beforeAll: [], afterAll: [] };
|
|
41
|
+
#screenshotPath = (0, path_1.join)(helpers_1.CACHE_PATH, 'screenshots');
|
|
42
|
+
#driver;
|
|
43
|
+
#browserDelay = -1;
|
|
44
|
+
#hookError;
|
|
45
|
+
#monitor;
|
|
46
|
+
config;
|
|
47
|
+
get journey() {
|
|
48
|
+
return this.#currentJourney;
|
|
49
|
+
}
|
|
50
|
+
get journeys() {
|
|
51
|
+
return this.#journeys;
|
|
52
|
+
}
|
|
53
|
+
get hooks() {
|
|
54
|
+
return this.#hooks;
|
|
65
55
|
}
|
|
66
56
|
async captureScreenshot(page, step) {
|
|
67
57
|
try {
|
|
@@ -81,7 +71,7 @@ class Runner {
|
|
|
81
71
|
timestamp: (0, helpers_1.getTimestamp)(),
|
|
82
72
|
data: buffer.toString('base64'),
|
|
83
73
|
};
|
|
84
|
-
await (0, promises_1.writeFile)((0, path_1.join)(
|
|
74
|
+
await (0, promises_1.writeFile)((0, path_1.join)(this.#screenshotPath, fileName), JSON.stringify(screenshot));
|
|
85
75
|
(0, logger_1.log)(`Runner: captured screenshot for (${step.name})`);
|
|
86
76
|
}
|
|
87
77
|
catch (_) {
|
|
@@ -89,21 +79,21 @@ class Runner {
|
|
|
89
79
|
(0, logger_1.log)(`Runner: failed to capture screenshot for (${step.name})`);
|
|
90
80
|
}
|
|
91
81
|
}
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
_addHook(type, callback) {
|
|
83
|
+
this.#hooks[type].push(callback);
|
|
94
84
|
}
|
|
95
|
-
|
|
96
|
-
this.
|
|
85
|
+
buildHookArgs() {
|
|
86
|
+
return { env: this.config.environment, params: this.config.params, info: this };
|
|
97
87
|
}
|
|
98
|
-
|
|
99
|
-
if (!this
|
|
100
|
-
this
|
|
88
|
+
_updateMonitor(config) {
|
|
89
|
+
if (!this.#monitor) {
|
|
90
|
+
this.#monitor = new monitor_1.Monitor(config);
|
|
101
91
|
return;
|
|
102
92
|
}
|
|
103
|
-
this
|
|
93
|
+
this.#monitor.update(config);
|
|
104
94
|
}
|
|
105
|
-
|
|
106
|
-
this
|
|
95
|
+
_addJourney(journey) {
|
|
96
|
+
this.#journeys.push(journey);
|
|
107
97
|
this.#currentJourney = journey;
|
|
108
98
|
}
|
|
109
99
|
setReporter(options) {
|
|
@@ -117,66 +107,64 @@ class Runner {
|
|
|
117
107
|
: reporters_1.reporters[reporter] || reporters_1.reporters['default'];
|
|
118
108
|
this.#reporter = new Reporter({ fd: outfd, dryRun });
|
|
119
109
|
}
|
|
120
|
-
async runBeforeAllHook(args) {
|
|
110
|
+
async #runBeforeAllHook(args) {
|
|
121
111
|
(0, logger_1.log)(`Runner: beforeAll hooks`);
|
|
122
|
-
await (0, helpers_1.runParallel)(this
|
|
112
|
+
await (0, helpers_1.runParallel)(this.#hooks.beforeAll, args);
|
|
123
113
|
}
|
|
124
|
-
async runAfterAllHook(args) {
|
|
114
|
+
async #runAfterAllHook(args) {
|
|
125
115
|
(0, logger_1.log)(`Runner: afterAll hooks`);
|
|
126
|
-
await (0, helpers_1.runParallel)(this
|
|
116
|
+
await (0, helpers_1.runParallel)(this.#hooks.afterAll, args);
|
|
127
117
|
}
|
|
128
|
-
async runBeforeHook(journey, args) {
|
|
118
|
+
async #runBeforeHook(journey, args) {
|
|
129
119
|
(0, logger_1.log)(`Runner: before hooks for (${journey.name})`);
|
|
130
|
-
await (0, helpers_1.runParallel)(journey.
|
|
120
|
+
await (0, helpers_1.runParallel)(journey._getHook('before'), args);
|
|
131
121
|
}
|
|
132
|
-
async runAfterHook(journey, args) {
|
|
122
|
+
async #runAfterHook(journey, args) {
|
|
133
123
|
(0, logger_1.log)(`Runner: after hooks for (${journey.name})`);
|
|
134
|
-
await (0, helpers_1.runParallel)(journey.
|
|
124
|
+
await (0, helpers_1.runParallel)(journey._getHook('after'), args);
|
|
135
125
|
}
|
|
136
|
-
async runStep(step,
|
|
137
|
-
const data = {
|
|
138
|
-
status: 'succeeded',
|
|
139
|
-
};
|
|
126
|
+
async #runStep(step, options) {
|
|
140
127
|
(0, logger_1.log)(`Runner: start step (${step.name})`);
|
|
141
128
|
const { metrics, screenshots, filmstrips, trace } = options;
|
|
142
|
-
const { driver, pluginManager } = context;
|
|
143
129
|
/**
|
|
144
130
|
* URL needs to be the first navigation request of any step
|
|
145
131
|
* Listening for request solves the case where `about:blank` would be
|
|
146
132
|
* reported for failed navigations
|
|
147
133
|
*/
|
|
148
134
|
const captureUrl = req => {
|
|
149
|
-
if (!
|
|
150
|
-
|
|
135
|
+
if (!step.url && req.isNavigationRequest()) {
|
|
136
|
+
step.url = req.url();
|
|
151
137
|
}
|
|
152
|
-
driver.context.off('request', captureUrl);
|
|
138
|
+
this.#driver.context.off('request', captureUrl);
|
|
153
139
|
};
|
|
154
|
-
driver.context.on('request', captureUrl);
|
|
140
|
+
this.#driver.context.on('request', captureUrl);
|
|
141
|
+
const data = {};
|
|
155
142
|
const traceEnabled = trace || filmstrips;
|
|
156
143
|
try {
|
|
157
144
|
/**
|
|
158
145
|
* Set up plugin manager context and also register
|
|
159
146
|
* step level plugins
|
|
160
147
|
*/
|
|
161
|
-
pluginManager.onStep(step);
|
|
162
|
-
traceEnabled && (await pluginManager.start('trace'));
|
|
148
|
+
gatherer_1.Gatherer.pluginManager.onStep(step);
|
|
149
|
+
traceEnabled && (await gatherer_1.Gatherer.pluginManager.start('trace'));
|
|
163
150
|
// invoke the step callback by extracting to a variable to get better stack trace
|
|
164
|
-
const cb = step.
|
|
151
|
+
const cb = step.cb;
|
|
165
152
|
await cb();
|
|
153
|
+
step.status = "succeeded";
|
|
166
154
|
}
|
|
167
155
|
catch (error) {
|
|
168
|
-
|
|
169
|
-
|
|
156
|
+
step.status = 'failed';
|
|
157
|
+
step.error = error;
|
|
170
158
|
}
|
|
171
159
|
finally {
|
|
172
160
|
/**
|
|
173
161
|
* Collect all step level metrics and trace events
|
|
174
162
|
*/
|
|
175
163
|
if (metrics) {
|
|
176
|
-
data.pagemetrics = await pluginManager.get('performance').getMetrics();
|
|
164
|
+
data.pagemetrics = await gatherer_1.Gatherer.pluginManager.get('performance').getMetrics();
|
|
177
165
|
}
|
|
178
166
|
if (traceEnabled) {
|
|
179
|
-
const traceOutput = await pluginManager.stop('trace');
|
|
167
|
+
const traceOutput = await gatherer_1.Gatherer.pluginManager.stop('trace');
|
|
180
168
|
Object.assign(data, traceOutput);
|
|
181
169
|
}
|
|
182
170
|
/**
|
|
@@ -185,10 +173,10 @@ class Runner {
|
|
|
185
173
|
*
|
|
186
174
|
* Last open page will get us the correct screenshot
|
|
187
175
|
*/
|
|
188
|
-
const pages = driver.context.pages();
|
|
176
|
+
const pages = this.#driver.context.pages();
|
|
189
177
|
const page = pages[pages.length - 1];
|
|
190
178
|
if (page) {
|
|
191
|
-
|
|
179
|
+
step.url ??= page.url();
|
|
192
180
|
if (screenshots && screenshots !== 'off') {
|
|
193
181
|
await this.captureScreenshot(page, step);
|
|
194
182
|
}
|
|
@@ -197,14 +185,14 @@ class Runner {
|
|
|
197
185
|
(0, logger_1.log)(`Runner: end step (${step.name})`);
|
|
198
186
|
return data;
|
|
199
187
|
}
|
|
200
|
-
async runSteps(journey,
|
|
188
|
+
async #runSteps(journey, options) {
|
|
201
189
|
const results = [];
|
|
202
190
|
const isOnlyExists = journey.steps.filter(s => s.only).length > 0;
|
|
203
191
|
let skipStep = false;
|
|
204
192
|
for (const step of journey.steps) {
|
|
205
|
-
|
|
193
|
+
step._startTime = (0, helpers_1.monotonicTimeInSeconds)();
|
|
206
194
|
this.#reporter?.onStepStart?.(journey, step);
|
|
207
|
-
let data = {
|
|
195
|
+
let data = {};
|
|
208
196
|
/**
|
|
209
197
|
* Skip the step
|
|
210
198
|
* - if the step is marked as skip
|
|
@@ -214,133 +202,126 @@ class Runner {
|
|
|
214
202
|
if (step.skip ||
|
|
215
203
|
(skipStep && !step.only) ||
|
|
216
204
|
(isOnlyExists && !step.only)) {
|
|
217
|
-
|
|
205
|
+
step.status = 'skipped';
|
|
218
206
|
}
|
|
219
207
|
else {
|
|
220
|
-
data = await this
|
|
208
|
+
data = await this.#runStep(step, options);
|
|
221
209
|
/**
|
|
222
210
|
* skip next steps if the previous step returns error
|
|
223
211
|
*/
|
|
224
|
-
if (
|
|
212
|
+
if (step.error && !step.soft)
|
|
225
213
|
skipStep = true;
|
|
226
214
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
...data,
|
|
231
|
-
});
|
|
232
|
-
if (options.pauseOnError && data.error) {
|
|
215
|
+
step.duration = (0, helpers_1.monotonicTimeInSeconds)() - step._startTime;
|
|
216
|
+
this.#reporter?.onStepEnd?.(journey, step, data);
|
|
217
|
+
if (options.pauseOnError && step.error) {
|
|
233
218
|
await new Promise(r => process.stdin.on('data', r));
|
|
234
219
|
}
|
|
235
220
|
results.push(data);
|
|
236
221
|
}
|
|
237
222
|
return results;
|
|
238
223
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
224
|
+
async #startJourney(journey, options) {
|
|
225
|
+
journey._startTime = (0, helpers_1.monotonicTimeInSeconds)();
|
|
226
|
+
this.#driver = await gatherer_1.Gatherer.setupDriver(options);
|
|
227
|
+
await gatherer_1.Gatherer.beginRecording(this.#driver, options);
|
|
228
|
+
/**
|
|
229
|
+
* For each journey we create the screenshots folder for
|
|
230
|
+
* caching all screenshots and clear them at end of each journey
|
|
231
|
+
*/
|
|
232
|
+
await (0, promises_1.mkdir)(this.#screenshotPath, { recursive: true });
|
|
233
|
+
const params = options.params;
|
|
243
234
|
this.#reporter?.onJourneyStart?.(journey, {
|
|
244
|
-
timestamp,
|
|
235
|
+
timestamp: (0, helpers_1.getTimestamp)(),
|
|
245
236
|
params,
|
|
246
237
|
});
|
|
247
238
|
/**
|
|
248
239
|
* Exeucute the journey callback which registers the steps for current journey
|
|
249
240
|
*/
|
|
250
|
-
journey.
|
|
241
|
+
journey.cb({ ...this.#driver, params, info: this });
|
|
251
242
|
}
|
|
252
|
-
async endJourney(journey, result, options) {
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
const
|
|
243
|
+
async #endJourney(journey, result, options) {
|
|
244
|
+
// Enhance the journey results
|
|
245
|
+
const pOutput = await gatherer_1.Gatherer.pluginManager.output();
|
|
246
|
+
const bConsole = (0, plugins_1.filterBrowserMessages)(pOutput.browserconsole, journey.status);
|
|
256
247
|
await this.#reporter?.onJourneyEnd?.(journey, {
|
|
257
|
-
|
|
258
|
-
error,
|
|
259
|
-
start,
|
|
260
|
-
end,
|
|
261
|
-
browserDelay,
|
|
248
|
+
browserDelay: this.#browserDelay,
|
|
262
249
|
timestamp: (0, helpers_1.getTimestamp)(),
|
|
263
250
|
options,
|
|
264
|
-
|
|
265
|
-
browserconsole:
|
|
251
|
+
networkinfo: pOutput.networkinfo,
|
|
252
|
+
browserconsole: bConsole,
|
|
266
253
|
});
|
|
254
|
+
await gatherer_1.Gatherer.endRecording();
|
|
255
|
+
await gatherer_1.Gatherer.dispose(this.#driver);
|
|
267
256
|
// clear screenshots cache after each journey
|
|
268
|
-
await (0, promises_1.rm)(
|
|
257
|
+
await (0, promises_1.rm)(this.#screenshotPath, { recursive: true, force: true });
|
|
258
|
+
return Object.assign(result, {
|
|
259
|
+
networkinfo: pOutput.networkinfo,
|
|
260
|
+
browserconsole: bConsole,
|
|
261
|
+
...journey,
|
|
262
|
+
});
|
|
269
263
|
}
|
|
270
264
|
/**
|
|
271
265
|
* Simulate a journey run to capture errors in the beforeAll hook
|
|
272
266
|
*/
|
|
273
|
-
async runFakeJourney(journey, options) {
|
|
267
|
+
async #runFakeJourney(journey, options) {
|
|
274
268
|
const start = (0, helpers_1.monotonicTimeInSeconds)();
|
|
275
269
|
this.#reporter.onJourneyStart?.(journey, {
|
|
276
270
|
timestamp: (0, helpers_1.getTimestamp)(),
|
|
277
271
|
params: options.params,
|
|
278
272
|
});
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
273
|
+
// Mark the journey as failed and report the hook error as journey error
|
|
274
|
+
journey.status = 'failed';
|
|
275
|
+
journey.error = this.#hookError;
|
|
276
|
+
journey.duration = (0, helpers_1.monotonicTimeInSeconds)() - start;
|
|
283
277
|
await this.#reporter.onJourneyEnd?.(journey, {
|
|
284
278
|
timestamp: (0, helpers_1.getTimestamp)(),
|
|
285
|
-
start,
|
|
286
279
|
options,
|
|
287
|
-
browserDelay:
|
|
288
|
-
end: (0, helpers_1.monotonicTimeInSeconds)(),
|
|
289
|
-
...result,
|
|
280
|
+
browserDelay: this.#browserDelay,
|
|
290
281
|
});
|
|
291
|
-
return
|
|
282
|
+
return journey;
|
|
292
283
|
}
|
|
293
|
-
async
|
|
294
|
-
|
|
295
|
-
const context = await Runner.createContext(options);
|
|
284
|
+
async _runJourney(journey, options) {
|
|
285
|
+
this.#currentJourney = journey;
|
|
296
286
|
(0, logger_1.log)(`Runner: start journey (${journey.name})`);
|
|
287
|
+
let result = {};
|
|
288
|
+
const hookArgs = { env: options.environment, params: options.params, info: this };
|
|
297
289
|
try {
|
|
298
|
-
this
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
*/
|
|
308
|
-
for (const stepResult of stepResults) {
|
|
309
|
-
if (stepResult.status === 'failed') {
|
|
310
|
-
result.status = stepResult.status;
|
|
311
|
-
result.error = stepResult.error;
|
|
290
|
+
await this.#startJourney(journey, options);
|
|
291
|
+
await this.#runBeforeHook(journey, hookArgs);
|
|
292
|
+
const stepResults = await this.#runSteps(journey, options);
|
|
293
|
+
journey.status = "succeeded";
|
|
294
|
+
// Mark journey as failed if any one of the step fails
|
|
295
|
+
for (const step of journey.steps) {
|
|
296
|
+
if (step.status === 'failed') {
|
|
297
|
+
journey.status = step.status;
|
|
298
|
+
journey.error = step.error;
|
|
312
299
|
}
|
|
313
300
|
}
|
|
314
|
-
result.
|
|
315
|
-
await this.runAfterHook(journey, hookArgs);
|
|
301
|
+
result.stepsresults = stepResults;
|
|
316
302
|
}
|
|
317
303
|
catch (e) {
|
|
318
|
-
|
|
319
|
-
|
|
304
|
+
journey.status = 'failed';
|
|
305
|
+
journey.error = e;
|
|
320
306
|
}
|
|
321
307
|
finally {
|
|
322
|
-
|
|
323
|
-
|
|
308
|
+
journey.duration = (0, helpers_1.monotonicTimeInSeconds)() - journey._startTime;
|
|
309
|
+
// Run after hook on journey failure and capture the uncaught error as
|
|
310
|
+
// journey error, hook is purposely run before to capture errors during reporting
|
|
311
|
+
await this.#runAfterHook(journey, hookArgs).catch(e => {
|
|
312
|
+
journey.status = 'failed';
|
|
313
|
+
journey.error = e;
|
|
314
|
+
});
|
|
315
|
+
result = await this.#endJourney(journey, result, options);
|
|
324
316
|
}
|
|
325
317
|
(0, logger_1.log)(`Runner: end journey (${journey.name})`);
|
|
326
318
|
return result;
|
|
327
319
|
}
|
|
328
|
-
|
|
329
|
-
this.setReporter(options);
|
|
330
|
-
this.#reporter.onStart?.({
|
|
331
|
-
numJourneys: this.journeys.length,
|
|
332
|
-
networkConditions: options.networkConditions,
|
|
333
|
-
});
|
|
334
|
-
/**
|
|
335
|
-
* Set up the directory for caching screenshots
|
|
336
|
-
*/
|
|
337
|
-
await (0, promises_1.mkdir)(helpers_1.CACHE_PATH, { recursive: true });
|
|
338
|
-
}
|
|
339
|
-
buildMonitors(options) {
|
|
320
|
+
_buildMonitors(options) {
|
|
340
321
|
/**
|
|
341
322
|
* Update the global monitor configuration required for setting defaults
|
|
342
323
|
*/
|
|
343
|
-
this.
|
|
324
|
+
this._updateMonitor({
|
|
344
325
|
throttling: options.throttling,
|
|
345
326
|
schedule: options.schedule,
|
|
346
327
|
locations: options.locations,
|
|
@@ -354,7 +335,7 @@ class Runner {
|
|
|
354
335
|
enabled: options.enabled,
|
|
355
336
|
});
|
|
356
337
|
const monitors = [];
|
|
357
|
-
for (const journey of this
|
|
338
|
+
for (const journey of this.#journeys) {
|
|
358
339
|
this.#currentJourney = journey;
|
|
359
340
|
if (journey.skip) {
|
|
360
341
|
throw new Error(`Journey ${journey.name} is skipped. Please remove the journey.skip annotation and try again.`);
|
|
@@ -367,63 +348,77 @@ class Runner {
|
|
|
367
348
|
* - filter out monitors based on matched tags and name after applying both
|
|
368
349
|
* global and local monitor configurations
|
|
369
350
|
*/
|
|
370
|
-
journey.
|
|
371
|
-
journey.
|
|
372
|
-
|
|
351
|
+
journey.cb({ params: options.params });
|
|
352
|
+
const monitor = journey._getMonitor();
|
|
353
|
+
monitor.update(this.#monitor?.config);
|
|
354
|
+
if (!monitor.isMatch(options.grepOpts?.match, options.grepOpts?.tags)) {
|
|
373
355
|
continue;
|
|
374
356
|
}
|
|
375
|
-
|
|
376
|
-
monitors.push(
|
|
357
|
+
monitor.validate();
|
|
358
|
+
monitors.push(monitor);
|
|
377
359
|
}
|
|
378
360
|
return monitors;
|
|
379
361
|
}
|
|
380
|
-
async
|
|
381
|
-
|
|
362
|
+
async #init(options) {
|
|
363
|
+
this.setReporter(options);
|
|
364
|
+
this.#reporter.onStart?.({
|
|
365
|
+
numJourneys: this.#journeys.length,
|
|
366
|
+
networkConditions: options.networkConditions,
|
|
367
|
+
});
|
|
368
|
+
/**
|
|
369
|
+
* Set up the directory for caching screenshots
|
|
370
|
+
*/
|
|
371
|
+
await (0, promises_1.mkdir)(helpers_1.CACHE_PATH, { recursive: true });
|
|
372
|
+
}
|
|
373
|
+
async _run(options) {
|
|
374
|
+
this.config = options;
|
|
375
|
+
let result = {};
|
|
382
376
|
if (this.#active) {
|
|
383
377
|
return result;
|
|
384
378
|
}
|
|
385
379
|
this.#active = true;
|
|
386
|
-
(0, logger_1.log)(`Runner: run ${this
|
|
387
|
-
this
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
params: options.params,
|
|
391
|
-
}).catch(e => (this.hookError = e));
|
|
380
|
+
(0, logger_1.log)(`Runner: run ${this.#journeys.length} journeys`);
|
|
381
|
+
this.#init(options);
|
|
382
|
+
const hookArgs = this.buildHookArgs();
|
|
383
|
+
await this.#runBeforeAllHook(hookArgs).catch(e => (this.#hookError = e));
|
|
392
384
|
const { dryRun, grepOpts } = options;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
*/
|
|
396
|
-
const onlyJournerys = this.journeys.filter(j => j.only);
|
|
385
|
+
// collect all journeys with `.only` annotation and skip the rest
|
|
386
|
+
const onlyJournerys = this.#journeys.filter(j => j.only);
|
|
397
387
|
if (onlyJournerys.length > 0) {
|
|
398
|
-
this
|
|
388
|
+
this.#journeys = onlyJournerys;
|
|
399
389
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
390
|
+
else {
|
|
391
|
+
// filter journeys based on tags and skip annotations
|
|
392
|
+
this.#journeys = this.#journeys.filter(j => j._isMatch(grepOpts?.match, grepOpts?.tags) && !j.skip);
|
|
393
|
+
}
|
|
394
|
+
// Used by heartbeat to gather all registered journeys
|
|
395
|
+
if (dryRun) {
|
|
396
|
+
this.#journeys.forEach(journey => this.#reporter.onJourneyRegister?.(journey));
|
|
397
|
+
}
|
|
398
|
+
else if (this.#journeys.length > 0) {
|
|
399
|
+
result = await this._runJourneys(options);
|
|
400
|
+
}
|
|
401
|
+
await this.#runAfterAllHook(hookArgs).catch(async () => await this._reset());
|
|
402
|
+
await this._reset();
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
async _runJourneys(options) {
|
|
406
|
+
const result = {};
|
|
407
|
+
const browserStart = (0, helpers_1.monotonicTimeInSeconds)();
|
|
408
|
+
await gatherer_1.Gatherer.launchBrowser(options);
|
|
409
|
+
this.#browserDelay = (0, helpers_1.monotonicTimeInSeconds)() - browserStart;
|
|
410
|
+
for (const journey of this.#journeys) {
|
|
411
|
+
const journeyResult = this.#hookError
|
|
412
|
+
? await this.#runFakeJourney(journey, options)
|
|
413
|
+
: await this._runJourney(journey, options);
|
|
414
414
|
result[journey.name] = journeyResult;
|
|
415
415
|
}
|
|
416
416
|
await gatherer_1.Gatherer.stop();
|
|
417
|
-
await this.runAfterAllHook({
|
|
418
|
-
env: options.environment,
|
|
419
|
-
params: options.params,
|
|
420
|
-
});
|
|
421
|
-
await this.reset();
|
|
422
417
|
return result;
|
|
423
418
|
}
|
|
424
|
-
async
|
|
419
|
+
async _reset() {
|
|
425
420
|
this.#currentJourney = null;
|
|
426
|
-
this
|
|
421
|
+
this.#journeys = [];
|
|
427
422
|
this.#active = false;
|
|
428
423
|
/**
|
|
429
424
|
* Clear all cache data stored for post processing by
|