@elastic/synthetics 1.0.0-beta.22 → 1.0.0-beta.25

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 (81) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/NOTICE.txt +0 -29
  3. package/dist/cli.js +55 -184
  4. package/dist/cli.js.map +1 -1
  5. package/dist/common_types.d.ts +43 -36
  6. package/dist/common_types.d.ts.map +1 -1
  7. package/dist/core/gatherer.d.ts +2 -3
  8. package/dist/core/gatherer.d.ts.map +1 -1
  9. package/dist/core/gatherer.js +17 -9
  10. package/dist/core/gatherer.js.map +1 -1
  11. package/dist/core/index.d.ts +1 -1
  12. package/dist/core/index.d.ts.map +1 -1
  13. package/dist/core/index.js +7 -9
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/core/runner.d.ts +1 -8
  16. package/dist/core/runner.d.ts.map +1 -1
  17. package/dist/core/runner.js +2 -3
  18. package/dist/core/runner.js.map +1 -1
  19. package/dist/dsl/journey.d.ts +4 -3
  20. package/dist/dsl/journey.d.ts.map +1 -1
  21. package/dist/dsl/journey.js +4 -3
  22. package/dist/dsl/journey.js.map +1 -1
  23. package/dist/dsl/step.d.ts +3 -2
  24. package/dist/dsl/step.d.ts.map +1 -1
  25. package/dist/dsl/step.js +2 -1
  26. package/dist/dsl/step.js.map +1 -1
  27. package/dist/formatter/javascript.d.ts +31 -6
  28. package/dist/formatter/javascript.d.ts.map +1 -1
  29. package/dist/formatter/javascript.js +45 -24
  30. package/dist/formatter/javascript.js.map +1 -1
  31. package/dist/helpers.d.ts +2 -1
  32. package/dist/helpers.d.ts.map +1 -1
  33. package/dist/helpers.js +30 -1
  34. package/dist/helpers.js.map +1 -1
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -17
  38. package/dist/index.js.map +1 -1
  39. package/dist/{parse_args.d.ts → loader.d.ts} +2 -5
  40. package/dist/loader.d.ts.map +1 -0
  41. package/dist/loader.js +144 -0
  42. package/dist/loader.js.map +1 -0
  43. package/dist/options.d.ts +27 -0
  44. package/dist/options.d.ts.map +1 -0
  45. package/dist/options.js +108 -0
  46. package/dist/options.js.map +1 -0
  47. package/dist/plugins/network.d.ts +17 -33
  48. package/dist/plugins/network.d.ts.map +1 -1
  49. package/dist/plugins/network.js +179 -245
  50. package/dist/plugins/network.js.map +1 -1
  51. package/dist/plugins/plugin-manager.d.ts +1 -1
  52. package/dist/plugins/plugin-manager.d.ts.map +1 -1
  53. package/dist/plugins/plugin-manager.js +2 -2
  54. package/dist/plugins/plugin-manager.js.map +1 -1
  55. package/dist/reporters/json.d.ts +0 -1
  56. package/dist/reporters/json.d.ts.map +1 -1
  57. package/dist/reporters/json.js +5 -24
  58. package/dist/reporters/json.js.map +1 -1
  59. package/dist/sdk/trace-metrics.js +3 -4
  60. package/dist/sdk/trace-metrics.js.map +1 -1
  61. package/dist/tsconfig.tsbuildinfo +1 -1
  62. package/package.json +5 -4
  63. package/src/cli.ts +114 -188
  64. package/src/common_types.ts +47 -36
  65. package/src/core/gatherer.ts +17 -10
  66. package/src/core/index.ts +22 -16
  67. package/src/core/runner.ts +3 -23
  68. package/src/dsl/journey.ts +10 -4
  69. package/src/dsl/step.ts +9 -2
  70. package/src/formatter/javascript.ts +59 -22
  71. package/src/helpers.ts +40 -1
  72. package/src/index.ts +10 -16
  73. package/src/loader.ts +162 -0
  74. package/src/options.ts +116 -0
  75. package/src/plugins/network.ts +218 -293
  76. package/src/plugins/plugin-manager.ts +2 -2
  77. package/src/reporters/json.ts +1 -17
  78. package/dist/parse_args.d.ts.map +0 -1
  79. package/dist/parse_args.js +0 -103
  80. package/dist/parse_args.js.map +0 -1
  81. package/src/parse_args.ts +0 -158
