fix: add more validation to cy.intercept() (#16577)

Co-authored-by: Zach Bloomquist <github@chary.us>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
This commit is contained in:
Zach Bloomquist
2021-05-24 13:41:34 -04:00
committed by GitHub
parent 55a4e7a835
commit 3c33db5ab0
6 changed files with 91 additions and 8 deletions

View File

@@ -1195,6 +1195,7 @@ jobs:
desktop-gui-component-tests:
<<: *defaults
resource_class: medium
parallelism: 1
steps:
- restore_cached_workspace

View File

@@ -680,6 +680,38 @@ describe('network stubbing', { retries: { runMode: 2, openMode: 0 } }, function
cy.intercept('/foo', { middleware: true })
})
context('with an unexpected number of arguments', function () {
it('cy.intercept(url, handler?)', function (done) {
testFail((err) => {
expect(err.message).to.include('The `cy.intercept(url, handler?)` signature accepts a maximum of 2 arguments, but 3 arguments were passed.')
done()
})
// @ts-ignore
cy.intercept('/url', { forceNetworkError: true }, () => {})
})
it('cy.intercept(url, mergeRouteMatcher, handler)', function (done) {
testFail((err) => {
expect(err.message).to.include('The `cy.intercept(url, mergeRouteMatcher, handler)` signature accepts a maximum of 3 arguments, but 4 arguments were passed.')
done()
})
// @ts-ignore
cy.intercept('/url', { middleware: true }, { forceNetworkError: true }, () => {})
})
it('cy.intercept(method, url, handler?)', function (done) {
testFail((err) => {
expect(err.message).to.include('The `cy.intercept(method, url, handler?)` signature accepts a maximum of 3 arguments, but 4 arguments were passed.')
done()
})
// @ts-ignore
cy.intercept('POST', '/url', { forceNetworkError: true }, () => {})
})
})
context('with invalid RouteMatcher', function () {
it('requires unique header names', function (done) {
testFail((err) => {
@@ -737,7 +769,7 @@ describe('network stubbing', { retries: { runMode: 2, openMode: 0 } }, function
})
it('times must be a positive integer', function (done) {
cy.on('fail', function (err) {
testFail((err) => {
expect(err.message).to.include('`times` must be a positive integer.')
done()
})
@@ -745,6 +777,15 @@ describe('network stubbing', { retries: { runMode: 2, openMode: 0 } }, function
cy
.intercept({ times: 9.75 })
})
it('string hostname must be a valid domain name', function (done) {
testFail((err) => {
expect(err.message).to.include('`hostname` must be a valid host name or domain name.')
done()
})
cy.intercept({ hostname: 'http://website.web' })
})
})
context('with invalid handler', function () {

View File

@@ -47,6 +47,7 @@
"errorhandler": "1.5.1",
"eventemitter2": "6.4.2",
"express": "4.17.1",
"is-valid-domain": "0.0.19",
"jquery": "3.1.1",
"jquery.scrollto": "2.1.3",
"js-cookie": "2.2.1",

View File

@@ -26,6 +26,7 @@ import {
import { registerEvents } from './events'
import $errUtils from '../../cypress/error_utils'
import $utils from '../../cypress/utils'
import isValidDomain from 'is-valid-domain'
const lowercaseFieldNames = (headers: { [fieldName: string]: any }) => _.mapKeys(headers, (v, k) => _.toLower(k))
@@ -129,6 +130,10 @@ function validateRouteMatcherOptions (routeMatcher: RouteMatcherOptions): { isVa
}
}
if (_.isString(routeMatcher.hostname) && !isValidDomain(routeMatcher.hostname, { allowUnicode: true })) {
return err('`hostname` must be a valid host name or domain name.')
}
if (_.has(routeMatcher, 'port') && !isNumberMatcher(routeMatcher.port)) {
return err('`port` must be a number or a list of numbers.')
}
@@ -234,6 +239,17 @@ export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy,
}
function intercept (matcher: RouteMatcher, handler?: RouteHandler | StringMatcher | RouteMatcherOptions, arg2?: RouteHandler) {
const checkExtraArguments = (overload: string[]) => {
if (arguments.length > overload.length) {
$errUtils.throwErrByPath('net_stubbing.intercept.extra_arguments', {
args: {
overload,
argsLength: arguments.length,
},
})
}
}
function getMatcherOptions (): RouteMatcherOptions {
if (isStringMatcher(matcher) && hasOnlyRouteMatcherKeys(handler)) {
// url, mergeRouteMatcher, handler
@@ -246,6 +262,8 @@ export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy,
return $errUtils.throwErrByPath('net_stubbing.intercept.handler_required')
}
checkExtraArguments(['url', 'mergeRouteMatcher', 'handler'])
const opts = {
url: matcher,
...handler as RouteMatcherOptions,
@@ -262,6 +280,8 @@ export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy,
handler = arg2
checkExtraArguments(['method', 'url', 'handler?'])
return {
method: matcher,
url,
@@ -270,6 +290,8 @@ export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy,
if (isStringMatcher(matcher)) {
// url, handler?
checkExtraArguments(['url', 'handler?'])
return {
url: matcher,
}

View File

@@ -931,23 +931,29 @@ module.exports = {
You passed: ${format(staticResponse)}`, 8)
},
intercept: {
extra_arguments: ({ argsLength, overload }) => {
return cyStripIndent(`\
The ${cmd('intercept', overload.join(', '))} signature accepts a maximum of ${overload.length} arguments, but ${argsLength} arguments were passed.
Please refer to the docs for all accepted signatures for ${cmd('intercept')}.`, 10)
},
invalid_handler: ({ handler }) => {
return stripIndent`\
return cyStripIndent(`\
${cmd('intercept')}'s \`handler\` argument must be a String, StaticResponse, or HttpController function.
You passed: ${format(handler)}`
You passed: ${format(handler)}`, 10)
},
invalid_middleware_handler: ({ handler }) => {
return stripIndent`\
return cyStripIndent(`\
${cmd('intercept')}'s \`handler\` argument must be an HttpController function when \`middleware\` is set to \`true\`.
You passed: ${format(handler)}`
You passed: ${format(handler)}`, 10)
},
invalid_route_matcher: ({ message, matcher }) => {
return stripIndent`\
return cyStripIndent(`\
An invalid RouteMatcher was supplied to ${cmd('intercept')}. ${message}
You passed: ${format(matcher)}`
You passed: ${format(matcher)}`, 10)
},
no_duplicate_url: `When invoking ${cmd('intercept')} with a \`RouteMatcher\` as the second parameter, \`url\` can only be specified as the first parameter.`,
handler_required: `When invoking ${cmd('intercept')} with a \`RouteMatcher\` as the second parameter, a handler (function or \`StaticResponse\`) must be specified as the third parameter. If you intended to stub out a response body by passing an object as the 2nd parameter, pass an object with a \`body\` property containing the desired response body instead.`,

View File

@@ -22873,6 +22873,13 @@ is-utf8@^0.2.0, is-utf8@^0.2.1:
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
is-valid-domain@0.0.19:
version "0.0.19"
resolved "https://registry.npmjs.org/is-valid-domain/-/is-valid-domain-0.0.19.tgz#50ce5ff3ab1cbe85bcb5b155b0fba61f4b9ea668"
integrity sha512-NxuZbJABXdGlFNEVphG9bT0YOQE0B75Bv+emGsEjmRnAs9aMUVbdKUafj//yTxApThjqQqRKBd9MJDlnqx8Pmg==
dependencies:
punycode "^1.4.1"
is-valid-glob@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe"
@@ -31369,11 +31376,16 @@ pumpify@1.5.1, pumpify@^1.3.3, pumpify@^1.3.5:
inherits "^2.0.3"
pump "^2.0.0"
punycode@1.3.2, punycode@^1.2.4, punycode@^1.3.2:
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"