Rename uses of term 'whitelist' (#7782)

* Rename non-user facing instances of whitelist

* Rename server option 'whitelist' to 'ignore'

* Update use of whitelist with server to throw instead of warn

* Rename Cypress.Cookies.defaults 'whitelist' option to 'preserve'

* fix circle yml parameter parsing consistent

* compose cloning an external repo and switching to the NEXT_DEV_VERSION branch consistently

* add cypress org to repo parameter

* cd into the right dir before switching branches

* one line git checkout

* simplify passing repo

* cd into the right dir

* clone into the right dir

* oh my cd 101

* replace kitchen sink strings for 5.0.0

Co-authored-by: Brian Mann <brian.mann86@gmail.com>
This commit is contained in:
Jennifer Shehane
2020-06-30 12:57:29 +06:30
committed by GitHub
parent e767bcfe4b
commit 639df99036
28 changed files with 306 additions and 356 deletions
+71 -67
View File
@@ -77,14 +77,14 @@ commands:
- run:
name: Install latest Google Chrome (stable)
command: |
if [ << parameters.browser >> == "chrome" ]; then
if [ <<parameters.browser>> == "chrome" ]; then
echo "**** Running Chrome tests. Installing latest stable version of Google Chrome. ****"
apt-get update
apt-get install google-chrome-stable -y
echo "**** Location of Google Chrome Installation: "`which google-chrome`" ****"
echo "**** Google Chrome Version: "`google-chrome --version`" ****"
else
echo "**** Not updating Chrome. Running tests in '<< parameters.browser >>' ****"
echo "**** Not updating Chrome. Running tests in '<<parameters.browser>>' ****"
fi
run-driver-integration-tests:
@@ -105,7 +105,7 @@ commands:
if [[ -v PACKAGES_RECORD_KEY ]]; then
# internal PR
CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
yarn cypress:run --record --parallel --group 5x-driver-<< parameters.browser >> --browser << parameters.browser >>
yarn cypress:run --record --parallel --group 5x-driver-<<parameters.browser>> --browser <<parameters.browser>>
else
# external PR
TESTFILES=$(circleci tests glob "cypress/integration/**/*_spec.*" | circleci tests split --total=$CIRCLE_NODE_TOTAL)
@@ -114,7 +114,7 @@ commands:
if [[ -z "$TESTFILES" ]]; then
echo "Empty list of test files"
fi
yarn cypress:run --browser << parameters.browser >> --spec $TESTFILES
yarn cypress:run --browser <<parameters.browser>> --spec $TESTFILES
fi
working_directory: packages/driver
- verify-mocha-results
@@ -136,7 +136,7 @@ commands:
command: |
CYPRESS_KONFIG_ENV=production \
CYPRESS_RECORD_KEY=$PACKAGES_RECORD_KEY \
yarn workspace @packages/runner cypress:run --record --parallel --group runner-integration-<< parameters.browser >> --browser <<parameters.browser>>
yarn workspace @packages/runner cypress:run --record --parallel --group runner-integration-<<parameters.browser>> --browser <<parameters.browser>>
- store_test_results:
path: /tmp/cypress
- store_artifacts:
@@ -156,7 +156,7 @@ commands:
- attach_workspace:
at: ~/
- run:
command: yarn workspace @packages/server test ./test/e2e/<< parameters.chunk >>*spec* --browser << parameters.browser >>
command: yarn workspace @packages/server test ./test/e2e/<<parameters.chunk>>*spec* --browser <<parameters.browser>>
- verify-mocha-results
- store_test_results:
path: /tmp/cypress
@@ -194,15 +194,30 @@ commands:
## by default, assert that at least 1 test ran
default: 0
steps:
- run: yarn verify:mocha:results << parameters.expectedResultCount >>
- run: yarn verify:mocha:results <<parameters.expectedResultCount>>
clone-repo-and-checkout-release-branch:
description: |
Clones an external repo and then checks out the branch that matches NEXT_DEV_VERSION otherwise uses 'master' branch.
parameters:
repo:
description: "Name of the github repo to clone like: cypress-example-kitchensink"
type: string
steps:
- attach_workspace:
at: ~/
- run:
name: "Cloning test project: <<parameters.repo>>"
command: |
git clone --depth 1 --no-single-branch https://github.com/cypress-io/<<parameters.repo>>.git /tmp/<<parameters.repo>>
cd /tmp/<<parameters.repo>> && (git checkout $NEXT_DEV_VERSION || true)
test-binary-against-repo:
description: |
Takes the built binary and NPM package, clones given example repo
and runs the new version of Cypress against it.
parameters:
repo:
description: Name of the repo like "cypress-example-kitchensink"
description: "Name of the github repo to clone like: cypress-example-kitchensink"
type: string
browser:
description: Name of the browser to use, like "electron", "chrome", "firefox"
@@ -232,18 +247,17 @@ commands:
# make sure the binary and NPM package files are present
- run: ls -l
- run: ls -l cypress.zip cypress.tgz
- run:
name: Cloning project <<parameters.repo>>
command: git clone --depth 1 https://github.com/cypress-io/<<parameters.repo>>.git /tmp/<<parameters.repo>>
- clone-repo-and-checkout-release-branch:
repo: <<parameters.repo>>
- when:
condition: << parameters.pull_request_id >>
condition: <<parameters.pull_request_id>>
steps:
- run:
name: Check out PR << parameters.pull_request_id >>
name: Check out PR <<parameters.pull_request_id>>
working_directory: /tmp/<<parameters.repo>>
command: |
git fetch origin pull/<< parameters.pull_request_id >>/head:pr-<< parameters.pull_request_id >>
git checkout pr-<< parameters.pull_request_id >>
git fetch origin pull/<<parameters.pull_request_id>>/head:pr-<<parameters.pull_request_id>>
git checkout pr-<<parameters.pull_request_id>>
git log -n 2
- run:
command: npm install
@@ -266,42 +280,42 @@ commands:
command: npm start --if-present
background: true
- when:
condition: << parameters.folder >>
condition: <<parameters.folder>>
steps:
- when:
condition: << parameters.browser >>
condition: <<parameters.browser>>
steps:
- run:
name: Run tests using browser "<< parameters.browser >>"
working_directory: /tmp/<<parameters.repo>>/<< parameters.folder >>
name: Run tests using browser "<<parameters.browser>>"
working_directory: /tmp/<<parameters.repo>>/<<parameters.folder>>
command: |
<<parameters.command>> -- --browser <<parameters.browser>>
- unless:
condition: << parameters.browser >>
condition: <<parameters.browser>>
steps:
- run:
name: Run tests using command
working_directory: /tmp/<<parameters.repo>>/<< parameters.folder >>
working_directory: /tmp/<<parameters.repo>>/<<parameters.folder>>
command: <<parameters.command>>
- store_artifacts:
name: screenshots
path: /tmp/<<parameters.repo>>/<< parameters.folder >>/cypress/screenshots
path: /tmp/<<parameters.repo>>/<<parameters.folder>>/cypress/screenshots
- store_artifacts:
name: videos
path: /tmp/<<parameters.repo>>/<< parameters.folder >>/cypress/videos
path: /tmp/<<parameters.repo>>/<<parameters.folder>>/cypress/videos
- unless:
condition: << parameters.folder >>
condition: <<parameters.folder>>
steps:
- when:
condition: << parameters.browser >>
condition: <<parameters.browser>>
steps:
- run:
name: Run tests using browser "<< parameters.browser >>"
name: Run tests using browser "<<parameters.browser>>"
working_directory: /tmp/<<parameters.repo>>
command: <<parameters.command>> -- --browser <<parameters.browser>>
- unless:
condition: << parameters.browser >>
condition: <<parameters.browser>>
steps:
- run:
name: Run tests using command
@@ -904,45 +918,39 @@ jobs:
test-kitchensink:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Cloning test project
command: git clone https://github.com/cypress-io/cypress-example-kitchensink.git /tmp/repo
- clone-repo-and-checkout-release-branch:
repo: cypress-example-kitchensink
- run:
name: Install prod dependencies
command: yarn --production
working_directory: /tmp/repo
working_directory: /tmp/cypress-example-kitchensink
- run:
name: Example server
command: yarn start
working_directory: /tmp/repo
working_directory: /tmp/cypress-example-kitchensink
background: true
- run:
name: Run Kitchensink example project
command: yarn cypress:run --project /tmp/repo
command: yarn cypress:run --project /tmp/cypress-example-kitchensink
- store_artifacts:
path: /tmp/repo/cypress/screenshots
path: /tmp/cypress-example-kitchensink/cypress/screenshots
- store_artifacts:
path: /tmp/repo/cypress/videos
path: /tmp/cypress-example-kitchensink/cypress/videos
- store-npm-logs
"test-kitchensink-against-staging":
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Cloning test project
command: git clone https://github.com/cypress-io/cypress-example-kitchensink.git /tmp/repo
- clone-repo-and-checkout-release-branch:
repo: cypress-example-kitchensink
- run:
name: Install prod dependencies
command: yarn --production
working_directory: /tmp/repo
working_directory: /tmp/cypress-example-kitchensink
- run:
name: Example server
command: yarn start
working_directory: /tmp/repo
working_directory: /tmp/cypress-example-kitchensink
background: true
- run:
name: Run Kitchensink example project
@@ -951,24 +959,21 @@ jobs:
CYPRESS_RECORD_KEY=$TEST_KITCHENSINK_RECORD_KEY \
CYPRESS_INTERNAL_ENV=staging \
CYPRESS_video=false \
yarn cypress:run --project /tmp/repo --record
yarn cypress:run --project /tmp/cypress-example-kitchensink --record
- store-npm-logs
"test-against-staging":
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Cloning test project
command: git clone https://github.com/cypress-io/cypress-test-tiny.git /tmp/repo
- clone-repo-and-checkout-release-branch:
repo: cypress-test-tiny
- run:
name: Run test project
command: |
CYPRESS_PROJECT_ID=$TEST_TINY_PROJECT_ID \
CYPRESS_RECORD_KEY=$TEST_TINY_RECORD_KEY \
CYPRESS_INTERNAL_ENV=staging \
yarn cypress:run --project /tmp/repo --record
yarn cypress:run --project /tmp/cypress-example-kitchensink --record
- store-npm-logs
build-npm-package:
@@ -1164,16 +1169,16 @@ jobs:
# make sure we have cypress.zip received
- run: ls -l
- run: ls -l cypress.zip cypress.tgz
- run: mkdir << parameters.wd >>
- run: mkdir <<parameters.wd>>
- run: node --version
- run: npm --version
- run:
name: Create new NPM package ⚗️
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
command: npm init -y
- run:
name: Install dependencies 📦
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
environment:
CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
# let's install Cypress, Jest and any other package that might conflict
@@ -1183,7 +1188,7 @@ jobs:
typescript jest @types/jest enzyme @types/enzyme
- run:
name: Test types clash ⚔️
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
command: |
echo "console.log('hello world')" > hello.ts
npx tsc hello.ts --noEmit
@@ -1207,16 +1212,16 @@ jobs:
# make sure we have cypress.zip received
- run: ls -l
- run: ls -l cypress.zip cypress.tgz
- run: mkdir << parameters.wd >>
- run: mkdir <<parameters.wd>>
- run: node --version
- run: npm --version
- run:
name: Create new NPM package ⚗️
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
command: npm init -y
- run:
name: Install dependencies 📦
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
environment:
CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
# let's install Cypress, Jest and any other package that might conflict
@@ -1226,7 +1231,7 @@ jobs:
typescript jest @types/jest enzyme @types/enzyme
- run:
name: Scaffold and test examples 🏗
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
environment:
CYPRESS_INTERNAL_FORCE_SCAFFOLD: "1"
command: |
@@ -1250,27 +1255,27 @@ jobs:
# make sure we have cypress.zip received
- run: ls -l
- run: ls -l cypress.zip cypress.tgz
- run: mkdir << parameters.wd >>
- run: mkdir <<parameters.wd>>
- run: node --version
- run: npm --version
- run:
name: Create new NPM package ⚗️
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
command: npm init -y
- run:
name: Install dependencies 📦
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
environment:
CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
command: |
npm install /root/cypress/cypress.tgz typescript
- run:
name: Scaffold full TypeScript project 🏗
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
command: npx @bahmutov/cly@1 init --typescript
- run:
name: Run project tests 🗳
working_directory: << parameters.wd >>
working_directory: <<parameters.wd>>
command: npx cypress run
# install NPM + binary zip and run against staging API
@@ -1282,9 +1287,8 @@ jobs:
- run: ls -l
# make sure we have the binary and NPM package
- run: ls -l cypress.zip cypress.tgz
- run:
name: Cloning test project
command: git clone https://github.com/cypress-io/cypress-test-tiny.git /tmp/cypress-test-tiny
- clone-repo-and-checkout-release-branch:
repo: cypress-test-tiny
- run:
name: Install Cypress
working_directory: /tmp/cypress-test-tiny
+3 -3
View File
@@ -2130,7 +2130,7 @@ declare namespace Cypress {
type Agent<T extends sinon.SinonSpy> = SinonSpyAgent<T> & T
interface CookieDefaults {
whitelist: string | string[] | RegExp | ((cookie: any) => boolean)
preserve: string | string[] | RegExp | ((cookie: any) => boolean)
}
interface Failable {
@@ -2616,7 +2616,7 @@ declare namespace Cypress {
enable: boolean
force404: boolean
urlMatchingOptions: object
whitelist(xhr: Request): void
ignore(xhr: Request): void
onAnyRequest(route: RouteOptions, proxy: any): void
onAnyResponse(route: RouteOptions, proxy: any): void
onAnyAbort(route: RouteOptions, proxy: any): void
@@ -4806,7 +4806,7 @@ declare namespace Cypress {
interface Server extends RouteOptions {
enable: boolean
whitelist: (xhr: any) => boolean
ignore: (xhr: any) => boolean
}
interface Viewport {
+1 -1
View File
@@ -35,7 +35,7 @@ cy.visit('https://www.acme.com/', {
const serverOptions: Partial<Cypress.ServerOptions> = {
delay: 100,
whitelist: () => true
ignore: () => true
}
cy.server(serverOptions)
@@ -1246,4 +1246,18 @@ describe('src/cy/commands/cookies', () => {
})
})
})
context('Cypress.cookies.defaults', () => {
it('throws error on use of renamed whitelist option', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('`Cypress.Cookies.defaults` `whitelist` option has been renamed to `preserve`. Please rename `whitelist` to `preserve`.')
done()
})
Cypress.Cookies.defaults({
whitelist: 'session_id',
})
})
})
})
@@ -305,39 +305,6 @@ describe('src/cy/commands/xhr', () => {
})
})
// FIXME: I have no idea why this is skipped, this test is rly old
describe.skip('filtering requests', () => {
beforeEach(() => {
cy.server()
})
const extensions = {
html: 'ajax html',
js: '{foo: "bar"}',
css: 'body {}',
}
_.each(extensions, (val, ext) => {
it(`filters out non ajax requests by default for extension: .${ext}`, (done) => {
cy.state('window').$.get(`/fixtures/app.${ext}`).done((res) => {
expect(res).to.eq(val)
done()
})
})
})
it('can disable default filtering', (done) => {
// this should throw since it should return 404 when no
// route matches it
cy.server({ ignore: false }).window().then((w) => {
Promise.resolve(w.$.get('/fixtures/app.html')).catch(() => {
done()
})
})
})
})
describe('url rewriting', () => {
it('has a FQDN absolute-relative url', () => {
cy
@@ -1139,6 +1106,14 @@ describe('src/cy/commands/xhr', () => {
})
})
it('sets ignore as function by default', () => {
cy.server()
cy.route('*', {})
.then(() => {
expect(cy.state('server').getRoutes()[0].ignore).to.be.a('function')
})
})
it('passes down options.delay to routes', () => {
cy
.server({ delay: 100 })
@@ -1243,110 +1218,6 @@ describe('src/cy/commands/xhr', () => {
})
})
// FIXME: I have no idea why this is skipped, this test is rly old
context.skip('#server', () => {
beforeEach(function () {
const defaults = {
ignore: true,
respond: true,
delay: 10,
beforeRequest () {},
afterResponse () {},
onAbort () {},
onError () {},
onFilter () {},
}
this.options = (obj) => {
return _.extend(obj, defaults)
}
this.create = cy.spy(this.Cypress.Server, 'create')
})
it('can accept an onRequest and onResponse callback', function (done) {
const onRequest = () => {}
const onResponse = () => {}
cy.on('end', () => {
expect(this.create.getCall(0).args[1]).to.have.keys(_.keys(this.options({ onRequest, onResponse })))
done()
})
cy.server(onRequest, onResponse)
})
it('can accept onRequest and onRespond through options', function (done) {
const onRequest = () => {}
const onResponse = () => {}
cy.on('end', () => {
expect(this.create.getCall(0).args[1]).to.have.keys(_.keys(this.options({ onRequest, onResponse })))
done()
})
cy.server({ onRequest, onResponse })
})
describe('without sinon present', () => {
beforeEach(() => {
// force us to start from blank window
cy.state('$autIframe').prop('src', 'about:blank')
})
it('can start server with no errors', () => {
cy
.server()
.visit('http://localhost:3500/fixtures/sinon.html')
})
it('can add routes with no errors', () => {
cy
.server()
.route(/foo/, {})
.visit('http://localhost:3500/fixtures/sinon.html')
})
it('routes xhr requests', () => {
cy
.server()
.route(/foo/, { foo: 'bar' })
.visit('http://localhost:3500/fixtures/sinon.html')
.window().then((w) => {
return w.$.get('/foo')
})
.then((resp) => {
expect(resp).to.deep.eq({ foo: 'bar' })
})
})
it('works with aliases', () => {
cy
.server()
.route(/foo/, { foo: 'bar' }).as('getFoo')
.visit('http://localhost:3500/fixtures/sinon.html')
.window().then((w) => {
return w.$.get('/foo')
})
.wait('@getFoo').then((xhr) => {
expect(xhr.responseText).to.eq(JSON.stringify({ foo: 'bar' }))
})
})
it('prevents XHR\'s from going out from sinon.html', () => {
cy
.server()
.route(/bar/, { bar: 'baz' }).as('getBar')
.visit('http://localhost:3500/fixtures/sinon.html')
.wait('@getBar').then((xhr) => {
expect(xhr.responseText).to.eq(JSON.stringify({ bar: 'baz' }))
})
})
})
})
context('#route', () => {
beforeEach(function () {
this.expectOptionsToBe = (opts) => {
@@ -1909,6 +1780,16 @@ describe('src/cy/commands/xhr', () => {
cy.route()
})
it('throws on use of whitelist option', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('The `cy.server()` `whitelist` option has been renamed to `ignore`. Please rename `whitelist` to `ignore`.')
done()
})
cy.server({ whitelist: () => { } })
})
it('url must be a string or regexp', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('`cy.route()` was called with an invalid `url`. `url` must be either a string or regular expression.')
@@ -2285,8 +2166,8 @@ describe('src/cy/commands/xhr', () => {
})
})
describe('whitelisting', () => {
it('does not send back 404s on whitelisted routes', () => {
describe('ignored routes', () => {
it('does not send back 404s on allowed routes', () => {
cy
.server()
.window().then((win) => {
@@ -2298,7 +2179,7 @@ describe('src/cy/commands/xhr', () => {
})
// https://github.com/cypress-io/cypress/issues/7280
it('ignores query params when whitelisting routes', () => {
it('ignores query params when filtering routes', () => {
cy.server()
cy.route(/url-with-query-param/, { foo: 'bar' }).as('getQueryParam')
cy.window().then((win) => {
@@ -2312,7 +2193,7 @@ describe('src/cy/commands/xhr', () => {
})
// https://github.com/cypress-io/cypress/issues/7280
it('ignores hashes when whitelisting routes', () => {
it('ignores hashes when filtering routes', () => {
cy.server()
cy.route(/url-with-hash/, { foo: 'bar' }).as('getHash')
cy.window().then((win) => {
@@ -2324,6 +2205,30 @@ describe('src/cy/commands/xhr', () => {
cy.wait('@getHash').its('response.body')
.should('deep.equal', { foo: 'bar' })
})
it('overrides ignoring resources when passed as option', () => {
cy.server({ ignore: () => false })
cy.route('app.js', { foo: 'bar' }).as('getJSResource')
cy.route('index.html', '<html></html>').as('getHTMLResource')
cy.route('style.css', 'body: {color: red;}').as('getCSSResource')
cy.window().then((win) => {
win.$.get('/fixtures/app.js')
win.$.get('/fixtures/style.css')
return win.$.get('/fixtures/index.html')
})
// normally these resources would be ignored
// but overwriting ignore to return false allows all resources
cy.wait('@getJSResource').its('response.body')
.should('deep.equal', { foo: 'bar' })
cy.wait('@getHTMLResource').its('response.body')
.should('deep.equal', '<html></html>')
cy.wait('@getCSSResource').its('response.body')
.should('deep.equal', 'body: {color: red;}')
})
})
describe('route setup', () => {
+1 -1
View File
@@ -95,7 +95,7 @@ module.exports = function (Commands, Cypress, cy, state, config) {
return resp
}
// iterate over all of these and ensure none are whitelisted
// iterate over all of these and ensure none are allowed
// or preserved
const cookies = Cypress.Cookies.getClearableCookies(resp)
+1 -1
View File
@@ -263,7 +263,7 @@ const shouldUpdateValue = (el: HTMLElement, key: KeyDetails, options: typeOption
if (!(numberRe.test(potentialValue))) {
debug('skipping inserting value since number input would be invalid', key.text, potentialValue)
// when typing in a number input, only certain whitelisted chars will insert text
// when typing in a number input, only certain allowed chars will insert text
if (!key.text.match(isValidNumberInputChar)) {
// https://github.com/cypress-io/cypress/issues/6055
// Should not remove old valid values when a new one is not a valid number char, just dismiss it with return
+12 -4
View File
@@ -9,7 +9,13 @@ let isDebuggingVerbose = false
const preserved = {}
const defaults = {
whitelist: null,
preserve: null,
}
const warnOnWhitelistRenamed = (obj, type) => {
if (obj.whitelist) {
return $errUtils.throwErrByPath('cookies.whitelist_renamed', { args: { type } })
}
}
const $Cookies = (namespace, domain) => {
@@ -17,8 +23,8 @@ const $Cookies = (namespace, domain) => {
return _.startsWith(name, namespace)
}
const isWhitelisted = (cookie) => {
const w = defaults.whitelist
const isAllowed = (cookie) => {
const w = defaults.preserve
if (w) {
if (_.isString(w)) {
@@ -76,7 +82,7 @@ const $Cookies = (namespace, domain) => {
getClearableCookies (cookies = []) {
return _.filter(cookies, (cookie) => {
return !isWhitelisted(cookie) && !removePreserved(cookie.name)
return !isAllowed(cookie) && !removePreserved(cookie.name)
})
},
@@ -132,6 +138,8 @@ const $Cookies = (namespace, domain) => {
},
defaults (obj = {}) {
warnOnWhitelistRenamed(obj, 'Cypress.Cookies.defaults')
// merge obj into defaults
return _.extend(defaults, obj)
},
@@ -301,6 +301,11 @@ module.exports = {
- \`cy.clearCookie()\`
- \`cy.clearCookies()\``,
},
whitelist_renamed (obj) {
return {
message: `\`${obj.type}\` \`whitelist\` option has been renamed to \`preserve\`. Please rename \`whitelist\` to \`preserve\`.`,
}
},
},
dom: {
@@ -1286,6 +1291,7 @@ module.exports = {
},
xhrurl_not_set: '`Server.options.xhrUrl` has not been set',
unavailable: 'The XHR server is unavailable or missing. This should never happen and likely is a bug. Open an issue if you see this message.',
whitelist_renamed: `The ${cmd('server')} \`whitelist\` option has been renamed to \`ignore\`. Please rename \`whitelist\` to \`ignore\`.`,
},
setCookie: {
+18 -11
View File
@@ -65,7 +65,13 @@ const warnOnForce404Default = (obj) => {
}
}
const whitelist = (xhr) => {
const warnOnWhitelistRenamed = (obj, type) => {
if (obj.whitelist) {
return $errUtils.throwErrByPath('server.whitelist_renamed', { args: { type } })
}
}
const ignore = (xhr) => {
const url = new URL(xhr.url)
// https://github.com/cypress-io/cypress/issues/7280
@@ -74,7 +80,7 @@ const whitelist = (xhr) => {
url.search = ''
url.hash = ''
// whitelist if we're GET + looks like we're fetching regular resources
// allow if we're GET + looks like we're fetching regular resources
return xhr.method === 'GET' && regularResourcesRe.test(url.href)
}
@@ -95,7 +101,7 @@ const serverDefaults = {
urlMatchingOptions: { matchBase: true },
stripOrigin: _.identity,
getUrlOptions: _.identity,
whitelist, // function whether to allow a request to go out (css/js/html/templates) etc
ignore, // function whether to allow a request to go out (css/js/html/templates) etc
onOpen () {},
onSend () {},
onXhrAbort () {},
@@ -209,8 +215,8 @@ const create = (options = {}) => {
return routes
},
isWhitelisted (xhr) {
return options.whitelist(xhr)
isIgnored (xhr) {
return options.ignore(xhr)
},
shouldApplyStub (route) {
@@ -257,9 +263,9 @@ const create = (options = {}) => {
// return the 404 stub if we dont have any stubs
// but we are stubbed - meaning we havent added any routes
// but have started the server
// and this request shouldnt be whitelisted
// and this request shouldnt be allowed
if (!routes.length && hasEnabledStubs &&
options.force404 !== false && !server.isWhitelisted(xhr)) {
options.force404 !== false && !server.isIgnored(xhr)) {
return get404Route()
}
@@ -268,8 +274,8 @@ const create = (options = {}) => {
return nope()
}
// bail if this xhr matches our whitelist
if (server.isWhitelisted(xhr)) {
// bail if this xhr matches our ignore list
if (server.isIgnored(xhr)) {
return nope()
}
@@ -414,6 +420,7 @@ const create = (options = {}) => {
set (obj) {
warnOnStubDeprecation(obj, 'server')
warnOnForce404Default(obj)
warnOnWhitelistRenamed(obj, 'server')
// handle enable=true|false
if (obj.enable != null) {
@@ -648,8 +655,8 @@ const create = (options = {}) => {
proxy._setRequestBody(requestBody)
// log this out now since it's being sent officially
// unless its been whitelisted
if (!server.isWhitelisted(this)) {
// unless its not been ignored
if (!server.isIgnored(this)) {
options.onSend(proxy, sendStack, route)
}
+5
View File
@@ -24,6 +24,11 @@ function replaceStringsIn (file) {
replace(eslintRe, "")
replace("imgSrcToDataURL('/assets", "imgSrcToDataURL('https://example.cypress.io/assets")
// temporary for 5.0.0
// TODO: remove this
replace("whitelist: 'session_id'", "preserve: 'session_id'")
replace("server.whitelist", "server.ignore")
fs.writeFile(file, str, function (err) {
if (err) throw err
@@ -18,12 +18,12 @@ exports['e2e cookies with baseurl'] = `
cookies
with whitelist
with preserve
can get all cookies
resets cookies between tests correctly
should be only two left now
handles undefined cookies
without whitelist
without preserve
sends set cookies to path
handles expired cookies secure
issue: #224 sets expired cookies between redirects
@@ -122,12 +122,12 @@ exports['e2e cookies with no baseurl'] = `
cookies
with whitelist
with preserve
can get all cookies
resets cookies between tests correctly
should be only two left now
handles undefined cookies
without whitelist
without preserve
sends cookies to localhost:2121
handles expired cookies secure
issue: #224 sets expired cookies between redirects
+3 -3
View File
@@ -83,7 +83,7 @@ firefoxGcInterval\
`)
// NOTE: If you add a config value, make sure to update the following
// - cli/types/index.d.ts (including whitelisted config options on TestOptions)
// - cli/types/index.d.ts (including allowed config options on TestOptions)
// - cypress.schema.json
// experimentalComponentTesting
@@ -372,7 +372,7 @@ module.exports = {
return _.includes(names, value)
},
whitelist (obj = {}) {
allowed (obj = {}) {
const propertyNames = configKeys
.concat(breakingConfigKeys)
.concat(systemConfigKeys)
@@ -427,7 +427,7 @@ module.exports = {
debug('merged config with options, got %o', config)
_
.chain(this.whitelist(options))
.chain(this.allowed(options))
.omit('env')
.omit('browsers')
.each((val, key) => {
+2 -2
View File
@@ -173,10 +173,10 @@ class Project extends EE {
_initPlugins (cfg, options) {
// only init plugins with the
// whitelisted config values to
// allowed config values to
// prevent tampering with the
// internals and breaking cypress
cfg = config.whitelist(cfg)
cfg = config.allowed(cfg)
return plugins.init(cfg, {
projectRoot: this.projectRoot,
+6 -6
View File
@@ -9,7 +9,7 @@ const fs = require('./util/fs')
const stateFiles = {}
const whitelist = `
const allowed = `
appWidth
appHeight
appX
@@ -64,7 +64,7 @@ const formStatePath = (projectRoot) => {
})
}
const normalizeAndWhitelistSet = (set, key, value) => {
const normalizeAndAllowSet = (set, key, value) => {
const valueObject = (() => {
if (_.isString(key)) {
const tmp = {}
@@ -78,15 +78,15 @@ const normalizeAndWhitelistSet = (set, key, value) => {
})()
const invalidKeys = _.filter(_.keys(valueObject), (key) => {
return !_.includes(whitelist, key)
return !_.includes(allowed, key)
})
if (invalidKeys.length) {
// eslint-disable-next-line no-console
console.error(`WARNING: attempted to save state for non-whitelisted key(s): ${invalidKeys.join(', ')}. All keys must be whitelisted in server/lib/saved_state.js`)
console.error(`WARNING: attempted to save state for non-allowed key(s): ${invalidKeys.join(', ')}. All keys must be allowed in server/lib/saved_state.js`)
}
return set(_.pick(valueObject, whitelist))
return set(_.pick(valueObject, allowed))
}
const create = (projectRoot, isTextTerminal) => {
@@ -110,7 +110,7 @@ const create = (projectRoot, isTextTerminal) => {
path: fullStatePath,
})
stateFile.set = _.wrap(stateFile.set.bind(stateFile), normalizeAndWhitelistSet)
stateFile.set = _.wrap(stateFile.set.bind(stateFile), normalizeAndAllowSet)
stateFiles[fullStatePath] = stateFile
+5 -5
View File
@@ -28,7 +28,7 @@ const appData = require('./util/app_data')
const statusCode = require('./util/status_code')
const headersUtil = require('./util/headers')
const allowDestroy = require('./util/server_destroy')
const { SocketWhitelist } = require('./util/socket_whitelist')
const { SocketAllowed } = require('./util/socket_allowed')
const errors = require('./errors')
const logger = require('./logger')
const Socket = require('./socket')
@@ -59,7 +59,7 @@ const _forceProxyMiddleware = function (clientRoute) {
const trimmedUrl = _.trimEnd(req.proxiedUrl, '/')
if (_isNonProxiedRequest(req) && !ALLOWED_PROXY_BYPASS_URLS.includes(trimmedUrl) && (trimmedUrl !== trimmedClientRoute)) {
// this request is non-proxied and non-whitelisted, redirect to the runner error page
// this request is non-proxied and non-allowed, redirect to the runner error page
return res.redirect(clientRoute)
}
@@ -115,7 +115,7 @@ class Server {
return new Server()
}
this._socketWhitelist = new SocketWhitelist()
this._socketAllowed = new SocketAllowed()
this._request = null
this._middleware = null
this._server = null
@@ -278,7 +278,7 @@ class Server {
this._server.on('connect', (req, socket, head) => {
debug('Got CONNECT request from %s', req.url)
socket.once('upstream-connected', this._socketWhitelist.add)
socket.once('upstream-connected', this._socketAllowed.add)
return this._httpsProxy.connect(req, socket, head, {
onDirectConnection: (req) => {
@@ -761,7 +761,7 @@ class Server {
let host; let remoteOrigin
if (req.url.startsWith(socketIoRoute)) {
if (!this._socketWhitelist.isRequestWhitelisted(req)) {
if (!this._socketAllowed.isRequestAllowed(req)) {
socket.write('HTTP/1.1 400 Bad Request\r\n\r\nRequest not made via a Cypress-launched browser.')
socket.end()
}
+5 -5
View File
@@ -13,7 +13,7 @@ const nestedObjectsInCurlyBracesRe = /\{(.+?)\}/g
const nestedArraysInSquareBracketsRe = /\[(.+?)\]/g
const everythingAfterFirstEqualRe = /=(.*)/
const whitelist = 'appPath apiKey browser ci ciBuildId clearLogs config configFile cwd env execPath exit exitWithCode generateKey getKey group headed inspectBrk key logs mode outputPath parallel ping port project proxySource quiet record reporter reporterOptions returnPkg runMode runProject smokeTest spec tag updating version'.split(' ')
const allowList = 'appPath apiKey browser ci ciBuildId clearLogs config configFile cwd env execPath exit exitWithCode generateKey getKey group headed inspectBrk key logs mode outputPath parallel ping port project proxySource quiet record reporter reporterOptions returnPkg runMode runProject smokeTest spec tag updating version'.split(' ')
// returns true if the given string has double quote character "
// only at the last position.
const hasStrayEndQuote = (s) => {
@@ -189,14 +189,14 @@ module.exports = {
alias,
})
const whitelisted = _.pick(argv, whitelist)
const allowed = _.pick(argv, allowList)
// were we invoked from the CLI or directly?
const invokedFromCli = Boolean(options.cwd)
options = _
.chain(options)
.defaults(whitelisted)
.defaults(allowed)
.omit(_.keys(alias)) // remove aliases
.extend({ invokedFromCli })
.defaults({
@@ -320,11 +320,11 @@ module.exports = {
toArray (obj = {}) {
// goes in reverse, takes an object
// and converts to an array by picking
// only the whitelisted properties and
// only the allowed properties and
// mapping them to include the argument
return _
.chain(obj)
.pick(...whitelist)
.pick(...allowList)
.mapValues((val, key) => {
return `--${key}=${stringify(val)}`
}).values()
@@ -0,0 +1,46 @@
import _ from 'lodash'
import Debug from 'debug'
import net from 'net'
import { Request } from 'express'
const debug = Debug('cypress:server:util:socket_allowed')
/**
* Utility to validate incoming, local socket connections against a list of
* expected client TCP ports.
*/
export class SocketAllowed {
allowedLocalPorts: number[] = []
/**
* Add a socket to the allowed list.
*/
add = (socket: net.Socket) => {
const { localPort } = socket
debug('allowing socket %o', { localPort })
this.allowedLocalPorts.push(localPort)
socket.once('close', () => {
debug('allowed socket closed, removing %o', { localPort })
this._remove(socket)
})
}
_remove (socket: net.Socket) {
_.pull(this.allowedLocalPorts, socket.localPort)
}
/**
* Is this socket that this request originated allowed?
*/
isRequestAllowed (req: Request) {
const { remotePort, remoteAddress } = req.socket
const isAllowed = this.allowedLocalPorts.includes(remotePort!)
&& ['127.0.0.1', '::1'].includes(remoteAddress!)
debug('is incoming request allowed? %o', { isAllowed, reqUrl: req.url, remotePort, remoteAddress })
return isAllowed
}
}
@@ -1,46 +0,0 @@
import _ from 'lodash'
import Debug from 'debug'
import net from 'net'
import { Request } from 'express'
const debug = Debug('cypress:server:util:socket_whitelist')
/**
* Utility to validate incoming, local socket connections against a list of
* expected client TCP ports.
*/
export class SocketWhitelist {
whitelistedLocalPorts: number[] = []
/**
* Add a socket to the whitelist.
*/
add = (socket: net.Socket) => {
const { localPort } = socket
debug('whitelisting socket %o', { localPort })
this.whitelistedLocalPorts.push(localPort)
socket.once('close', () => {
debug('whitelisted socket closed, removing %o', { localPort })
this._remove(socket)
})
}
_remove (socket: net.Socket) {
_.pull(this.whitelistedLocalPorts, socket.localPort)
}
/**
* Is this socket that this request originated from whitelisted?
*/
isRequestWhitelisted (req: Request) {
const { remotePort, remoteAddress } = req.socket
const isWhitelisted = this.whitelistedLocalPorts.includes(remotePort!)
&& ['127.0.0.1', '::1'].includes(remoteAddress!)
debug('is incoming request whitelisted? %o', { isWhitelisted, reqUrl: req.url, remotePort, remoteAddress })
return isWhitelisted
}
}
@@ -1,5 +1,5 @@
Cypress.Cookies.defaults({
whitelist: "foo1"
preserve: "foo1"
})
describe "Cookies", ->
@@ -84,3 +84,4 @@ describe "Cookies", ->
domain: "brian.dev.local"
})
.its("body").should("deep.eq", {wow: "bob"})
@@ -35,10 +35,10 @@ describe "cookies", ->
beforeEach ->
cy.wrap({foo: "bar"})
context "with whitelist", ->
context "with preserve", ->
before ->
Cypress.Cookies.defaults({
whitelist: "foo1"
preserve: "foo1"
})
it "can get all cookies", ->
@@ -104,10 +104,10 @@ describe "cookies", ->
it "handles undefined cookies", ->
cy.visit("/cookieWithNoName")
context "without whitelist", ->
context "without preserve", ->
before ->
Cypress.Cookies.defaults({
whitelist: []
preserve: []
})
it "sends set cookies to path", ->
@@ -5,10 +5,10 @@ describe "cookies", ->
beforeEach ->
cy.wrap({foo: "bar"})
context "with whitelist", ->
context "with preserve", ->
before ->
Cypress.Cookies.defaults({
whitelist: "foo1"
preserve: "foo1"
})
it "can get all cookies", ->
@@ -79,10 +79,10 @@ describe "cookies", ->
it "handles undefined cookies", ->
cy.visit("#{httpUrl}/cookieWithNoName")
context "without whitelist", ->
context "without preserve", ->
before ->
Cypress.Cookies.defaults({
whitelist: []
preserve: []
})
it "sends cookies to localhost:2121", ->
+1 -1
View File
@@ -270,7 +270,7 @@ describe('lib/util/args', () => {
expect(options.config).to.deep.eq(config)
})
it('whitelists config properties', function () {
it('allows config properties', function () {
const options = this.setup('--config', 'foo=bar,port=1111,supportFile=path/to/support_file')
expect(options.config.port).to.eq(1111)
@@ -62,7 +62,7 @@ describe('lib/saved_state', () => {
})
})
it('only saves whitelisted keys', () => {
it('only saves allowed keys', () => {
return savedState.create()
.then((state) => {
return state.set({ foo: 'bar', appWidth: 20 })
@@ -81,7 +81,7 @@ describe('lib/saved_state', () => {
.then((state) => {
return state.set({ foo: 'bar', baz: 'qux' })
}).then(() => {
expect(console.error).to.be.calledWith('WARNING: attempted to save state for non-whitelisted key(s): foo, baz. All keys must be whitelisted in server/lib/saved_state.js')
expect(console.error).to.be.calledWith('WARNING: attempted to save state for non-allowed key(s): foo, baz. All keys must be allowed in server/lib/saved_state.js')
})
})
})
@@ -679,7 +679,7 @@ describe('lib/screenshots', () => {
return sinon.stub(plugins, 'execute')
})
it('resolves whitelisted details if no after:screenshot plugin registered', function () {
it('resolves allowed details if no after:screenshot plugin registered', function () {
plugins.has.returns(false)
return screenshots.afterScreenshot(this.data, this.details).then((result) => {
+1 -1
View File
@@ -338,7 +338,7 @@ describe('lib/server', () => {
remoteAddress: '127.0.0.1',
}
this.server._socketWhitelist.add({
this.server._socketAllowed.add({
localPort: socket.remotePort,
once: _.noop,
})
@@ -0,0 +1,42 @@
import '../../spec_helper'
import { expect } from 'chai'
import { Request } from 'express'
import { SocketAllowed } from '../../../lib/util/socket_allowed'
import { EventEmitter } from 'events'
import { Socket } from 'net'
describe('lib/util/socket_allowed', function () {
let sw: SocketAllowed
beforeEach(() => {
sw = new SocketAllowed()
})
context('#add', () => {
it('adds localPort to allowed list and removes it when closed', () => {
const socket = new EventEmitter as Socket
// @ts-ignore readonly
socket.localPort = 12345
const req = {
socket: {
remotePort: socket.localPort,
remoteAddress: '127.0.0.1',
},
} as Request
expect(sw.allowedLocalPorts).to.deep.eq([])
expect(sw.isRequestAllowed(req)).to.be.false
sw.add(socket)
expect(sw.allowedLocalPorts).to.deep.eq([socket.localPort])
expect(sw.isRequestAllowed(req)).to.be.true
socket.emit('close')
expect(sw.allowedLocalPorts).to.deep.eq([])
expect(sw.isRequestAllowed(req)).to.be.false
})
})
})
@@ -1,42 +0,0 @@
import '../../spec_helper'
import { expect } from 'chai'
import { Request } from 'express'
import { SocketWhitelist } from '../../../lib/util/socket_whitelist'
import { EventEmitter } from 'events'
import { Socket } from 'net'
describe('lib/util/socket_whitelist', function () {
let sw: SocketWhitelist
beforeEach(() => {
sw = new SocketWhitelist()
})
context('#add', () => {
it('adds localPort to whitelist and removes it when closed', () => {
const socket = new EventEmitter as Socket
// @ts-ignore readonly
socket.localPort = 12345
const req = {
socket: {
remotePort: socket.localPort,
remoteAddress: '127.0.0.1',
},
} as Request
expect(sw.whitelistedLocalPorts).to.deep.eq([])
expect(sw.isRequestWhitelisted(req)).to.be.false
sw.add(socket)
expect(sw.whitelistedLocalPorts).to.deep.eq([socket.localPort])
expect(sw.isRequestWhitelisted(req)).to.be.true
socket.emit('close')
expect(sw.whitelistedLocalPorts).to.deep.eq([])
expect(sw.isRequestWhitelisted(req)).to.be.false
})
})
})