cypress 5.6.0 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -12,7 +12,7 @@ After installing you'll be able to:
12
12
 
13
13
  ## Install
14
14
 
15
- Requires Node version >= 4.0.0
15
+ Requires Node version >= 10.0.0
16
16
 
17
17
  ```sh
18
18
  npm install --save-dev cypress
package/lib/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ // @ts-check
3
4
  const _ = require('lodash');
4
5
 
5
6
  const R = require('ramda');
@@ -156,11 +157,58 @@ function includesVersion(args) {
156
157
  return _.includes(args, 'version') || _.includes(args, '--version') || _.includes(args, '-v');
157
158
  }
158
159
 
159
- function showVersions() {
160
+ function showVersions(args) {
160
161
  debug('printing Cypress version');
161
- return require('./exec/versions').getVersions().then((versions = {}) => {
162
+ debug('additional arguments %o', args);
163
+ const versionParser = commander.option('--component <package|binary|electron|node>', 'component to report version for').allowUnknownOption(true);
164
+ const parsed = versionParser.parse(args);
165
+ const parsedOptions = {
166
+ component: parsed.component
167
+ };
168
+ debug('parsed version arguments %o', parsedOptions);
169
+
170
+ const reportAllVersions = versions => {
162
171
  logger.always('Cypress package version:', versions.package);
163
172
  logger.always('Cypress binary version:', versions.binary);
173
+ logger.always('Electron version:', versions.electronVersion);
174
+ logger.always('Bundled Node version:', versions.electronNodeVersion);
175
+ };
176
+
177
+ const reportComponentVersion = (componentName, versions) => {
178
+ const names = {
179
+ package: 'package',
180
+ binary: 'binary',
181
+ electron: 'electronVersion',
182
+ node: 'electronNodeVersion'
183
+ };
184
+
185
+ if (!names[componentName]) {
186
+ throw new Error(`Unknown component name "${componentName}"`);
187
+ }
188
+
189
+ const name = names[componentName];
190
+
191
+ if (!versions[name]) {
192
+ throw new Error(`Cannot find version for component "${componentName}" under property "${name}"`);
193
+ }
194
+
195
+ const version = versions[name];
196
+ logger.always(version);
197
+ };
198
+
199
+ const defaultVersions = {
200
+ package: undefined,
201
+ binary: undefined,
202
+ electronVersion: undefined,
203
+ electronNodeVersion: undefined
204
+ };
205
+ return require('./exec/versions').getVersions().then((versions = defaultVersions) => {
206
+ if (parsedOptions.component) {
207
+ reportComponentVersion(parsedOptions.component, versions);
208
+ } else {
209
+ reportAllVersions(versions);
210
+ }
211
+
164
212
  process.exit(0);
165
213
  }).catch(util.logErrorExit1);
166
214
  }
@@ -266,7 +314,9 @@ module.exports = {
266
314
  program.command('help').description('Shows CLI help and exits').action(() => {
267
315
  program.help();
268
316
  });
269
- program.option('-v, --version', text('version')).command('version').description(text('version')).action(showVersions);
317
+ program.option('-v, --version', text('version')).command('version').description(text('version')).action(() => {
318
+ showVersions(args);
319
+ });
270
320
  addCypressRunCommand(program).action((...fnArgs) => {
271
321
  debug('running Cypress with args %o', fnArgs);
272
322
 
@@ -346,14 +396,14 @@ module.exports = {
346
396
  // and now does not understand top level options
347
397
  // .option('-v, --version').command('version')
348
398
  // so we have to manually catch '-v, --version'
349
- return showVersions();
399
+ return showVersions(args);
350
400
  }
351
401
 
352
402
  debug('program parsing arguments');
353
403
  return program.parse(args);
354
404
  }
355
405
 
356
- };
406
+ }; // @ts-ignore
357
407
 
358
408
  if (!module.parent) {
359
409
  logger.error('This CLI module should be required from another Node module');
package/lib/errors.js CHANGED
@@ -225,24 +225,6 @@ const childProcessKilled = (eventName, signal) => {
225
225
  };
226
226
  };
227
227
 
228
- const removed = {
229
- CYPRESS_BINARY_VERSION: {
230
- description: stripIndent`
231
- The environment variable CYPRESS_BINARY_VERSION has been renamed to CYPRESS_INSTALL_BINARY as of version ${chalk.green('3.0.0')}
232
- `,
233
- solution: stripIndent`
234
- You should set CYPRESS_INSTALL_BINARY instead.
235
- `
236
- },
237
- CYPRESS_SKIP_BINARY_INSTALL: {
238
- description: stripIndent`
239
- The environment variable CYPRESS_SKIP_BINARY_INSTALL has been removed as of version ${chalk.green('3.0.0')}
240
- `,
241
- solution: stripIndent`
242
- To skip the binary install, set CYPRESS_INSTALL_BINARY=0
243
- `
244
- }
245
- };
246
228
  const CYPRESS_RUN_BINARY = {
247
229
  notValid: value => {
248
230
  const properFormat = `**/${state.getPlatformExecutable()}`;
@@ -404,7 +386,6 @@ module.exports = {
404
386
  failedUnzip,
405
387
  invalidCypressEnv,
406
388
  invalidCacheDirectory,
407
- removed,
408
389
  CYPRESS_RUN_BINARY,
409
390
  smokeTestFailure,
410
391
  childProcessKilled,
package/lib/exec/run.js CHANGED
@@ -78,13 +78,6 @@ const processRunOptions = (options = {}) => {
78
78
  args.push('--browser', options.browser);
79
79
  }
80
80
 
81
- if (options.ci) {
82
- // push to display the deprecation message
83
- args.push('--ci'); // also automatically record
84
-
85
- args.push('--record', true);
86
- }
87
-
88
81
  if (options.ciBuildId) {
89
82
  args.push('--ci-build-id', options.ciBuildId);
90
83
  }
@@ -124,7 +117,7 @@ const processRunOptions = (options = {}) => {
124
117
 
125
118
  if (options.key == null) {
126
119
  debug('--key is not set, looking up environment variable CYPRESS_RECORD_KEY');
127
- options.key = util.getEnv('CYPRESS_RECORD_KEY') || util.getEnv('CYPRESS_CI_KEY');
120
+ options.key = util.getEnv('CYPRESS_RECORD_KEY');
128
121
  } // if we have a key assume we're in record mode
129
122
 
130
123
 
@@ -150,7 +143,7 @@ const processRunOptions = (options = {}) => {
150
143
  // already in ci mode, then send it up
151
144
 
152
145
 
153
- if (options.record != null && !options.ci) {
146
+ if (options.record != null) {
154
147
  args.push('--record', options.record);
155
148
  } // if we have a specific reporter push that into the args
156
149
 
@@ -34,11 +34,23 @@ const getVersions = () => {
34
34
  }
35
35
 
36
36
  return state.getBinaryDir();
37
- }).then(state.getBinaryPkgVersionAsync).then(binaryVersion => {
38
- return {
37
+ }).then(state.getBinaryPkgAsync).then(pkg => {
38
+ const versions = {
39
+ binary: state.getBinaryPkgVersion(pkg),
40
+ electronVersion: state.getBinaryElectronVersion(pkg),
41
+ electronNodeVersion: state.getBinaryElectronNodeVersion(pkg)
42
+ };
43
+ debug('binary versions %o', versions);
44
+ return versions;
45
+ }).then(binaryVersions => {
46
+ const versions = {
39
47
  package: util.pkgVersion(),
40
- binary: binaryVersion || 'not installed'
48
+ binary: binaryVersions.binary || 'not installed',
49
+ electronVersion: binaryVersions.electronVersion || 'not found',
50
+ electronNodeVersion: binaryVersions.electronNodeVersion || 'not found'
41
51
  };
52
+ debug('combined versions %o', versions);
53
+ return versions;
42
54
  });
43
55
  };
44
56
 
@@ -219,15 +219,6 @@ const downloadAndUnzip = ({
219
219
  };
220
220
 
221
221
  const start = (options = {}) => {
222
- // handle deprecated / removed
223
- if (util.getEnv('CYPRESS_BINARY_VERSION')) {
224
- return throwFormErrorText(errors.removed.CYPRESS_BINARY_VERSION)();
225
- }
226
-
227
- if (util.getEnv('CYPRESS_SKIP_BINARY_INSTALL')) {
228
- return throwFormErrorText(errors.removed.CYPRESS_SKIP_BINARY_INSTALL)();
229
- }
230
-
231
222
  debug('installing with options %j', options);
232
223
 
233
224
  _.defaults(options, {
@@ -279,7 +270,7 @@ const start = (options = {}) => {
279
270
  ${err.message}
280
271
  `);
