@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.
Files changed (87) hide show
  1. package/dist/cli.js +23 -4
  2. package/dist/cli.js.map +1 -1
  3. package/dist/common_types.d.ts +9 -16
  4. package/dist/common_types.d.ts.map +1 -1
  5. package/dist/core/gatherer.d.ts +3 -1
  6. package/dist/core/gatherer.d.ts.map +1 -1
  7. package/dist/core/gatherer.js +42 -35
  8. package/dist/core/gatherer.js.map +1 -1
  9. package/dist/core/globals.d.ts +27 -0
  10. package/dist/core/globals.d.ts.map +1 -0
  11. package/dist/core/globals.js +41 -0
  12. package/dist/core/globals.js.map +1 -0
  13. package/dist/core/index.d.ts +0 -2
  14. package/dist/core/index.d.ts.map +1 -1
  15. package/dist/core/index.js +13 -25
  16. package/dist/core/index.js.map +1 -1
  17. package/dist/core/mfa.d.ts +4 -0
  18. package/dist/core/mfa.d.ts.map +1 -1
  19. package/dist/core/mfa.js.map +1 -1
  20. package/dist/core/runner.d.ts +30 -39
  21. package/dist/core/runner.d.ts.map +1 -1
  22. package/dist/core/runner.js +174 -179
  23. package/dist/core/runner.js.map +1 -1
  24. package/dist/dsl/journey.d.ts +24 -16
  25. package/dist/dsl/journey.d.ts.map +1 -1
  26. package/dist/dsl/journey.js +28 -15
  27. package/dist/dsl/journey.js.map +1 -1
  28. package/dist/dsl/monitor.d.ts +1 -0
  29. package/dist/dsl/monitor.d.ts.map +1 -1
  30. package/dist/dsl/monitor.js.map +1 -1
  31. package/dist/dsl/step.d.ts +12 -6
  32. package/dist/dsl/step.d.ts.map +1 -1
  33. package/dist/dsl/step.js +11 -3
  34. package/dist/dsl/step.js.map +1 -1
  35. package/dist/helpers.d.ts +1 -0
  36. package/dist/helpers.d.ts.map +1 -1
  37. package/dist/helpers.js +1 -0
  38. package/dist/helpers.js.map +1 -1
  39. package/dist/index.js +10 -10
  40. package/dist/index.js.map +1 -1
  41. package/dist/options.d.ts +1 -0
  42. package/dist/options.d.ts.map +1 -1
  43. package/dist/options.js +18 -0
  44. package/dist/options.js.map +1 -1
  45. package/dist/push/index.d.ts.map +1 -1
  46. package/dist/push/index.js +1 -1
  47. package/dist/push/index.js.map +1 -1
  48. package/dist/push/monitor.d.ts +1 -0
  49. package/dist/push/monitor.d.ts.map +1 -1
  50. package/dist/push/monitor.js +18 -1
  51. package/dist/push/monitor.js.map +1 -1
  52. package/dist/reporters/base.d.ts +3 -3
  53. package/dist/reporters/base.d.ts.map +1 -1
  54. package/dist/reporters/base.js +6 -6
  55. package/dist/reporters/base.js.map +1 -1
  56. package/dist/reporters/build_kite_cli.d.ts +2 -4
  57. package/dist/reporters/build_kite_cli.d.ts.map +1 -1
  58. package/dist/reporters/build_kite_cli.js +8 -10
  59. package/dist/reporters/build_kite_cli.js.map +1 -1
  60. package/dist/reporters/json.d.ts +4 -9
  61. package/dist/reporters/json.d.ts.map +1 -1
  62. package/dist/reporters/json.js +31 -40
  63. package/dist/reporters/json.js.map +1 -1
  64. package/dist/reporters/junit.d.ts +2 -2
  65. package/dist/reporters/junit.d.ts.map +1 -1
  66. package/dist/reporters/junit.js +7 -7
  67. package/dist/reporters/junit.js.map +1 -1
  68. package/package.json +2 -2
  69. package/src/cli.ts +24 -5
  70. package/src/common_types.ts +9 -16
  71. package/src/core/gatherer.ts +44 -37
  72. package/src/core/globals.ts +37 -0
  73. package/src/core/index.ts +12 -25
  74. package/src/core/mfa.ts +5 -0
  75. package/src/core/runner.ts +201 -202
  76. package/src/dsl/journey.ts +42 -23
  77. package/src/dsl/monitor.ts +1 -0
  78. package/src/dsl/step.ts +16 -7
  79. package/src/helpers.ts +4 -3
  80. package/src/index.ts +2 -2
  81. package/src/options.ts +22 -0
  82. package/src/push/index.ts +3 -4
  83. package/src/push/monitor.ts +20 -0
  84. package/src/reporters/base.ts +8 -12
  85. package/src/reporters/build_kite_cli.ts +13 -18
  86. package/src/reporters/json.ts +35 -52
  87. package/src/reporters/junit.ts +8 -10