package/src/cli.ts CHANGED
@@ -25,200 +25,126 @@
25
25
  *
26
26
  */
27
27
 
28
- import { stdin, cwd } from 'process';
29
- import { resolve } from 'path';
30
- import merge from 'deepmerge';
31
- import { step, journey } from './core';
32
- import { log } from './core/logger';
33
- import program, { options } from './parse_args';
34
- import { expect } from './core/expect';
35
- import {
36
- findPkgJsonByTraversing,
37
- isDepInstalled,
38
- isDirectory,
39
- totalist,
40
- parseNetworkConditions,
41
- } from './helpers';
28
+ import { program, Option } from 'commander';
29
+ import { CliArgs } from './common_types';
30
+ import { reporters } from './reporters';
31
+ import { DEFAULT_NETWORK_CONDITIONS_ARG } from './helpers';
32
+ import { normalizeOptions } from './options';
33
+ import { loadTestFiles } from './loader';
42
34
  import { run } from './';
43
- import { readConfig } from './config';
44
35
 
45
- const resolvedCwd = cwd();
46
- /**
47
- * Set debug based on DEBUG ENV and -d flags
48
- * namespace - synthetics
49
- */
50
- const namespace = 'synthetics';
51
- if (process.env.DEBUG === namespace || Boolean(options.debug)) {
52
- process.env.DEBUG = '1';
53
- }
54
-
55
- const loadInlineScript = source => {
56
- const scriptFn = new Function(
57
- 'step',
58
- 'page',
59
- 'context',
60
- 'browser',
61
- 'params',
62
- 'expect',
63
- source
64
- );
65
- journey('inline', ({ page, context, browser, params }) => {
66
- scriptFn.apply(null, [step, page, context, browser, params, expect]);
67
- });
68
- };
69
-
70
- async function readStdin() {
71
- const chunks = [];
72
- stdin.resume();
73
- stdin.setEncoding('utf-8');
74
- for await (const chunk of stdin) {
75
- chunks.push(chunk);
76
- }
77
- return chunks.join();
78
- }
79
-
80
- function requireSuites(suites: Iterable<string>) {
81
- for (const suite of suites) {
82
- require(suite);
83
- }
84
- }
85
-
86
- /**
87
- * Handle both directory and files that are passed through TTY
88
- * and add them to suites
89
- */
90
- async function prepareSuites(inputs: string[]) {
91
- const suites = new Set<string>();
92
- const addSuite = absPath => {
93
- log(`Processing file: ${absPath}`);
94
- suites.add(require.resolve(absPath));
95
- };
96
- /**
97
- * Match all files inside the directory with the
98
- * .journey.{mjs|cjs|js|ts) extensions
99
- */
100
- const pattern = options.pattern
101
- ? new RegExp(options.pattern, 'i')
102
- : /.+\.journey\.([mc]js|[jt]s?)$/;
103
- /**
104
- * Ignore node_modules by default when running suites
105
- */
106
- const ignored = /node_modules/i;
36
+ /* eslint-disable-next-line @typescript-eslint/no-var-requires */
37
+ const { name, version } = require('../package.json');
107
38
 
108
- for (const input of inputs) {
109
- const absPath = resolve(resolvedCwd, input);
110
- /**
111
- * Validate for package.json file before running
112
- * the suites
113
- */
114
- findPkgJsonByTraversing(absPath, resolvedCwd);
115
- if (isDirectory(absPath)) {
116
- await totalist(absPath, (rel, abs) => {
117
- if (pattern.test(rel) && !ignored.test(rel)) {
118
- addSuite(abs);
39
+ program
40
+ .name(`npx ${name}`)
41
+ .usage('[options] [dir] [files] file')
42
+ .option(
43
+ '-c, --config <path>',
44
+ 'configuration path (default: synthetics.config.js)'
45
+ )
46
+ .option(
47
+ '-p, --params <jsonstring>',
48
+ 'JSON object that gets injected to all journeys',
49
+ JSON.parse
50
+ )
51
+ .addOption(
52
+ new Option('--reporter <value>', `output repoter format`).choices(
53
+ Object.keys(reporters)
54
+ )
55
+ )
56
+ .option(
57
+ '--pattern <pattern>',
58
+ 'RegExp file patterns to search inside directory'
59
+ )
60
+ .option('--inline', 'Run inline journeys from heartbeat')
61
+ .option('-r, --require <modules...>', 'module(s) to preload')
62
+ .option('--no-headless', 'run browser in headful mode')
63
+ .option('--sandbox', 'enable chromium sandboxing', false)
64
+ .option('--rich-events', 'Mimics a heartbeat run')
65
+ .option(
66
+ '--capability <features...>',
67
+ 'Enable capabilities through feature flags'
68
+ )
69
+ .addOption(
70
+ new Option('--screenshots [flag]', 'take screenshots at end of each step')
71
+ .choices(['on', 'off', 'only-on-failure'])
72
+ .default('on')
73
+ )
74
+ .option(
75
+ '--dry-run',
76
+ "don't actually execute anything, report only registered journeys"
77
+ )
78
+ .option(
79
+ '--match <name>',
80
+ 'run only journeys with a name or tags that matches the glob'
81
+ )
82
+ .option(
83
+ '--tags <name...>',
84
+ 'run only journeys with the given tag(s), or globs'
85
+ )
86
+ .option(
87
+ '--outfd <fd>',
88
+ 'specify a file descriptor for logs. Default is stdout',
89
+ parseInt
90
+ )
91
+ .option(
92
+ '--ws-endpoint <endpoint>',
93
+ 'Browser WebSocket endpoint to connect to'
94
+ )
95
+ .option(
96
+ '--pause-on-error',
97
+ 'pause on error until a keypress is made in the console. Useful during development'
98
+ )
99
+ .option(
100
+ '--ignore-https-errors',
101
+ 'ignores any HTTPS errors in sites being tested, including ones related to unrecognized certs or signatures. This can be insecure!'
102
+ )
103
+ .option(
104
+ '--quiet-exit-code',
105
+ 'always return 0 as an exit code status, regardless of test pass / fail. Only return > 0 exit codes on internal errors where the suite could not be run'
106
+ )
107
+ .option(
108
+ '--throttling <d/u/l>',
109
+ 'List of options to throttle network conditions for download throughput (d) in megabits/second, upload throughput (u) in megabits/second and latency (l) in milliseconds.',
110
+ DEFAULT_NETWORK_CONDITIONS_ARG
111
+ )
112
+ .option('--no-throttling', 'Turns off default network throttling.')
113
+ .option(
114
+ '--playwright-options <jsonstring>',
115
+ 'JSON object to pass in custom Playwright options for the agent. Options passed will be merged with Playwright options defined in your synthetics.config.js file. Options defined via --playwright-options take precedence.',
116
+ JSON.parse
117
+ )
118
+ .version(version)
119
+ .description('Run synthetic tests')
120
+ .action(async (cliArgs: CliArgs) => {
121
+ try {
122
+ await loadTestFiles(cliArgs, program.args);
123
+ const options = normalizeOptions(cliArgs);
124
+ const results = await run(options);
125
+ /**
126
+ * Exit with error status if any journey fails
127
+ */
128
+ if (!options.quietExitCode) {
129
+ for (const result of Object.values(results)) {
130
+ if (result.status === 'failed') {
131
+ process.exit(1);
132
+ }
119
133
  }
120
- });
121
- } else {
122
- addSuite(absPath);
123
- }
124
- }
125
- return suites.values();
126
- }
127
-
128
- (async () => {
129
- /**
130
- * Transform `.ts` files out of the box by invoking
131
- * the `ts-node` via `transpile-only` mode that compiles
132
- * TS files without doing any extensive type checks.
133
- *
134
- * We must register `ts-node` _before_ loading inline
135
- * scripts too because otherwise we will not be able to
136
- * require `.ts` configuration files.
137
- */
138
- /* eslint-disable-next-line @typescript-eslint/no-var-requires */
139
- require('ts-node').register({
140
- transpileOnly: true,
141
- compilerOptions: {
142
- esModuleInterop: true,
143
- allowJs: true,
144
- target: 'es2018',
145
- },
146
- });
147
-
148
- if (options.inline) {
149
- const source = await readStdin();
150
- loadInlineScript(source);
151
- } else {
152
- /**
153
- * Preload modules before running the suites
154
- */
155
- const modules = [].concat(options.require || []).filter(Boolean);
156
- for (const name of modules) {
157
- if (isDepInstalled(name)) {
158
- require(name);
159
- } else {
160
- throw new Error(`cannot find module '${name}'`);
161
134
  }
135
+ } catch (e) {
136
+ console.error(e);
137
+ process.exit(1);
162
138
  }
163
- /**
164
- * Handle piped files by reading the STDIN
165
- * ex: ls example/suites/*.js | npx @elastic/synthetics
166
- */
167
- const files =
168
- program.args.length > 0
169
- ? program.args
170
- : (await readStdin()).split('\n').filter(Boolean);
171
- const suites = await prepareSuites(files);
172
- requireSuites(suites);
173
- }
174
-
175
- /**
176
- * Use the NODE_ENV variable to control the environment
177
- */
178
- const environment = process.env['NODE_ENV'] || 'development';
179
- /**
180
- * Validate and handle configs
181
- */
182
- const config =
183
- options.config || !options.inline
184
- ? readConfig(environment, options.config)
185
- : {};
186
- const params = merge(config.params, options.params || {});
187
-
188
- /**
189
- * Favor playwright options passed via cli to inline playwright options
190
- */
191
- const playwrightOptions = merge.all([
192
- config.playwrightOptions || {},
193
- options.playwrightOptions || {},
194
- {
195
- headless: options.headless,
196
- chromiumSandbox: options.sandbox,
197
- ignoreHTTPSErrors: options.ignoreHttpsErrors,
198
- },
199
- ]);
139
+ });
200
140
 
201
- const results = await run({
202
- params: Object.freeze(params),
203
- networkConditions: options.throttling
204
- ? parseNetworkConditions(options.throttling as string)
205
- : undefined,
206
- environment,
207
- playwrightOptions,
208
- ...options,
141
+ program
142
+ .command('push')
143
+ .description(
144
+ 'Push monitors to create new montors with Kibana monitor management UI'
145
+ )
146
+ .action(() => {
147
+ throw new Error('TODO: Implement me');
209
148
  });
210
149
 
211
- if (!options.quietExitCode) {
212
- /**
213
- * Exit with error status if any journey fails
214
- */
215
- for (const result of Object.values(results)) {
216
- if (result.status === 'failed') {
217
- process.exit(1);
218
- }
219
- }
220
- }
221
- })().catch(e => {
222
- console.error(e);
223
- process.exit(1);
224
- });
150
+ program.parse(process.argv);
@@ -31,18 +31,17 @@ import {
31
31
  ChromiumBrowserContext,
32
32
  Page,
33
33
  } from 'playwright-chromium';
34
- import { Protocol } from 'playwright-chromium/types/protocol';
35
34
  import { Step } from './dsl';
36
- import { reporters } from './reporters';
35
+ import { Reporter, reporters } from './reporters';
37
36
 
38
37
  export type VoidCallback = () => void;
39
- export type Params = Record<string, any>;
40
- export type NetworkConditions = {
41
- offline: boolean;
42
- downloadThroughput: number;
43
- uploadThroughput: number;
44
- latency: number;
38
+ export type Location = {
39
+ file: string;
40
+ line: number;
41
+ column: number;
45
42
  };
43
+
44
+ export type Params = Record<string, any>;
46
45
  export type HooksArgs = {
47
46
  env: string;
48
47
  params: Params;
@@ -51,6 +50,13 @@ export type HooksCallback = (args: HooksArgs) => void;
51
50
  export type StatusValue = 'succeeded' | 'failed' | 'skipped';
52
51
  export type Reporters = keyof typeof reporters;
53
52
 
53
+ export type NetworkConditions = {
54
+ offline: boolean;
55
+ downloadThroughput: number;
56
+ uploadThroughput: number;
57
+ latency: number;
58
+ };
59
+
54
60
  export type Driver = {
55
61
  browser: ChromiumBrowser;
56
62
  context: ChromiumBrowserContext;
@@ -123,11 +129,9 @@ export type Request = {
123
129
 
124
130
  export type Response = {
125
131
  url?: string;
126
- protocol?: string;
127
132
  status: number;
128
133
  statusText?: string;
129
- mimeType: string;
130
- httpVersion?: string;
134
+ mimeType?: string;
131
135
  headers: Record<string, string>;
132
136
  // Total size in bytes of the response (body and headers)
133
137
  bytes?: number;
@@ -141,7 +145,6 @@ export type Response = {
141
145
  remoteIPAddress?: string;
142
146
  remotePort?: number;
143
147
  fromServiceWorker?: boolean;
144
- timing?: Protocol.Network.ResourceTiming;
145
148
  };
146
149
 
147
150
  export type NetworkInfo = {
@@ -149,19 +152,17 @@ export type NetworkInfo = {
149
152
  browser: BrowserInfo;
150
153
  type: string;
151
154
  request: Request;
152
- response?: Response;
155
+ response: Response;
153
156
  isNavigationRequest: boolean;
154
157
  requestSentTime: number;
155
158
  loadEndTime: number;
156
159
  responseReceivedTime: number;
157
160
  resourceSize: number;
158
161
  transferSize: number;
159
- timings?: {
162
+ timings: {
160
163
  blocked: number;
161
- queueing: number;
162
164
  dns: number;
163
165
  ssl: number;
164
- proxy: number;
165
166
  connect: number;
166
167
  send: number;
167
168
  wait: number;
@@ -186,34 +187,44 @@ export type PluginOutput = {
186
187
 
187
188
  export type ScreenshotOptions = 'on' | 'off' | 'only-on-failure';
188
189
 
189
- export type CliArgs = {
190
- capability?: Array<string>;
191
- config?: string;
192
- outfd?: number;
193
- headless?: boolean;
190
+ type BaseArgs = {
191
+ params?: Params;
194
192
  screenshots?: ScreenshotOptions;
195
- ssblocks?: boolean;
196
- metrics?: boolean;
197
- filmstrips?: boolean;
198
- trace?: boolean;
199
193
  dryRun?: boolean;
200
- network?: boolean;
194
+ match?: string;
195
+ tags?: Array<string>;
196
+ outfd?: number;
197
+ wsEndpoint?: string;
201
198
  pauseOnError?: boolean;
199
+ ignoreHttpsErrors?: boolean;
200
+ playwrightOptions?: PlaywrightOptions;
202
201
  quietExitCode?: boolean;
202
+ };
203
+
204
+ export type CliArgs = BaseArgs & {
205
+ config?: string;
203
206
  reporter?: Reporters;
204
- wsEndpoint?: string;
205
- sandbox?: boolean;
206
207
  pattern?: string;
207
- inline: boolean;
208
- match?: string;
209
- tags?: Array<string>;
210
- require: Array<string>;
211
- debug?: boolean;
208
+ inline?: boolean;
209
+ require?: Array<string>;
210
+ headless?: boolean;
211
+ sandbox?: boolean;
212
+ richEvents?: boolean;
213
+ capability?: Array<string>;
212
214
  ignoreHttpsErrors?: boolean;
213
- params?: Params;
214
215
  throttling?: boolean | string;
215
- playwrightOptions?: LaunchOptions & BrowserContextOptions;
216
- richEvents?: boolean;
216
+ };
217
+
218
+ export type RunOptions = BaseArgs & {
219
+ metrics?: boolean;
220
+ ssblocks?: boolean;
221
+ network?: boolean;
222
+ trace?: boolean;
223
+ filmstrips?: boolean;
224
+ environment?: string;
225
+ playwrightOptions?: PlaywrightOptions;
226
+ networkConditions?: NetworkConditions;
227
+ reporter?: CliArgs['reporter'] | Reporter;
217
228
  };
218
229
 
219
230
  export type PlaywrightOptions = LaunchOptions & BrowserContextOptions;
@@ -25,9 +25,8 @@
25
25
 
26
26
  import { chromium, ChromiumBrowser, BrowserContext } from 'playwright-chromium';
27
27
  import { PluginManager } from '../plugins';
28
- import { RunOptions } from './runner';
29
28
  import { log } from './logger';
30
- import { Driver } from '../common_types';
29
+ import { Driver, RunOptions } from '../common_types';
31
30
 
32
31
  /**
33
32
  * Purpose of the Gatherer is to set up the necessary browser driver
@@ -58,7 +57,7 @@ export class Gatherer {
58
57
  ...playwrightOptions,
59
58
  userAgent: await Gatherer.getUserAgent(playwrightOptions?.userAgent),
60
59
  });
61
- await Gatherer.setNetworkConditions(context, networkConditions);
60
+ Gatherer.setNetworkConditions(context, networkConditions);
62
61
 
63
62
  const page = await context.newPage();
64
63
  const client = await context.newCDPSession(page);
@@ -74,18 +73,26 @@ export class Gatherer {
74
73
  return userAgent + syntheticsIdentifier;
75
74
  }
76
75
 
77
- static async setNetworkConditions(
76
+ static setNetworkConditions(
78
77
  context: BrowserContext,
79
78
  networkConditions: RunOptions['networkConditions']
80
79
  ) {
81
80
  if (networkConditions) {
82
- context.on('page', async page => {
81
+ context.on('page', page => {
83
82
  const context = page.context();
84
- const client = await context.newCDPSession(page);
85
- await client.send(
86
- 'Network.emulateNetworkConditions',
87
- networkConditions
88
- );
83
+ const emulatePromise = context
84
+ .newCDPSession(page)
85
+ .then(client =>
86
+ client.send('Network.emulateNetworkConditions', networkConditions)
87
+ );
88
+ /**
89
+ * Guard against pages that gets closed before the emulation kicks to capture
90
+ * unhandled rejections from accessing the CDP session of closed page
91
+ */
92
+ Promise.race([
93
+ new Promise<void>(resolve => page.on('close', () => resolve())),
94
+ emulatePromise,
95
+ ]);
89
96
  });
90
97
  }
91
98
  }
package/src/core/index.ts CHANGED
@@ -25,7 +25,8 @@
25
25
 
26
26
  import { Journey, JourneyCallback, JourneyOptions } from '../dsl';
27
27
  import Runner from './runner';
28
- import { VoidCallback, HooksCallback } from '../common_types';
28
+ import { VoidCallback, HooksCallback, Location } from '../common_types';
29
+ import { wrapFnWithLocation } from '../helpers';
29
30
  import { log } from './logger';
30
31
 
31
32
  /**
@@ -39,23 +40,28 @@ if (!global[SYNTHETICS_RUNNER]) {
39
40
 
40
41
  export const runner: Runner = global[SYNTHETICS_RUNNER];
41
42
 
42
- export const journey = (
43
- options: JourneyOptions | string,
44
- callback: JourneyCallback
45
- ) => {
46
- log(`register journey: ${JSON.stringify(options)}`);
47
- if (typeof options === 'string') {
48
- options = { name: options, id: options };
43
+ export const journey = wrapFnWithLocation(
44
+ (
45
+ location: Location,
46
+ options: JourneyOptions | string,
47
+ callback: JourneyCallback
48
+ ) => {
49
+ log(`register journey: ${JSON.stringify(options)}`);
50
+ if (typeof options === 'string') {
51
+ options = { name: options, id: options };
52
+ }
53
+ const j = new Journey(options, callback, location);
54
+ runner.addJourney(j);
55
+ return j;
49
56
  }
50
- const j = new Journey(options, callback);
51
- runner.addJourney(j);
52
- return j;
53
- };
57
+ );
54
58
 
55
- export const step = (name: string, callback: VoidCallback) => {
56
- log(`register step: ${name}`);
57
- return runner.currentJourney?.addStep(name, callback);
58
- };
59
+ export const step = wrapFnWithLocation(
60
+ (location: Location, name: string, callback: VoidCallback) => {
61
+ log(`register step: ${name}`);
62
+ return runner.currentJourney?.addStep(name, callback, location);
63
+ }
64
+ );
59
65
 
60
66
  export const beforeAll = (callback: HooksCallback) => {
61
67
  runner.addHook('beforeAll', callback);
@@ -28,7 +28,7 @@ import { join } from 'path';
28
28
  import { rm } from 'fs/promises';
29
29
  import { Journey } from '../dsl/journey';
30
30
  import { Step } from '../dsl/step';
31
- import { reporters, Reporter } from '../reporters';
31
+ import { reporters } from '../reporters';
32
32
  import {
33
33
  CACHE_PATH,
34
34
  monotonicTimeInSeconds,
@@ -44,36 +44,16 @@ import {
44
44
  Params,
45
45
  NetworkConditions,
46
46
  PluginOutput,
47
- CliArgs,
48
47
  HooksArgs,
49
- PlaywrightOptions,
50
48
  Driver,
51
49
  Screenshot,
50
+ RunOptions,
52
51
  } from '../common_types';
53
52
  import { PageMetrics, PluginManager } from '../plugins';
54
53
  import { PerformanceManager } from '../plugins';
55
54
  import { Gatherer } from './gatherer';
56
55
  import { log } from './logger';
57
56
 
58
- export type RunOptions = Omit<
59
- CliArgs,
60
- | 'debug'
61
- | 'pattern'
62
- | 'inline'
63
- | 'require'
64
- | 'reporter'
65
- | 'richEvents'
66
- | 'capability'
67
- | 'sandbox'
68
- | 'headless'
69
- | 'throttling'
70
- > & {
71
- environment?: string;
72
- playwrightOptions?: PlaywrightOptions;
73
- networkConditions?: NetworkConditions;
74
- reporter?: CliArgs['reporter'] | Reporter;
75
- };
76
-
77
57
  type HookType = 'beforeAll' | 'afterAll';
78
58
  export type SuiteHooks = Record<HookType, Array<HooksCallback>>;
79
59
 
@@ -352,7 +332,7 @@ export default class Runner extends EventEmitter {
352
332
  ) {
353
333
  const end = monotonicTimeInSeconds();
354
334
  const { pluginManager, start, status, error } = result;
355
- const pluginOutput = pluginManager.output();
335
+ const pluginOutput = await pluginManager.output();
356
336
  this.emit('journey:end', {
357
337
  journey,
358
338
  status,
@@ -26,7 +26,7 @@
26
26
  import { Browser, Page, BrowserContext, CDPSession } from 'playwright-chromium';
27
27
  import micromatch, { isMatch } from 'micromatch';
28
28
  import { Step } from './step';
29
- import { VoidCallback, HooksCallback, Params } from '../common_types';
29
+ import { VoidCallback, HooksCallback, Params, Location } from '../common_types';
30
30
 
31
31
  export type JourneyOptions = {
32
32
  name: string;
@@ -49,18 +49,24 @@ export class Journey {
49
49
  id?: string;
50
50
  tags?: string[];
51
51
  callback: JourneyCallback;
52
+ location?: Location;
52
53
  steps: Step[] = [];
53
54
  hooks: Hooks = { before: [], after: [] };
54
55
 
55
- constructor(options: JourneyOptions, callback: JourneyCallback) {
56
+ constructor(
57
+ options: JourneyOptions,
58
+ callback: JourneyCallback,
59
+ location?: Location
60
+ ) {
56
61
  this.name = options.name;
57
62
  this.id = options.id || options.name;
58
63
  this.tags = options.tags;
59
64
  this.callback = callback;
65
+ this.location = location;
60
66
  }
61
67
 
62
- addStep(name: string, callback: VoidCallback) {
63
- const step = new Step(name, this.steps.length + 1, callback);
68
+ addStep(name: string, callback: VoidCallback, location?: Location) {
69
+ const step = new Step(name, this.steps.length + 1, callback, location);
64
70
  this.steps.push(step);
65
71
  return step;
66
72
  }
package/src/dsl/step.ts CHANGED
@@ -23,16 +23,23 @@
23
23
  *
24
24
  */
25
25
 
26
- import { VoidCallback } from '../common_types';
26
+ import { Location, VoidCallback } from '../common_types';
27
27
 
28
28
  export class Step {
29
29
  name: string;
30
30
  index: number;
31
31
  callback: VoidCallback;
32
+ location?: Location;
32
33
 
33
- constructor(name: string, index: number, callback: VoidCallback) {
34
+ constructor(
35
+ name: string,
36
+ index: number,
37
+ callback: VoidCallback,
38
+ location: Location
39
+ ) {
34
40
  this.name = name;
35
41
  this.index = index;
36
42
  this.callback = callback;
43
+ this.location = location;
37
44
  }
38
45
  }