281
272
  }).then(() => {
282
- return Promise.all([state.getBinaryPkgVersionAsync(binaryDir), getVersionSpecifier()]);
273
+ return Promise.all([state.getBinaryPkgAsync(binaryDir).then(state.getBinaryPkgVersion), getVersionSpecifier()]);
283
274
  }).then(([binaryVersion, versionSpecifier]) => {
284
275
  if (!binaryUrlOverride && versionSpecifier) {
285
276
  const computedBinaryUrl = getBinaryUrlFromPrereleaseNpmUrl(versionSpecifier);
@@ -8,6 +8,8 @@ const path = require('path');
8
8
 
9
9
  const untildify = require('untildify');
10
10
 
11
+ const R = require('ramda');
12
+
11
13
  const debug = require('debug')('cypress:cli');
12
14
 
13
15
  const fs = require('../fs');
@@ -183,8 +185,13 @@ const writeBinaryVerifiedAsync = (verified, binaryDir) => {
183
185
  const getPathToExecutable = binaryDir => {
184
186
  return path.join(binaryDir, getPlatformExecutable());
185
187
  };
188
+ /**
189
+ * Resolves with an object read from the binary app package.json file.
190
+ * If the file does not exist resolves with null
191
+ */
192
+
186
193
 
187
- const getBinaryPkgVersionAsync = binaryDir => {
194
+ const getBinaryPkgAsync = binaryDir => {
188
195
  const pathToPackageJson = getBinaryPkgPath(binaryDir);
189
196
  debug('Reading binary package.json from:', pathToPackageJson);
190
197
  return fs.pathExistsAsync(pathToPackageJson).then(exists => {
@@ -192,15 +199,22 @@ const getBinaryPkgVersionAsync = binaryDir => {
192
199
  return null;
193
200
  }
194
201
 
195
- return fs.readJsonAsync(pathToPackageJson).get('version');
202
+ return fs.readJsonAsync(pathToPackageJson);
196
203
  });
197
204
  };
198
205
 
206
+ const getBinaryPkgVersion = R.propOr(null, 'version');
207
+ const getBinaryElectronVersion = R.propOr(null, 'electronVersion');
208
+ const getBinaryElectronNodeVersion = R.propOr(null, 'electronNodeVersion');
199
209
  module.exports = {
200
210
  getPathToExecutable,
201
211
  getPlatformExecutable,
202
- getBinaryPkgVersionAsync,
212
+ // those names start to sound like Java
213
+ getBinaryElectronNodeVersion,
214
+ getBinaryElectronVersion,
215
+ getBinaryPkgVersion,
203
216
  getBinaryVerifiedAsync,
217
+ getBinaryPkgAsync,
204
218
  getBinaryPkgPath,
205
219
  getBinaryDir,
206
220
  getCacheDir,
@@ -284,7 +284,9 @@ const start = (options = {}) => {
284
284
  }).tap(() => {
285
285
  return debug('binaryDir is ', binaryDir);
286
286
  }).then(() => {
287
- return state.getBinaryPkgVersionAsync(binaryDir);
287
+ return state.getBinaryPkgAsync(binaryDir);
288
+ }).then(pkg => {
289
+ return state.getBinaryPkgVersion(pkg);
288
290
  }).then(binaryVersion => {
289
291
  if (!binaryVersion) {
290
292
  debug('no Cypress binary found for cli version ', packageVersion);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress",
3
- "version": "5.6.0",
3
+ "version": "6.2.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "postinstall": "node index.js --exec install",
@@ -6,3 +6,24 @@ interface EventEmitter extends EventEmitter2 {
6
6
  emitMap: (eventName: string, args: any[]) => Array<(...args: any[]) => any>
7
7
  emitThen: (eventName: string, args: any[]) => Bluebird.BluebirdStatic
8
8
  }
9
+
10
+ // Copied from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/events.d.ts
11
+ // to avoid type conflict.
12
+ interface NodeEventEmitter {
13
+ addListener(event: string | symbol, listener: (...args: any[]) => void): this
14
+ on(event: string | symbol, listener: (...args: any[]) => void): this
15
+ once(event: string | symbol, listener: (...args: any[]) => void): this
16
+ removeListener(event: string | symbol, listener: (...args: any[]) => void): this
17
+ off(event: string | symbol, listener: (...args: any[]) => void): this
18
+ removeAllListeners(event?: string | symbol): this
19
+ setMaxListeners(n: number): this
20
+ getMaxListeners(): number
21
+ listeners(event: string | symbol): Array<(...args: any[]) => void>
22
+ rawListeners(event: string | symbol): Array<(...args: any[]) => void>
23
+ emit(event: string | symbol, ...args: any[]): boolean
24
+ listenerCount(type: string | symbol): number
25
+ // Added in Node 6...
26
+ prependListener(event: string | symbol, listener: (...args: any[]) => void): this
27
+ prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this
28
+ eventNames(): Array<string | symbol>
29
+ }
@@ -1,3 +1,5 @@
1
+ /// <reference path="./cypress-npm-api.d.ts" />
2
+
1
3
  declare namespace Cypress {
2
4
  type FileContents = string | any[] | object
3
5
  type HistoryDirection = 'back' | 'forward'
@@ -116,6 +118,17 @@ declare namespace Cypress {
116
118
  */
117
119
  type CypressSpecType = 'integration' | 'component'
118
120
 
121
+ /**
122
+ * A Cypress spec.
123
+ */
124
+ interface Spec {
125
+ name: string // "config_passing_spec.js"
126
+ relative: string // "cypress/integration/config_passing_spec.js" or "__all" if clicked all specs button
127
+ absolute: string // "/Users/janelane/app/cypress/integration/config_passing_spec.js"
128
+ specFilter?: string // optional spec filter used by the user
129
+ specType?: CypressSpecType
130
+ }
131
+
119
132
  /**
120
133
  * Window type for Application Under Test(AUT)
121
134
  */
@@ -164,6 +177,9 @@ declare namespace Cypress {
164
177
  */
165
178
  minimatch: typeof Minimatch.minimatch
166
179
  /**
180
+ * @deprecated Will be removed in a future version.
181
+ * Consider including your own datetime formatter in your tests.
182
+ *
167
183
  * Cypress automatically includes moment.js and exposes it as Cypress.moment.
168
184
  *
169
185
  * @see https://on.cypress.io/moment
@@ -224,23 +240,17 @@ declare namespace Cypress {
224
240
  /**
225
241
  * Currently executing spec file.
226
242
  * @example
227
- ```
228
- Cypress.spec
229
- // {
230
- // name: "config_passing_spec.coffee",
231
- // relative: "cypress/integration/config_passing_spec.coffee",
232
- // absolute: "/users/smith/projects/web/cypress/integration/config_passing_spec.coffee"
233
- // specType: "integration"
234
- // }
235
- ```
243
+ * ```
244
+ * Cypress.spec
245
+ * // {
246
+ * // name: "config_passing_spec.coffee",
247
+ * // relative: "cypress/integration/config_passing_spec.coffee",
248
+ * // absolute: "/users/smith/projects/web/cypress/integration/config_passing_spec.coffee"
249
+ * // specType: "integration"
250
+ * // }
251
+ * ```
236
252
  */
237
- spec: {
238
- name: string // "config_passing_spec.coffee"
239
- relative: string // "cypress/integration/config_passing_spec.coffee" or "__all" if clicked all specs button
240
- absolute: string
241
- specFilter?: string // optional spec filter used by the user
242
- specType?: CypressSpecType
243
- }
253
+ spec: Spec
244
254
 
245
255
  /**
246
256
  * Information about the browser currently running the tests
@@ -421,7 +431,7 @@ declare namespace Cypress {
421
431
  /**
422
432
  * Returns a boolean indicating whether an element is hidden.
423
433
  */
424
- isHidden(element: JQuery | HTMLElement): boolean
434
+ isHidden(element: JQuery | HTMLElement, methodName?: string, options?: object): boolean
425
435
  /**
426
436
  * Returns a boolean indicating whether an element can receive focus.
427
437
  */
@@ -474,7 +484,7 @@ declare namespace Cypress {
474
484
  getContainsSelector(text: string, filter?: string): JQuery.Selector
475
485
  getFirstDeepestElement(elements: HTMLElement[], index?: number): HTMLElement
476
486
  getWindowByElement(element: JQuery | HTMLElement): JQuery | HTMLElement
477
- getReasonIsHidden(element: JQuery | HTMLElement): string
487
+ getReasonIsHidden(element: JQuery | HTMLElement, options?: object): string
478
488
  getFirstScrollableParent(element: JQuery | HTMLElement): JQuery | HTMLElement
479
489
  getFirstFixedOrStickyPositionParent(element: JQuery | HTMLElement): JQuery | HTMLElement
480
490
  getFirstStickyPositionParent(element: JQuery | HTMLElement): JQuery | HTMLElement
@@ -1477,8 +1487,9 @@ declare namespace Cypress {
1477
1487
  root<E extends Node = HTMLHtmlElement>(options?: Partial<Loggable>): Chainable<JQuery<E>> // can't do better typing unless we ignore the `.within()` case
1478
1488
 
1479
1489
  /**
1480
- * Use `cy.route()` to manage the behavior of network requests.
1490
+ * @deprecated Use `cy.intercept()` instead.
1481
1491
  *
1492
+ * Use `cy.route()` to manage the behavior of network requests.
1482
1493
  * @see https://on.cypress.io/route
1483
1494
  * @example
1484
1495
  * cy.server()
@@ -1486,6 +1497,8 @@ declare namespace Cypress {
1486
1497
  */
1487
1498
  route(url: string | RegExp, response?: string | object): Chainable<null>
1488
1499
  /**
1500
+ * @deprecated Use `cy.intercept()` instead.
1501
+ *
1489
1502
  * Spy or stub request with specific method and url.
1490
1503
  *
1491
1504
  * @see https://on.cypress.io/route
@@ -1496,6 +1509,8 @@ declare namespace Cypress {
1496
1509
  */
1497
1510
  route(method: string, url: string | RegExp, response?: string | object): Chainable<null>
1498
1511
  /**
1512
+ * @deprecated Use `cy.intercept()` instead.
1513
+ *
1499
1514
  * Set a route by returning an object literal from a callback function.
1500
1515
  * Functions that return a Promise will automatically be awaited.
1501
1516
  *
@@ -1514,6 +1529,8 @@ declare namespace Cypress {
1514
1529
  */
1515
1530
  route(fn: () => RouteOptions): Chainable<null>
1516
1531
  /**
1532
+ * @deprecated Use `cy.intercept()` instead.
1533
+ *
1517
1534
  * Spy or stub a given route.
1518
1535
  *
1519
1536
  * @see https://on.cypress.io/route
@@ -1581,6 +1598,8 @@ declare namespace Cypress {
1581
1598
  select(value: string | string[], options?: Partial<SelectOptions>): Chainable<Subject>
1582
1599
 
1583
1600
  /**
1601
+ * @deprecated Use `cy.intercept()` instead.
1602
+ *
1584
1603
  * Start a server to begin routing responses to `cy.route()` and `cy.request()`.
1585
1604
  *
1586
1605
  * @example
@@ -2013,50 +2032,6 @@ declare namespace Cypress {
2013
2032
  * cy.wait(1000) // wait for 1 second
2014
2033
  */
2015
2034
  wait(ms: number, options?: Partial<Loggable & Timeoutable>): Chainable<Subject>
2016
- /**
2017
- * Wait for a specific XHR to respond.
2018
- *
2019
- * @see https://on.cypress.io/wait
2020
- * @param {string} alias - Name of the alias to wait for.
2021
- *
2022
- ```
2023
- // Wait for the route aliased as 'getAccount' to respond
2024
- // without changing or stubbing its response
2025
- cy.server()
2026
- cy.route('/accounts/*').as('getAccount')
2027
- cy.visit('/accounts/123')
2028
- cy.wait('@getAccount').then((xhr) => {
2029
- // we can now access the low level xhr
2030
- // that contains the request body,
2031
- // response body, status, etc
2032
- })
2033
- ```
2034
- */
2035
- wait(alias: string, options?: Partial<Loggable & Timeoutable & TimeoutableXHR>): Chainable<WaitXHR>
2036
- /**
2037
- * Wait for list of XHR requests to complete.
2038
- *
2039
- * @see https://on.cypress.io/wait
2040
- * @param {string[]} aliases - An array of aliased routes as defined using the `.as()` command.
2041
- *
2042
- ```
2043
- // wait for 3 XHR requests to complete
2044
- cy.server()
2045
- cy.route('users/*').as('getUsers')
2046
- cy.route('activities/*').as('getActivities')
2047
- cy.route('comments/*').as('getComments')
2048
- cy.visit('/dashboard')
2049
-
2050
- cy.wait(['@getUsers', '@getActivities', '@getComments'])
2051
- .then((xhrs) => {
2052
- // xhrs will now be an array of matching XHR's
2053
- // xhrs[0] <-- getUsers
2054
- // xhrs[1] <-- getActivities
2055
- // xhrs[2] <-- getComments
2056
- })
2057
- ```
2058
- */
2059
- wait(alias: string[], options?: Partial<Loggable & Timeoutable & TimeoutableXHR>): Chainable<WaitXHR[]>
2060
2035
 
2061
2036
  /**
2062
2037
  * Get the window object of the page that is currently active.
@@ -2322,20 +2297,46 @@ declare namespace Cypress {
2322
2297
  force: boolean
2323
2298
  }
2324
2299
 
2300
+ type scrollBehaviorOptions = false | 'center' | 'top' | 'bottom' | 'nearest'
2301
+
2302
+ /**
2303
+ * Options to affect Actionability checks
2304
+ * @see https://docs.cypress.io/guides/core-concepts/interacting-with-elements.html#Actionability
2305
+ */
2306
+ interface ActionableOptions extends Forceable {
2307
+ /**
2308
+ * Whether to wait for elements to finish animating before executing commands
2309
+ *
2310
+ * @default true
2311
+ */
2312
+ waitForAnimations: boolean
2313
+ /**
2314
+ * The distance in pixels an element must exceed over time to be considered animating
2315
+ * @default 5
2316
+ */
2317
+ animationDistanceThreshold: number
2318
+ /**
2319
+ * Viewport position to which an element should be scrolled prior to action commands. Setting `false` disables scrolling.
2320
+ *
2321
+ * @default 'top'
2322
+ */
2323
+ scrollBehavior: scrollBehaviorOptions
2324
+ }
2325
+
2325
2326
  interface BlurOptions extends Loggable, Forceable { }
2326
2327
 
2327
- interface CheckOptions extends Loggable, Timeoutable, Forceable {
2328
+ interface CheckOptions extends Loggable, Timeoutable, ActionableOptions {
2328
2329
  interval: number
2329
2330
  }
2330
2331
 
2331
- interface ClearOptions extends Loggable, Timeoutable, Forceable {
2332
+ interface ClearOptions extends Loggable, Timeoutable, ActionableOptions {
2332
2333
  interval: number
2333
2334
  }
2334
2335
 
2335
2336
  /**
2336
2337
  * Object to change the default behavior of .click().
2337
2338
  */
2338
- interface ClickOptions extends Loggable, Timeoutable, Forceable {
2339
+ interface ClickOptions extends Loggable, Timeoutable, ActionableOptions {
2339
2340
  /**
2340
2341
  * Serially click multiple elements
2341
2342
  *
@@ -2563,6 +2564,11 @@ declare namespace Cypress {
2563
2564
  * @default true
2564
2565
  */
2565
2566
  waitForAnimations: boolean
2567
+ /**
2568
+ * Viewport position to which an element should be scrolled prior to action commands. Setting `false` disables scrolling.
2569
+ * @default 'top'
2570
+ */
2571
+ scrollBehavior: scrollBehaviorOptions
2566
2572
  /**
2567
2573
  * Firefox version 79 and below only: The number of tests that will run between forced garbage collections.
2568
2574
  * If a number is supplied, it will apply to `run` mode and `open` mode.
@@ -2571,16 +2577,16 @@ declare namespace Cypress {
2571
2577
  */
2572
2578
  firefoxGcInterval: Nullable<number | { runMode: Nullable<number>, openMode: Nullable<number> }>
2573
2579
  /**
2574
- * Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement
2575
- * algorithm.
2580
+ * Allows listening to the `before:run`, `after:run`, `before:spec`, and `after:spec` events in the plugins file.
2576
2581
  * @default false
2577
2582
  */
2578
- experimentalSourceRewriting: boolean
2583
+ experimentalRunEvents: boolean
2579
2584
  /**
2580
- * Enables `cy.route2`, which can be used to dynamically intercept/stub/await any HTTP request or response (XHRs, fetch, beacons, etc.)
2585
+ * Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement
2586
+ * algorithm.
2581
2587
  * @default false
2582
2588
  */
2583
- experimentalNetworkStubbing: boolean
2589
+ experimentalSourceRewriting: boolean
2584
2590
  /**
2585
2591
  * Number of times to retry a failed test.
2586
2592
  * If a number is set, tests will retry in both runMode and openMode.
@@ -2598,7 +2604,7 @@ declare namespace Cypress {
2598
2604
  includeShadowDom: boolean
2599
2605
  }
2600
2606
 
2601
- interface TestConfigOverrides extends Partial<Pick<ConfigOptions, 'baseUrl' | 'defaultCommandTimeout' | 'taskTimeout' | 'animationDistanceThreshold' | 'waitForAnimations' | 'viewportHeight' | 'viewportWidth' | 'requestTimeout' | 'execTimeout' | 'env' | 'responseTimeout' | 'retries' | 'includeShadowDom'>> {
2607
+ interface TestConfigOverrides extends Partial<Pick<ConfigOptions, 'animationDistanceThreshold' | 'baseUrl' | 'defaultCommandTimeout' | 'env' | 'execTimeout' | 'includeShadowDom' | 'requestTimeout' | 'responseTimeout' | 'retries' | 'scrollBehavior' | 'taskTimeout' | 'viewportHeight' | 'viewportWidth' | 'waitForAnimations'>> {
2602
2608
  browser?: IsBrowserMatcher | IsBrowserMatcher[]
2603
2609
  }
2604
2610
 
@@ -2794,7 +2800,7 @@ declare namespace Cypress {
2794
2800
  *
2795
2801
  * @see https://on.cypress.io/type
2796
2802
  */
2797
- interface TypeOptions extends Loggable, Timeoutable {
2803
+ interface TypeOptions extends Loggable, Timeoutable, ActionableOptions {
2798
2804
  /**
2799
2805
  * Delay after each keypress (ms)
2800
2806
  *
@@ -2808,12 +2814,6 @@ declare namespace Cypress {
2808
2814
  * @default true
2809
2815
  */
2810
2816
  parseSpecialCharSequences: boolean
2811
- /**
2812
- * Forces the action, disables waiting for actionability
2813
- *
2814
- * @default false
2815
- */
2816
- force: boolean
2817
2817
  /**
2818
2818
  * Keep a modifier activated between commands
2819
2819
  *
@@ -2906,7 +2906,7 @@ declare namespace Cypress {
2906
2906
  /**
2907
2907
  * Options to change the default behavior of .trigger()
2908
2908
  */
2909
- interface TriggerOptions extends Loggable, Timeoutable, Forceable {
2909
+ interface TriggerOptions extends Loggable, Timeoutable, ActionableOptions {
2910
2910
  /**
2911
2911
  * Whether the event bubbles
2912
2912
  *
@@ -4982,7 +4982,7 @@ declare namespace Cypress {
4982
4982
  dimensions?: Dimensions
4983
4983
  }
4984
4984
 
4985
- interface FileObject {
4985
+ interface FileObject extends NodeEventEmitter {
4986
4986
  filePath: string
4987
4987
  outputPath: string
4988
4988
  shouldWatch: boolean
@@ -4999,9 +4999,31 @@ declare namespace Cypress {
4999
4999
  [key: string]: Task
5000
5000
  }
5001
5001
 
5002
+ interface SystemDetails {
5003
+ osName: string
5004
+ osVersion: string
5005
+ }
5006
+
5007
+ interface BeforeRunDetails {
5008
+ browser: Browser
5009
+ config: ConfigOptions
5010
+ cypressVersion: string
5011
+ group?: string
5012
+ parallel: boolean
5013
+ runUrl?: string
5014
+ specs: Spec[]
5015
+ specPattern: string[]
5016
+ system: SystemDetails
5017
+ tag?: string
5018
+ }
5019
+
5002
5020
  interface PluginEvents {
5003
- (action: 'before:browser:launch', fn: (browser: Browser, browserLaunchOptions: BrowserLaunchOptions) => void | BrowserLaunchOptions | Promise<BrowserLaunchOptions>): void
5021
+ (action: 'after:run', fn: (results: CypressCommandLine.CypressRunResult | CypressCommandLine.CypressFailedRunResult) => void | Promise<void>): void
5004
5022
  (action: 'after:screenshot', fn: (details: ScreenshotDetails) => void | AfterScreenshotReturnObject | Promise<AfterScreenshotReturnObject>): void
5023
+ (action: 'after:spec', fn: (spec: Spec, results: CypressCommandLine.RunResult) => void | Promise<void>): void
5024
+ (action: 'before:run', fn: (runDetails: BeforeRunDetails) => void | Promise<void>): void
5025
+ (action: 'before:spec', fn: (spec: Spec) => void | Promise<void>): void
5026
+ (action: 'before:browser:launch', fn: (browser: Browser, browserLaunchOptions: BrowserLaunchOptions) => void | BrowserLaunchOptions | Promise<BrowserLaunchOptions>): void
5005
5027
  (action: 'file:preprocessor', fn: (file: FileObject) => string | Promise<string>): void
5006
5028
  (action: 'task', tasks: Tasks): void
5007
5029
  }
@@ -5255,7 +5277,8 @@ declare namespace Cypress {
5255
5277
  duration: number
5256
5278
  headers: { [key: string]: string }
5257
5279
  isOkStatusCode: boolean
5258
- redirectedToUrl: string
5280
+ redirects?: string[]
5281
+ redirectedToUrl?: string
5259
5282
  requestHeaders: { [key: string]: string }
5260
5283
  status: number
5261
5284
  statusText: string
@@ -70,7 +70,7 @@ type Method =
70
70
  | 'unsubscribe'
71
71
 
72
72
  export namespace CyHttpMessages {
73
- interface BaseMessage {
73
+ export interface BaseMessage {
74
74
  body?: any
75
75
  headers: { [key: string]: string }
76
76
  url: string
@@ -178,8 +178,9 @@ export type NumberMatcher = number | number[]
178
178
  /**
179
179
  * Request/response cycle.
180
180
  */
181
- export interface Request {
181
+ export interface Interception {
182
182
  id: string
183
+ routeHandlerId: string
183
184
  /* @internal */
184
185
  log: any
185
186
  request: CyHttpMessages.IncomingRequest
@@ -191,16 +192,20 @@ export interface Request {
191
192
  response?: CyHttpMessages.IncomingResponse
192
193
  /* @internal */
193
194
  responseHandler?: HttpResponseInterceptor
195
+ /**
196
+ * The error that occurred during this request.
197
+ */
198
+ error?: Error
194
199
  /**
195
200
  * Was `cy.wait()` used to wait on the response to this request?
196
201
  * @internal
197
202
  */
198
203
  responseWaited: boolean
199
204
  /* @internal */
200
- state: RequestState
205
+ state: InterceptionState
201
206
  }
202
207
 
203
- export type RequestState =
208
+ export type InterceptionState =
204
209
  'Received' |
205
210
  'Intercepted' |
206
211
  'ResponseReceived' |
@@ -214,7 +219,8 @@ export interface Route {
214
219
  options: RouteMatcherOptions
215
220
  handler: RouteHandler
216
221
  hitCount: number
217
- requests: { [key: string]: Request }
222
+ requests: { [key: string]: Interception }
223
+ command: any
218
224
  }
219
225
 
220
226
  export interface RouteMap { [key: string]: Route }
@@ -224,13 +230,9 @@ export interface RouteMap { [key: string]: Route }
224
230
  */
225
231
  export type RouteMatcher = StringMatcher | RouteMatcherOptions
226
232
 
227
- export interface RouteMatcherCompatOptions {
228
- response?: string | object
229
- }
230
-
231
233
  export type RouteMatcherOptions = RouteMatcherOptionsGeneric<StringMatcher>
232
234
 
233
- export interface RouteMatcherOptionsGeneric<S> extends RouteMatcherCompatOptions {
235
+ export interface RouteMatcherOptionsGeneric<S> {
234
236
  /**
235
237
  * Match against the username and password used in HTTP Basic authentication.
236
238
  */
@@ -248,6 +250,11 @@ export interface RouteMatcherOptionsGeneric<S> extends RouteMatcherCompatOptions
248
250
  * If 'false', only HTTP requests will be matched.
249
251
  */
250
252
  https?: boolean
253
+ /**
254
+ * If `true`, will match the supplied `url` against incoming `path`s.
255
+ * Requires a `url` argument. Cannot be used with a `path` argument.
256
+ */
257
+ matchUrlAgainstPath?: boolean
251
258
  /**
252
259
  * Match against the request's HTTP method.
253
260
  * @default '*'
@@ -328,41 +335,112 @@ export interface GenericStaticResponse<Fixture, Body> {
328
335
  */
329
336
  export type StringMatcher = GlobPattern | RegExp
330
337
 
338
+ interface WaitOptions {
339
+ /**
340
+ * Displays the command in the Command Log
341
+ *
342
+ * @default true
343
+ */
344
+ log: boolean
345
+ /**
346
+ * Time to wait for the request (ms)
347
+ *
348
+ * @default {@link Timeoutable#timeout}
349
+ * @see https://on.cypress.io/configuration#Timeouts
350
+ */
351
+ requestTimeout: number
352
+ /**
353
+ * Time to wait for the response (ms)
354
+ *
355
+ * @default {@link Timeoutable#timeout}
356
+ * @see https://on.cypress.io/configuration#Timeouts
357
+ */
358
+ responseTimeout: number
359
+ /**
360
+ * Time to wait (ms)
361
+ *
362
+ * @default defaultCommandTimeout
363
+ * @see https://on.cypress.io/configuration#Timeouts
364
+ */
365
+ timeout: number
366
+ }
367
+
331
368
  declare global {
332
369
  namespace Cypress {
333
370
  interface Chainable<Subject = any> {
334
371
  /**
335
- * Use `cy.route2()` to stub and intercept HTTP requests and responses.
372
+ * Use `cy.intercept()` to stub and intercept HTTP requests and responses.
336
373
  *
337
- * Note: this command is only available if you have set the `experimentalNetworkStubbing`
338
- * configuration option to `true`.
339
- *
340
- * @see https://on.cypress.io/route2
374
+ * @see https://on.cypress.io/intercept
341
375
  * @example
342
- * cy.route2('https://localhost:7777/users', [{id: 1, name: 'Pat'}])
376
+ * cy.intercept('https://localhost:7777/users', [{id: 1, name: 'Pat'}])
343
377
  * @example
344
- * cy.route2('https://localhost:7777/protected-endpoint', (req) => {
378
+ * cy.intercept('https://localhost:7777/protected-endpoint', (req) => {
345
379
  * req.headers['authorization'] = 'basic fooabc123'
346
380
  * })
347
381
  * @example
348
- * cy.route2('https://localhost:7777/some-response', (req) => {
382
+ * cy.intercept('https://localhost:7777/some-response', (req) => {
349
383
  * req.reply(res => {
350
384
  * res.body = 'some new body'
351
385
  * })
352
386
  * })
353
387
  */
354
- route2(url: RouteMatcher, response?: RouteHandler): Chainable<null>
388
+ intercept(url: RouteMatcher, response?: RouteHandler): Chainable<null>
355
389
  /**
356
- * Use `cy.route2()` to stub and intercept HTTP requests and responses.
390
+ * Use `cy.intercept()` to stub and intercept HTTP requests and responses.
357
391
  *
358
- * Note: this command is only available if you have set the `experimentalNetworkStubbing`
359
- * configuration option to `true`.
360
- *
361
- * @see https://on.cypress.io/route2
392
+ * @see https://on.cypress.io/intercept
362
393
  * @example
363
- * cy.route2('GET', 'http://foo.com/fruits', ['apple', 'banana', 'cherry'])
394
+ * cy.intercept('GET', 'http://foo.com/fruits', ['apple', 'banana', 'cherry'])
395
+ */
396
+ intercept(method: Method, url: RouteMatcher, response?: RouteHandler): Chainable<null>
397
+ /**
398
+ * @deprecated Use `cy.intercept()` instead.
399
+ */
400
+ route2(url: RouteMatcher, response?: RouteHandler): Chainable<null>
401
+ /**
402
+ * @deprecated Use `cy.intercept()` instead.
364
403
  */
365
404
  route2(method: Method, url: RouteMatcher, response?: RouteHandler): Chainable<null>
405
+ /**
406
+ * Wait for a specific request to complete.
407
+ *
408
+ * @see https://on.cypress.io/wait
409
+ * @param {string} alias - Name of the alias to wait for.
410
+ *
411
+ ```
412
+ // Wait for the route aliased as 'getAccount' to respond
413
+ // without changing or stubbing its response
414
+ cy.intercept('https://api.example.com/accounts/*').as('getAccount')
415
+ cy.visit('/accounts/123')
416
+ cy.wait('@getAccount').then((interception) => {
417
+ // we can now access the low level request
418
+ // that contains the request body,
419
+ // response body, status, etc
420
+ })
421
+ ```
422
+ */
423
+ wait(alias: string, options?: Partial<WaitOptions>): Chainable<Interception>
424
+ /**
425
+ * Wait for list of requests to complete.
426
+ *
427
+ * @see https://on.cypress.io/wait
428
+ * @param {string[]} aliases - An array of aliased routes as defined using the `.as()` command.
429
+ *
430
+ ```
431
+ // wait for 3 XHR requests to complete
432
+ cy.intercept('users/*').as('getUsers')
433
+ cy.intercept('activities/*').as('getActivities')
434
+ cy.intercept('comments/*').as('getComments')
435
+ cy.visit('/dashboard')
436
+
437
+ cy.wait(['@getUsers', '@getActivities', '@getComments'])
438
+ .then((interceptions) => {
439
+ // intercepts will now be an array of matching HTTP requests
440
+ })
441
+ ```
442
+ */
443
+ wait(alias: string[], options?: Partial<WaitOptions>): Chainable<Interception[]>
366
444
  }
367
445
  }
368
446
  }