@@ -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
- export type JourneyCallback = (options: {
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
- }) => void;
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
- callback: JourneyCallback;
60
- location?: Location;
61
- steps: Step[] = [];
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
- callback: JourneyCallback,
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.callback = callback;
82
+ this.#cb = cb;
76
83
  this.location = location;
77
- this.updateMonitor({});
84
+ this._updateMonitor({});
78
85
  }
79
86
 
80
- addStep(name: string, callback: VoidCallback, location?: Location) {
81
- const step = new Step(name, this.steps.length + 1, callback, location);
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
- addHook(type: HookType, callback: HooksCallback) {
87
- this.hooks[type].push(callback);
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
- updateMonitor(config: MonitorConfig) {
105
+ _updateMonitor(config: MonitorConfig) {
91
106
  /**
92
107
  * Use defaults values from journey for monitor object (id, name and tags)
93
108
  */
94
- this.monitor = new Monitor({
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.monitor.setSource(this.location);
102
- this.monitor.setFilter({ match: this.name });
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
- isMatch(matchPattern: string, tagsPattern: Array<string>) {
127
+ _isMatch(matchPattern: string, tagsPattern: Array<string>) {
109
128
  return isMatch(this.tags, this.name, tagsPattern, matchPattern);
110
129
  }
111
130
  }
@@ -58,6 +58,7 @@ export type MonitorConfig = {
58
58
  name?: string;
59
59
  type?: string;
60
60
  tags?: string[];
61
+ fields?: Record<string, string>;
61
62
  schedule?: typeof ALLOWED_SCHEDULES[number];
62
63
  enabled?: boolean;
63
64
  locations?: SyntheticsLocationsType[];
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
- callback: VoidCallback;
32
- location?: Location;
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
- callback: VoidCallback,
45
+ cb: VoidCallback,
41
46
  location: Location
42
47
  ) {
43
48
  this.name = name;
44
49
  this.index = index;
45
- this.callback = callback;
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
- `It is recommended to run the agent in an NPM project.\n` +
155
- `You can create one by running "npm init -y" in the project folder.`
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.run(options);
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
- opts.schedule
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
@@ -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,
@@ -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, result: StepEndResult) {
74
- const { status, end, start, error } = result;
69
+ onStepEnd(_: Journey, step: Step, { }: StepResult) {
70
+ const { status, error } = step;
75
71
  const message = `${symbols[status]} Step: '${step.name}' ${status} ${gray(
76
- '(' + renderDuration((end - start) * 1000) + ' ms)'
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(_: Journey, { error }: JourneyEndResult) {
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<StepEndResult & { name: string }>> = new Map();
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({ name: step.name, ...result });
55
+ this.journeys.get(journey.name)?.push(step);
56
56
  }
57
57
 
58
- override async onJourneyEnd(journey: Journey, endResult: JourneyEndResult) {
59
- const { start, end, status } = endResult;
60
- super.onJourneyEnd(journey, endResult);
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(stepResult => {
82
- const { status, end, start, error, name: stepName } = stepResult;
83
- const message = `${
84
- symbols[status]
85
- } Step: '${stepName}' ${status} (${renderDuration(
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
  });
@@ -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> & Duration;
100
+ journey?: Partial<Journey>;
98
101
  timestamp?: number;
99
102
  url?: string;
100
- step?: Partial<Step> & Duration;
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: OutputFields['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
- return {
262
- name: journey.name,
263
- id: journey.id,
264
- tags: journey.tags,
265
- status: type === 'journey/end' ? status : undefined,
266
- duration: journey.duration,
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: OutputFields['step'],
273
+ step: Partial<Step>,
272
274
  type: OutputFields['type'],
273
- status: Payload['status']
274
- ) {
275
+ ): Omit<Partial<Step>, 'duration'> & Duration {
275
276
  if (!step) {
276
277
  return;
277
278
  }
278
- return {
279
- name: step.name,
280
- index: step.index,
281
- status: type === 'step/end' ? status : undefined,
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.callback.toString() },
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
- ...step,
437
- duration: {
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.callback.toString(),
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, payload?.status),
617
- step: stepInfo(step, type, payload?.status),
599
+ journey: journeyInfo(journey, type),
600
+ step: stepInfo(step, type),
618
601
  root_fields: { ...(root_fields || {}), ...getMetadata() },
619
602
  payload,
620
603
  blob,
@@ -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: end - start,
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.message,
105
- type: error.name,
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
  }