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 +1 -1
- package/lib/cli.js +55 -5
- package/lib/errors.js +0 -19
- package/lib/exec/run.js +2 -9
- package/lib/exec/versions.js +15 -3
- package/lib/tasks/install.js +1 -10
- package/lib/tasks/state.js +17 -3
- package/lib/tasks/verify.js +3 -1
- package/package.json +1 -1
- package/types/cypress-eventemitter.d.ts +21 -0
- package/types/cypress.d.ts +106 -83
- package/types/net-stubbing.ts +103 -25
package/README.md
CHANGED
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
|
-
|
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(
|
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')
|
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
|
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
|
|
package/lib/exec/versions.js
CHANGED
@@ -34,11 +34,23 @@ const getVersions = () => {
|
|
34
34
|
}
|
35
35
|
|
36
36
|
return state.getBinaryDir();
|
37
|
-
}).then(state.
|
38
|
-
|
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:
|
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
|
|
package/lib/tasks/install.js
CHANGED
@@ -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.
|
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);
|
package/lib/tasks/state.js
CHANGED
@@ -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
|
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)
|
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
|
-
|
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,
|
package/lib/tasks/verify.js
CHANGED
@@ -284,7 +284,9 @@ const start = (options = {}) => {
|
|
284
284
|
}).tap(() => {
|
285
285
|
return debug('binaryDir is ', binaryDir);
|
286
286
|
}).then(() => {
|
287
|
-
return state.
|
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
@@ -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
|
+
}
|
package/types/cypress.d.ts
CHANGED
@@ -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
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
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.
|
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,
|
2328
|
+
interface CheckOptions extends Loggable, Timeoutable, ActionableOptions {
|
2328
2329
|
interval: number
|
2329
2330
|
}
|
2330
2331
|
|
2331
|
-
interface ClearOptions extends Loggable, Timeoutable,
|
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,
|
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
|
-
*
|
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
|
-
|
2583
|
+
experimentalRunEvents: boolean
|
2579
2584
|
/**
|
2580
|
-
* Enables
|
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
|
-
|
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' | '
|
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,
|
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: '
|
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
|
-
|
5280
|
+
redirects?: string[]
|
5281
|
+
redirectedToUrl?: string
|
5259
5282
|
requestHeaders: { [key: string]: string }
|
5260
5283
|
status: number
|
5261
5284
|
statusText: string
|
package/types/net-stubbing.ts
CHANGED
@@ -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
|
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:
|
205
|
+
state: InterceptionState
|
201
206
|
}
|
202
207
|
|
203
|
-
export type
|
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]:
|
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>
|
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.
|
372
|
+
* Use `cy.intercept()` to stub and intercept HTTP requests and responses.
|
336
373
|
*
|
337
|
-
*
|
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.
|
376
|
+
* cy.intercept('https://localhost:7777/users', [{id: 1, name: 'Pat'}])
|
343
377
|
* @example
|
344
|
-
* cy.
|
378
|
+
* cy.intercept('https://localhost:7777/protected-endpoint', (req) => {
|
345
379
|
* req.headers['authorization'] = 'basic fooabc123'
|
346
380
|
* })
|
347
381
|
* @example
|
348
|
-
* cy.
|
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
|
-
|
388
|
+
intercept(url: RouteMatcher, response?: RouteHandler): Chainable<null>
|
355
389
|
/**
|
356
|
-
* Use `cy.
|
390
|
+
* Use `cy.intercept()` to stub and intercept HTTP requests and responses.
|
357
391
|
*
|
358
|
-
*
|
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.
|
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
|
}
|