chore: remove experimentalSessionAndOrigin flag (#24340)

BREAKING CHANGE: removed experimentalSessionAndOrigin flag. testIsolation defaults to strict
This commit is contained in:
Matt Schile
2022-10-24 08:49:13 -06:00
committed by GitHub
parent 2b557d551a
commit 69873ae988
97 changed files with 525 additions and 1596 deletions
+9 -96
View File
@@ -27,8 +27,8 @@ mainBuildFilters: &mainBuildFilters
branches:
only:
- develop
- fix-ci-deps
- issue-23843_electron_21_upgrade
- release/11.0.0
- mschile/issue-21471_remove_experimentalSessionAndOrigin
# usually we don't build Mac app - it takes a long time
# but sometimes we want to really confirm we are doing the right thing
@@ -37,8 +37,7 @@ macWorkflowFilters: &darwin-workflow-filters
when:
or:
- equal: [ develop, << pipeline.git.branch >> ]
- equal: [ 'correct-dashboard-results', << pipeline.git.branch >> ]
- equal: [ 'issue-23843_electron_21_upgrade', << pipeline.git.branch >> ]
- equal: [ 'release/11.0.0', << pipeline.git.branch >> ]
- matches:
pattern: "-release$"
value: << pipeline.git.branch >>
@@ -47,8 +46,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
when:
or:
- equal: [ develop, << pipeline.git.branch >> ]
- equal: [ 'webkit-multidomain', << pipeline.git.branch >> ]
- equal: [ 'issue-23843_electron_21_upgrade', << pipeline.git.branch >> ]
- equal: [ 'release/11.0.0', << pipeline.git.branch >> ]
- matches:
pattern: "-release$"
value: << pipeline.git.branch >>
@@ -66,8 +64,7 @@ windowsWorkflowFilters: &windows-workflow-filters
when:
or:
- equal: [ develop, << pipeline.git.branch >> ]
- equal: [ linux-arm64, << pipeline.git.branch >> ]
- equal: [ 'issue-23843_electron_21_upgrade', << pipeline.git.branch >> ]
- equal: [ release/11.0.0, << pipeline.git.branch >> ]
- matches:
pattern: "-release$"
value: << pipeline.git.branch >>
@@ -132,7 +129,7 @@ commands:
- run:
name: Check current branch to persist artifacts
command: |
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "issue-23843_electron_21_upgrade" ]]; then
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/11.0.0" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi
@@ -458,10 +455,6 @@ commands:
description: chrome channel to install
type: string
default: ''
experimentalSessionAndOrigin:
description: experimental flag to apply
type: boolean
default: false
steps:
- restore_cached_workspace
- when:
@@ -485,13 +478,8 @@ commands:
if [[ -v MAIN_RECORD_KEY ]]; then
# internal PR
if <<parameters.experimentalSessionAndOrigin>>; then
CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \
yarn cypress:run-experimentalSessionAndOrigin --record --parallel --group 5x-driver-<<parameters.browser>>-experimentalSessionAndOrigin --browser <<parameters.browser>>
else
CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \
yarn cypress:run --record --parallel --group 5x-driver-<<parameters.browser>> --browser <<parameters.browser>>
fi
CYPRESS_RECORD_KEY=$MAIN_RECORD_KEY \
yarn cypress:run --record --parallel --group 5x-driver-<<parameters.browser>> --browser <<parameters.browser>>
else
# external PR
TESTFILES=$(circleci tests glob "cypress/e2e/**/*.cy.*" | circleci tests split --total=$CIRCLE_NODE_TOTAL)
@@ -500,11 +488,7 @@ commands:
if [[ -z "$TESTFILES" ]]; then
echo "Empty list of test files"
fi
if <<parameters.experimentalSessionAndOrigin>>; then
yarn cypress:run-experimentalSessionAndOrigin --browser <<parameters.browser>> --spec $TESTFILES
else
yarn cypress:run --browser <<parameters.browser>> --spec $TESTFILES
fi
yarn cypress:run --browser <<parameters.browser>> --spec $TESTFILES
fi
working_directory: packages/driver
- verify-mocha-results
@@ -1605,53 +1589,6 @@ jobs:
- run-driver-integration-tests:
browser: webkit
driver-integration-tests-chrome-experimentalSessionAndOrigin:
<<: *defaults
resource_class: medium
parallelism: 5
steps:
- run-driver-integration-tests:
browser: chrome
install-chrome-channel: stable
experimentalSessionAndOrigin: true
driver-integration-tests-chrome-beta-experimentalSessionAndOrigin:
<<: *defaults
resource_class: medium
parallelism: 5
steps:
- run-driver-integration-tests:
browser: chrome:beta
install-chrome-channel: beta
experimentalSessionAndOrigin: true
driver-integration-tests-firefox-experimentalSessionAndOrigin:
<<: *defaults
resource_class: medium
parallelism: 5
steps:
- run-driver-integration-tests:
browser: firefox
experimentalSessionAndOrigin: true
driver-integration-tests-electron-experimentalSessionAndOrigin:
<<: *defaults
resource_class: medium
parallelism: 5
steps:
- run-driver-integration-tests:
browser: electron
experimentalSessionAndOrigin: true
driver-integration-tests-webkit-experimentalSessionAndOrigin:
<<: *defaults
resource_class: medium
parallelism: 5
steps:
- run-driver-integration-tests:
browser: webkit
experimentalSessionAndOrigin: true
run-reporter-component-tests-chrome:
<<: *defaults
parameters:
@@ -2422,26 +2359,6 @@ linux-x64-workflow: &linux-x64-workflow
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-chrome-experimentalSessionAndOrigin:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-chrome-beta-experimentalSessionAndOrigin:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-firefox-experimentalSessionAndOrigin:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-electron-experimentalSessionAndOrigin:
context: test-runner:cypress-record-key
requires:
- build
- driver-integration-tests-webkit-experimentalSessionAndOrigin:
context: test-runner:cypress-record-key
requires:
- build
- run-frontend-shared-component-tests-chrome:
context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy]
percy: true
@@ -2543,10 +2460,6 @@ linux-x64-workflow: &linux-x64-workflow
- driver-integration-tests-chrome
- driver-integration-tests-chrome-beta
- driver-integration-tests-electron
- driver-integration-tests-firefox-experimentalSessionAndOrigin
- driver-integration-tests-chrome-experimentalSessionAndOrigin
- driver-integration-tests-chrome-beta-experimentalSessionAndOrigin
- driver-integration-tests-electron-experimentalSessionAndOrigin
- system-tests-non-root
- system-tests-firefox
- system-tests-electron
+3 -10
View File
@@ -1081,8 +1081,6 @@ declare namespace Cypress {
/**
* Save/Restore browser Cookies, LocalStorage, and SessionStorage data resulting from the supplied `setup` function.
*
* Only available if the `experimentalSessionAndOrigin` config option is enabled.
*
* @see https://on.cypress.io/session
*/
session(id: string | object, setup?: () => void, options?: SessionOptions): Chainable<null>
@@ -2803,7 +2801,7 @@ declare namespace Cypress {
* The test isolation level applied to ensure a clean slate between tests.
* - legacy - resets/clears aliases, intercepts, clock, viewport, cookies, and local storage before each test.
* - strict - applies all resets/clears from legacy, plus clears the page by visiting 'about:blank' to ensure clean app state before each test.
* @default "legacy", however, when experimentalSessionAndOrigin=true, the default is "strict"
* @default "strict"
*/
testIsolation: 'legacy' | 'strict'
/**
@@ -2866,11 +2864,6 @@ declare namespace Cypress {
* @default false
*/
experimentalInteractiveRunEvents: boolean
/**
* Enables cross-origin and improved session support, including the `cy.origin` and `cy.session` commands. See https://on.cypress.io/origin and https://on.cypress.io/session.
* @default false
*/
experimentalSessionAndOrigin: boolean
/**
* Whether Cypress will search for and replace obstructive code in third party .js or .html files.
* NOTE: Setting this flag to true removes Subresource Integrity (SRI).
@@ -3038,7 +3031,7 @@ declare namespace Cypress {
xhrUrl: string
}
interface TestConfigOverrides extends Partial<Pick<ConfigOptions, 'animationDistanceThreshold' | 'blockHosts' | 'defaultCommandTimeout' | 'env' | 'execTimeout' | 'includeShadowDom' | 'numTestsKeptInMemory' | 'pageLoadTimeout' | 'redirectionLimit' | 'requestTimeout' | 'responseTimeout' | 'retries' | 'screenshotOnRunFailure' | 'slowTestThreshold' | 'scrollBehavior' | 'taskTimeout' | 'viewportHeight' | 'viewportWidth' | 'waitForAnimations' | 'experimentalSessionAndOrigin'>>, Partial<Pick<ResolvedConfigOptions, 'baseUrl'>> {
interface TestConfigOverrides extends Partial<Pick<ConfigOptions, 'animationDistanceThreshold' | 'blockHosts' | 'defaultCommandTimeout' | 'env' | 'execTimeout' | 'includeShadowDom' | 'numTestsKeptInMemory' | 'pageLoadTimeout' | 'redirectionLimit' | 'requestTimeout' | 'responseTimeout' | 'retries' | 'screenshotOnRunFailure' | 'slowTestThreshold' | 'scrollBehavior' | 'taskTimeout' | 'viewportHeight' | 'viewportWidth' | 'waitForAnimations'>>, Partial<Pick<ResolvedConfigOptions, 'baseUrl'>> {
browser?: IsBrowserMatcher | IsBrowserMatcher[]
keystrokeDelay?: number
}
@@ -3094,7 +3087,7 @@ declare namespace Cypress {
}
}
interface ComponentConfigOptions<ComponentDevServerOpts = any> extends Omit<CoreConfigOptions, 'baseUrl' | 'experimentalSessionAndOrigin' | 'experimentalStudio'> {
interface ComponentConfigOptions<ComponentDevServerOpts = any> extends Omit<CoreConfigOptions, 'baseUrl' | 'experimentalStudio'> {
devServer: DevServerFn<ComponentDevServerOpts> | DevServerConfigOptions
devServerConfig?: ComponentDevServerOpts
/**
+12
View File
@@ -217,6 +217,18 @@ export function setupHooks (optionalCallback?: Function) {
)
})
Cypress.Commands.overwrite('session', () => {
throw new Error(
'cy.session from a component spec is not allowed',
)
})
Cypress.Commands.overwrite('origin', () => {
throw new Error(
'cy.origin from a component spec is not allowed',
)
})
// @ts-ignore
Cypress.on('test:before:run', () => {
optionalCallback?.()
-1
View File
@@ -3,7 +3,6 @@ import { defineConfig } from 'cypress'
export default defineConfig({
projectId: 'ypt4pf',
e2e: {
experimentalSessionAndOrigin: true,
defaultCommandTimeout: 10000, // these take a bit longer b/c they're e2e open mode test
async setupNodeEvents (on, config) {
if (!process.env.HTTP_PROXY_TARGET_FOR_ORIGIN_REQUESTS) {
-12
View File
@@ -202,18 +202,6 @@ describe('App: Settings', () => {
})
})
cy.get('[data-cy="experiment-experimentalSessionAndOrigin"]').within(() => {
cy.validateExternalLink({
name: 'cy.session()',
href: 'https://on.cypress.io/session',
})
cy.validateExternalLink({
name: 'cy.origin()',
href: 'https://on.cypress.io/origin',
})
})
cy.get('[data-cy="experiment-experimentalSourceRewriting"]').within(() => {
cy.validateExternalLink({
name: '#5273',
@@ -6,6 +6,7 @@ exports['config/src/index .getBreakingKeys returns list of breaking config keys
"experimentalNetworkStubbing",
"experimentalRunEvents",
"experimentalSessionSupport",
"experimentalSessionAndOrigin",
"experimentalShadowDomSupport",
"firefoxGcInterval",
"ignoreTestFiles",
@@ -35,7 +36,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1
"execTimeout": 60000,
"experimentalFetchPolyfill": false,
"experimentalInteractiveRunEvents": false,
"experimentalSessionAndOrigin": false,
"experimentalModifyObstructiveThirdPartyCode": false,
"experimentalSourceRewriting": false,
"experimentalSingleTabRunMode": false,
@@ -52,7 +52,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1
"port": null,
"projectId": null,
"redirectionLimit": 20,
"repoRoot": null,
"reporter": "spec",
"reporterOptions": null,
"requestTimeout": 5000,
@@ -70,7 +69,7 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1
"supportFile": "cypress/support/e2e.{js,jsx,ts,tsx}",
"supportFolder": false,
"taskTimeout": 60000,
"testIsolation": "legacy",
"testIsolation": "strict",
"trashAssetsBeforeRuns": true,
"userAgent": null,
"video": true,
@@ -94,6 +93,7 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1
"isTextTerminal": false,
"morgan": true,
"namespace": "__cypress",
"repoRoot": null,
"reporterRoute": "/__cypress/reporter",
"socketId": null,
"socketIoCookie": "__socket",
@@ -120,7 +120,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys f
"execTimeout": 60000,
"experimentalFetchPolyfill": false,
"experimentalInteractiveRunEvents": false,
"experimentalSessionAndOrigin": false,
"experimentalModifyObstructiveThirdPartyCode": false,
"experimentalSourceRewriting": false,
"experimentalSingleTabRunMode": false,
@@ -137,7 +136,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys f
"port": null,
"projectId": null,
"redirectionLimit": 20,
"repoRoot": null,
"reporter": "spec",
"reporterOptions": null,
"requestTimeout": 5000,
@@ -155,7 +153,7 @@ exports['config/src/index .getDefaultValues returns list of public config keys f
"supportFile": "cypress/support/e2e.{js,jsx,ts,tsx}",
"supportFolder": false,
"taskTimeout": 60000,
"testIsolation": "legacy",
"testIsolation": "strict",
"trashAssetsBeforeRuns": true,
"userAgent": null,
"video": true,
@@ -179,6 +177,7 @@ exports['config/src/index .getDefaultValues returns list of public config keys f
"isTextTerminal": false,
"morgan": true,
"namespace": "__cypress",
"repoRoot": null,
"reporterRoute": "/__cypress/reporter",
"socketId": null,
"socketIoCookie": "__socket",
@@ -201,7 +200,6 @@ exports['config/src/index .getPublicConfigKeys returns list of public config key
"execTimeout",
"experimentalFetchPolyfill",
"experimentalInteractiveRunEvents",
"experimentalSessionAndOrigin",
"experimentalModifyObstructiveThirdPartyCode",
"experimentalSourceRewriting",
"experimentalSingleTabRunMode",
+6 -21
View File
@@ -21,6 +21,7 @@ const BREAKING_OPTION_ERROR_KEY: Readonly<AllCypressErrorNames[]> = [
'EXPERIMENTAL_NETWORK_STUBBING_REMOVED',
'EXPERIMENTAL_RUN_EVENTS_REMOVED',
'EXPERIMENTAL_SESSION_SUPPORT_REMOVED',
'EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED',
'EXPERIMENTAL_SINGLE_TAB_RUN_MODE',
'EXPERIMENTAL_SHADOW_DOM_REMOVED',
'FIREFOX_GC_INTERVAL_REMOVED',
@@ -199,11 +200,6 @@ const driverConfigOptions: Array<DriverConfigOption> = [
validation: validate.isBoolean,
isExperimental: true,
requireRestartOnChange: 'server',
}, {
name: 'experimentalSessionAndOrigin',
defaultValue: false,
validation: validate.isBoolean,
isExperimental: true,
}, {
name: 'experimentalModifyObstructiveThirdPartyCode',
defaultValue: false,
@@ -371,12 +367,7 @@ const driverConfigOptions: Array<DriverConfigOption> = [
overrideLevel: 'any',
}, {
name: 'testIsolation',
// TODO: https://github.com/cypress-io/cypress/issues/23093
// When experimentalSessionAndOrigin is removed and released as GA,
// update the defaultValue from 'legacy' to 'strict' and
// update this code to remove the check/override specific to enable
// strict by default when experimentalSessionAndOrigin=true
defaultValue: 'legacy',
defaultValue: 'strict',
validation: validate.isOneOf('legacy', 'strict'),
overrideLevel: 'suite',
}, {
@@ -578,6 +569,10 @@ export const breakingOptions: Readonly<BreakingOption[]> = [
name: 'experimentalSessionSupport',
errorKey: 'EXPERIMENTAL_SESSION_SUPPORT_REMOVED',
isWarning: true,
}, {
name: 'experimentalSessionAndOrigin',
errorKey: 'EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED',
isWarning: true,
}, {
name: 'experimentalShadowDomSupport',
errorKey: 'EXPERIMENTAL_SHADOW_DOM_REMOVED',
@@ -623,11 +618,6 @@ export const breakingRootOptions: Array<BreakingOption> = [
errorKey: 'CONFIG_FILE_INVALID_ROOT_CONFIG_E2E',
isWarning: false,
testingTypes: ['e2e'],
}, {
name: 'experimentalSessionAndOrigin',
errorKey: 'CONFIG_FILE_INVALID_ROOT_CONFIG_E2E',
isWarning: false,
testingTypes: ['e2e'],
}, {
name: 'excludeSpecPattern',
errorKey: 'CONFIG_FILE_INVALID_ROOT_CONFIG',
@@ -681,11 +671,6 @@ export const testingTypeBreakingOptions: { e2e: Array<BreakingOption>, component
errorKey: 'CONFIG_FILE_INVALID_TESTING_TYPE_CONFIG_COMPONENT',
isWarning: false,
},
{
name: 'experimentalSessionAndOrigin',
errorKey: 'CONFIG_FILE_INVALID_TESTING_TYPE_CONFIG_COMPONENT',
isWarning: false,
},
{
name: 'experimentalStudio',
errorKey: 'EXPERIMENTAL_STUDIO_E2E_ONLY',
-14
View File
@@ -476,20 +476,6 @@ export function mergeDefaults (
throw makeConfigError(errors.get(err, ...args))
}, testingType)
// TODO: https://github.com/cypress-io/cypress/issues/23093
// testIsolation should equal 'strict' by default when experimentalSessionAndOrigin=true
// Once experimentalSessionAndOrigin is made GA, remove this logic and update the defaultValue
// to be be 'strict'
if (testingType === 'e2e' && config.experimentalSessionAndOrigin) {
if (config.rawJson.testIsolation) {
config.resolved.testIsolation.from = 'config'
} else {
config.testIsolation = 'strict'
config.resolved.testIsolation.value = 'strict'
config.resolved.testIsolation.from === 'default'
}
}
// We need to remove the nested propertied by testing type because it has been
// flattened/compacted based on the current testing type that is selected
// making the config only available with the properties that are valid,
+13 -33
View File
@@ -968,6 +968,16 @@ describe('config/src/project/utils', () => {
expect(warning).to.be.calledWith('EXPERIMENTAL_SESSION_SUPPORT_REMOVED')
})
it('warns if experimentalSessionAndOrigin is passed', async function () {
const warning = sinon.spy(errors, 'warning')
await this.defaults('experimentalSessionAndOrigin', true, {
experimentalSessionAndOrigin: true,
})
expect(warning).to.be.calledWith('EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED')
})
it('warns if experimentalShadowDomSupport is passed', async function () {
const warning = sinon.spy(errors, 'warning')
@@ -1040,7 +1050,6 @@ describe('config/src/project/utils', () => {
experimentalModifyObstructiveThirdPartyCode: { value: false, from: 'default' },
experimentalFetchPolyfill: { value: false, from: 'default' },
experimentalInteractiveRunEvents: { value: false, from: 'default' },
experimentalSessionAndOrigin: { value: false, from: 'default' },
experimentalSingleTabRunMode: { value: false, from: 'default' },
experimentalStudio: { value: false, from: 'default' },
experimentalSourceRewriting: { value: false, from: 'default' },
@@ -1074,7 +1083,7 @@ describe('config/src/project/utils', () => {
supportFile: { value: false, from: 'config' },
supportFolder: { value: false, from: 'default' },
taskTimeout: { value: 60000, from: 'default' },
testIsolation: { value: 'legacy', from: 'default' },
testIsolation: { value: 'strict', from: 'default' },
trashAssetsBeforeRuns: { value: true, from: 'default' },
userAgent: { value: null, from: 'default' },
video: { value: true, from: 'default' },
@@ -1134,7 +1143,6 @@ describe('config/src/project/utils', () => {
experimentalModifyObstructiveThirdPartyCode: { value: false, from: 'default' },
experimentalFetchPolyfill: { value: false, from: 'default' },
experimentalInteractiveRunEvents: { value: false, from: 'default' },
experimentalSessionAndOrigin: { value: false, from: 'default' },
experimentalSingleTabRunMode: { value: false, from: 'default' },
experimentalStudio: { value: false, from: 'default' },
experimentalSourceRewriting: { value: false, from: 'default' },
@@ -1190,7 +1198,7 @@ describe('config/src/project/utils', () => {
supportFile: { value: false, from: 'config' },
supportFolder: { value: false, from: 'default' },
taskTimeout: { value: 60000, from: 'default' },
testIsolation: { value: 'legacy', from: 'default' },
testIsolation: { value: 'strict', from: 'default' },
trashAssetsBeforeRuns: { value: true, from: 'default' },
userAgent: { value: null, from: 'default' },
video: { value: true, from: 'default' },
@@ -1206,39 +1214,13 @@ describe('config/src/project/utils', () => {
})
})
it('sets testIsolation=strict by default when experimentalSessionAndOrigin=true and e2e testing', () => {
it('honors user config for testIsolation', () => {
sinon.stub(utils, 'getProcessEnvVars').returns({})
const obj = {
projectRoot: '/foo/bar',
supportFile: false,
baseUrl: 'http://localhost:8080',
experimentalSessionAndOrigin: true,
}
const options = {
testingType: 'e2e',
}
const getFilesByGlob = sinon.stub().returns(['path/to/file.ts'])
return mergeDefaults(obj, options, {}, getFilesByGlob)
.then((cfg) => {
expect(cfg.resolved).to.have.property('experimentalSessionAndOrigin')
expect(cfg.resolved.experimentalSessionAndOrigin).to.deep.eq({ value: true, from: 'config' })
expect(cfg.resolved).to.have.property('testIsolation')
expect(cfg.resolved.testIsolation).to.deep.eq({ value: 'strict', from: 'default' })
})
})
it('honors user config for testIsolation when experimentalSessionAndOrigin=true and e2e testing', () => {
sinon.stub(utils, 'getProcessEnvVars').returns({})
const obj = {
projectRoot: '/foo/bar',
supportFile: false,
baseUrl: 'http://localhost:8080',
experimentalSessionAndOrigin: true,
testIsolation: 'legacy',
}
@@ -1250,8 +1232,6 @@ describe('config/src/project/utils', () => {
return mergeDefaults(obj, options, {}, getFilesByGlob)
.then((cfg) => {
expect(cfg.resolved).to.have.property('experimentalSessionAndOrigin')
expect(cfg.resolved.experimentalSessionAndOrigin).to.deep.eq({ value: true, from: 'config' })
expect(cfg.resolved).to.have.property('testIsolation')
expect(cfg.resolved.testIsolation).to.deep.eq({ value: 'legacy', from: 'config' })
})
@@ -28,7 +28,6 @@ module.exports = defineConfig({
return require('./cypress/plugins/index.js')(on, config)
},
baseUrl: 'localhost:3000',
experimentalSessionAndOrigin: true,
},
component: {
setupNodeEvents(on, config) {},
@@ -69,7 +68,6 @@ module.exports = defineConfig({
},
retries: 2,
baseUrl: 'localhost:300',
experimentalSessionAndOrigin: true,
slowTestThreshold: 500,
},
component: {
@@ -495,7 +495,6 @@ export function reduceConfig (cfg: LegacyCypressConfigJson, options: CreateConfi
e2e: { ...acc.e2e, supportFile: val },
}
case 'baseUrl':
case 'experimentalSessionAndOrigin':
return {
...acc,
e2e: { ...acc.e2e, [key]: val },
@@ -96,11 +96,6 @@ const resolvedOptions: Array<ResolvedConfigOption> = [
defaultValue: false,
isExperimental: true,
canUpdateDuringTestTime: false,
}, {
name: 'experimentalSessionAndOrigin',
defaultValue: false,
isExperimental: true,
canUpdateDuringTestTime: true,
}, {
name: 'experimentalSourceRewriting',
defaultValue: false,
@@ -60,7 +60,6 @@ describe('cypress.config.js generation', () => {
const config: Partial<Cypress.Config> = {
e2e: {
baseUrl: 'localhost:3000',
experimentalSessionAndOrigin: true,
},
}
@@ -127,7 +126,6 @@ describe('cypress.config.js generation', () => {
const config = {
viewportWidth: 300,
baseUrl: 'localhost:300',
experimentalSessionAndOrigin: true,
slowTestThreshold: 500,
e2e: {
retries: 2,
@@ -42,11 +42,8 @@ describe('src/cy/commands/local_storage', () => {
const clear = cy.spy(Cypress.LocalStorage, 'clear')
Cypress.emit('test:before:run', {})
if (Cypress.config('experimentalSessionAndOrigin')) {
expect(clear).not.to.be.called
} else {
expect(clear).to.be.calledWith([])
}
expect(clear).not.to.be.called
})
})
@@ -595,20 +595,18 @@ describe('src/cy/commands/navigation', () => {
})
})
if (Cypress.config('experimentalSessionAndOrigin')) {
describe('removes window:load listeners when testIsolation=strict', () => {
it('removes for first url visit', () => {
const listeners = cy.listeners('window:load')
describe('removes window:load listeners when testIsolation=strict', () => {
it('removes for first url visit', () => {
const listeners = cy.listeners('window:load')
const winLoad = cy.spy(cy, 'once').withArgs('window:load')
const winLoad = cy.spy(cy, 'once').withArgs('window:load')
cy.visit('/fixtures/generic.html').then(() => {
expect(winLoad).to.be.calledOnce
expect(cy.listeners('window:load')).to.deep.eq(listeners)
})
cy.visit('/fixtures/generic.html').then(() => {
expect(winLoad).to.be.calledOnce
expect(cy.listeners('window:load')).to.deep.eq(listeners)
})
})
}
})
it('can visit pages on the same origin', () => {
cy
@@ -617,6 +615,32 @@ describe('src/cy/commands/navigation', () => {
.visit('http://localhost:3500/fixtures/dimensions.html')
})
it('can visit a 2nd domain on different port', function () {
cy.visit('http://localhost:3500/fixtures/generic.html')
cy.visit('http://localhost:3501/fixtures/generic.html')
})
it('can visit a 2nd domain on different protocol', function () {
cy.visit('http://localhost:3500/fixtures/generic.html')
cy.visit('https://localhost:3502/fixtures/generic.html')
})
it('can visit a 2nd domain on different superdomain', function () {
cy.visit('http://localhost:3500/fixtures/generic.html')
cy.visit('http://www.foobar.com:3500/fixtures/generic.html')
})
it('can visit 2 unique ip addresses', function () {
cy
.visit('http://127.0.0.1:3500/fixtures/generic.html')
.visit('http://0.0.0.0:3500/fixtures/generic.html')
})
it('can navigate to a cross origin', { pageLoadTimeout: 3000 }, function () {
cy.visit('/fixtures/primary-origin.html')
cy.get('a[data-cy="cross-origin-secondary-link"]').click()
})
it('resolves the subject to the remote iframe window', () => {
cy.visit('/fixtures/jquery.html').then((win) => {
expect(win).to.eq(cy.state('$autIframe').prop('contentWindow'))
@@ -806,43 +830,41 @@ describe('src/cy/commands/navigation', () => {
})
})
if (Cypress.config('experimentalSessionAndOrigin')) {
describe('when only hashes are changing when testIsolation=strict', () => {
it('short circuits the visit if the page will not refresh', () => {
let count = 0
const urls = []
describe('when only hashes are changing when testIsolation=strict', () => {
it('short circuits the visit if the page will not refresh', () => {
let count = 0
const urls = []
cy.on('window:load', () => {
urls.push(cy.state('window').location.href)
cy.on('window:load', () => {
urls.push(cy.state('window').location.href)
count += 1
})
count += 1
})
cy
.visit('/fixtures/generic.html?foo#bar') // yes (1)
.visit('/fixtures/generic.html?foo#foo') // no (1)
.visit('/fixtures/generic.html?bar#bar') // yes (2)
.visit('/fixtures/dimensions.html?bar#bar') // yes (3)
.visit('/fixtures/dimensions.html?baz#bar') // yes (4)
.visit('/fixtures/dimensions.html#bar') // yes (5)
.visit('/fixtures/dimensions.html') // yes (6)
.visit('/fixtures/dimensions.html#baz') // no (6)
.visit('/fixtures/dimensions.html#') // no (6)
.then(() => {
expect(count).to.eq(6)
cy
.visit('/fixtures/generic.html?foo#bar') // yes (1)
.visit('/fixtures/generic.html?foo#foo') // no (1)
.visit('/fixtures/generic.html?bar#bar') // yes (2)
.visit('/fixtures/dimensions.html?bar#bar') // yes (3)
.visit('/fixtures/dimensions.html?baz#bar') // yes (4)
.visit('/fixtures/dimensions.html#bar') // yes (5)
.visit('/fixtures/dimensions.html') // yes (6)
.visit('/fixtures/dimensions.html#baz') // no (6)
.visit('/fixtures/dimensions.html#') // no (6)
.then(() => {
expect(count).to.eq(6)
expect(urls).to.deep.eq([
'http://localhost:3500/fixtures/generic.html?foo#bar',
'http://localhost:3500/fixtures/generic.html?bar#bar',
'http://localhost:3500/fixtures/dimensions.html?bar#bar',
'http://localhost:3500/fixtures/dimensions.html?baz#bar',
'http://localhost:3500/fixtures/dimensions.html#bar',
'http://localhost:3500/fixtures/dimensions.html',
])
})
expect(urls).to.deep.eq([
'http://localhost:3500/fixtures/generic.html?foo#bar',
'http://localhost:3500/fixtures/generic.html?bar#bar',
'http://localhost:3500/fixtures/dimensions.html?bar#bar',
'http://localhost:3500/fixtures/dimensions.html?baz#bar',
'http://localhost:3500/fixtures/dimensions.html#bar',
'http://localhost:3500/fixtures/dimensions.html',
])
})
})
}
})
// https://github.com/cypress-io/cypress/issues/1311
// TODO: fix flaky test https://github.com/cypress-io/cypress/issues/23201
@@ -1467,159 +1489,6 @@ describe('src/cy/commands/navigation', () => {
})
})
it('throws when attempting to visit a 2nd domain on different port', function (done) {
cy.on('fail', (err) => {
const { lastLog } = this
const experimentalMessage = Cypress.config('experimentalSessionAndOrigin') ? `You likely forgot to use \`cy.origin()\`:\n` : `In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:\n`
expect(err.message).to.equal(stripIndent`\
\`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.\n
${experimentalMessage}
\`cy.visit('http://localhost:3500/fixtures/generic.html')\`
\`<commands targeting http://localhost:3500 go here>\`\n
\`cy.origin('http://localhost:3501', () => {\`
\` cy.visit('http://localhost:3501/fixtures/generic.html')\`
\` <commands targeting http://localhost:3501 go here>\`
\`})\`\n
The new URL is considered a different origin because the following parts of the URL are different:\n
> port\n
You may only \`cy.visit()\` same-origin URLs within a single test.\n
The previous URL you visited was:\n
> 'http://localhost:3500'\n
You're attempting to visit this URL:\n
> 'http://localhost:3501'`)
expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain')
assertLogLength(this.logs, 2)
expect(lastLog.get('error')).to.eq(err)
done()
})
cy.visit('http://localhost:3500/fixtures/generic.html')
cy.visit('http://localhost:3501/fixtures/generic.html')
// If experimentalSessionAndOrigin is enabled this is no longer an error
if (Cypress.config('experimentalSessionAndOrigin')) {
done()
}
})
it('throws when attempting to visit a 2nd domain on different protocol', function (done) {
cy.on('fail', (err) => {
const { lastLog } = this
const experimentalMessage = Cypress.config('experimentalSessionAndOrigin') ? `You likely forgot to use \`cy.origin()\`:\n` : `In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:\n`
expect(err.message).to.equal(stripIndent`\
\`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.\n
${experimentalMessage}
\`cy.visit('http://localhost:3500/fixtures/generic.html')\`
\`<commands targeting http://localhost:3500 go here>\`\n
\`cy.origin('https://localhost:3502', () => {\`
\` cy.visit('https://localhost:3502/fixtures/generic.html')\`
\` <commands targeting https://localhost:3502 go here>\`
\`})\`\n
The new URL is considered a different origin because the following parts of the URL are different:\n
> protocol, port\n
You may only \`cy.visit()\` same-origin URLs within a single test.\n
The previous URL you visited was:\n
> 'http://localhost:3500'\n
You're attempting to visit this URL:\n
> 'https://localhost:3502'`)
expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain')
assertLogLength(this.logs, 2)
expect(lastLog.get('error')).to.eq(err)
done()
})
cy.visit('http://localhost:3500/fixtures/generic.html')
cy.visit('https://localhost:3502/fixtures/generic.html')
// If experimentalSessionAndOrigin is enabled this is no longer an error
if (Cypress.config('experimentalSessionAndOrigin')) {
done()
}
})
it('throws when attempting to visit a 2nd domain on different superdomain', function (done) {
cy.on('fail', (err) => {
const { lastLog } = this
const experimentalMessage = Cypress.config('experimentalSessionAndOrigin') ? `You likely forgot to use \`cy.origin()\`:\n` : `In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:\n`
expect(err.message).to.equal(stripIndent`\
\`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.\n
${experimentalMessage}
\`cy.visit('http://localhost:3500/fixtures/generic.html')\`
\`<commands targeting http://localhost:3500 go here>\`\n
\`cy.origin('http://www.foobar.com:3500', () => {\`
\` cy.visit('http://www.foobar.com:3500/fixtures/generic.html')\`
\` <commands targeting http://www.foobar.com:3500 go here>\`
\`})\`\n
The new URL is considered a different origin because the following parts of the URL are different:\n
> superdomain\n
You may only \`cy.visit()\` same-origin URLs within a single test.\n
The previous URL you visited was:\n
> 'http://localhost:3500'\n
You're attempting to visit this URL:\n
> 'http://www.foobar.com:3500'`)
expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain')
assertLogLength(this.logs, 2)
expect(lastLog.get('error')).to.eq(err)
done()
})
cy.visit('http://localhost:3500/fixtures/generic.html')
cy.visit('http://www.foobar.com:3500/fixtures/generic.html')
// If experimentalSessionAndOrigin is enabled this is no longer an error
if (Cypress.config('experimentalSessionAndOrigin')) {
done()
}
})
it('throws attempting to visit 2 unique ip addresses', function (done) {
cy.on('fail', (err) => {
const { lastLog } = this
const experimentalMessage = Cypress.config('experimentalSessionAndOrigin') ? `You likely forgot to use \`cy.origin()\`:\n` : `In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:\n`
expect(err.message).to.equal(stripIndent`\
\`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.\n
${experimentalMessage}
\`cy.visit('http://127.0.0.1:3500/fixtures/generic.html')\`
\`<commands targeting http://127.0.0.1:3500 go here>\`\n
\`cy.origin('http://0.0.0.0:3500', () => {\`
\` cy.visit('http://0.0.0.0:3500/fixtures/generic.html')\`
\` <commands targeting http://0.0.0.0:3500 go here>\`
\`})\`\n
The new URL is considered a different origin because the following parts of the URL are different:\n
> superdomain\n
You may only \`cy.visit()\` same-origin URLs within a single test.\n
The previous URL you visited was:\n
> 'http://127.0.0.1:3500'\n
You're attempting to visit this URL:\n
> 'http://0.0.0.0:3500'`)
expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain')
assertLogLength(this.logs, 2)
expect(lastLog.get('error')).to.eq(err)
done()
})
cy
.visit('http://127.0.0.1:3500/fixtures/generic.html')
.visit('http://0.0.0.0:3500/fixtures/generic.html')
// If experimentalSessionAndOrigin is enabled this is no longer an error
if (Cypress.config('experimentalSessionAndOrigin')) {
done()
}
})
it('displays loading_network_failed when _resolveUrl throws', function (done) {
const err1 = new Error('connect ECONNREFUSED 127.0.0.1:64646')
@@ -2231,42 +2100,6 @@ describe('src/cy/commands/navigation', () => {
.get('#does-not-exist', { timeout: 200 }).should('have.class', 'foo')
})
it('displays cross origin failures when navigating to a cross origin', { pageLoadTimeout: 3000 }, function (done) {
cy.on('fail', (err) => {
const { lastLog } = this
const error = Cypress.isBrowser('firefox') ? 'Permission denied to get property "href" on cross-origin object' : 'Blocked a frame with origin "http://localhost:3500" from accessing a cross-origin frame.'
// When the experimentalSessionAndOrigin feature is disabled, we will immediately and display this message.
expect(err.message).to.contain(stripIndent`\
Cypress detected a cross origin error happened on page load:\n
> ${error}\n
Before the page load, you were bound to the origin:\n
> http://localhost:3500\n
A cross origin error happens when your application navigates to a new URL which does not match the origin above.\n
A new URL does not match the origin if the 'protocol', 'port' (if specified), and/or 'host' are different.\n
Cypress does not allow you to navigate to a different origin URL within a single test.\n
You may need to restructure some of your test code to avoid this problem.\n
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false }`)
expect(err.message).to.contain(`packages/driver/cypress.config.ts`)
expect(err.docsUrl).to.eq('https://on.cypress.io/cross-origin-violation')
assertLogLength(this.logs, 7)
expect(lastLog.get('error')).to.eq(err)
done()
})
cy.visit('/fixtures/primary-origin.html')
cy.get('a[data-cy="cross-origin-secondary-link"]').click()
// If experimentalSessionAndOrigin is enabled this is no longer an error
if (Cypress.config('experimentalSessionAndOrigin')) {
done()
}
})
return null
})
})
@@ -2689,103 +2522,101 @@ describe('src/cy/commands/navigation', () => {
})
})
if (Cypress.config('experimentalSessionAndOrigin')) {
describe('filters page load events when going back with window navigation when testIsolation=strict', () => {
// https://github.com/cypress-io/cypress/issues/19230
it('when going back with window navigation', () => {
const emit = cy.spy(Cypress, 'emit').log(false).withArgs('navigation:changed')
describe('filters page load events when going back with window navigation when testIsolation=strict', () => {
// https://github.com/cypress-io/cypress/issues/19230
it('when going back with window navigation', () => {
const emit = cy.spy(Cypress, 'emit').log(false).withArgs('navigation:changed')
cy
.visit('/fixtures/generic.html')
.get('#hashchange').click()
.window().then((win) => {
cy
.visit('/fixtures/generic.html')
.get('#hashchange').click()
.window().then((win) => {
return new Promise((resolve) => {
cy.once('navigation:changed', resolve)
win.history.back()
}).then(() => {
return new Promise((resolve) => {
cy.once('navigation:changed', resolve)
win.history.back()
}).then(() => {
return new Promise((resolve) => {
cy.once('navigation:changed', resolve)
win.history.forward()
})
})
})
cy.get('#dimensions').click()
.window().then((win) => {
return new Promise((resolve) => {
cy.on('navigation:changed', (event) => {
if (event.includes('(load)')) {
resolve()
}
})
win.history.back()
})
.then(() => {
return new Promise((resolve) => {
cy.on('navigation:changed', resolve)
win.history.back()
})
})
.then(() => {
expect(emit.getCall(0)).to.be.calledWith(
'navigation:changed',
'page navigation event (before:load)',
)
expect(emit.getCall(1)).to.be.calledWith(
'navigation:changed',
'page navigation event (load)',
)
expect(emit.getCall(2)).to.be.calledWith(
'navigation:changed',
'hashchange',
)
expect(emit.getCall(3)).to.be.calledWithMatch(
'navigation:changed',
'hashchange',
)
expect(emit.getCall(4)).to.be.calledWithMatch(
'navigation:changed',
'hashchange',
)
expect(emit.getCall(5)).to.be.calledWithMatch(
'navigation:changed',
'page navigation event (before:load)',
)
expect(emit.getCall(6)).to.be.calledWith(
'navigation:changed',
'page navigation event (load)',
)
expect(emit.getCall(7)).to.be.calledWith(
'navigation:changed',
'page navigation event (before:load)',
)
expect(emit.getCall(8)).to.be.calledWith(
'navigation:changed',
'page navigation event (load)',
)
expect(emit.getCall(9)).to.be.calledWith(
'navigation:changed',
'hashchange',
)
expect(emit.callCount).to.eq(10)
win.history.forward()
})
})
})
cy.get('#dimensions').click()
.window().then((win) => {
return new Promise((resolve) => {
cy.on('navigation:changed', (event) => {
if (event.includes('(load)')) {
resolve()
}
})
win.history.back()
})
.then(() => {
return new Promise((resolve) => {
cy.on('navigation:changed', resolve)
win.history.back()
})
})
.then(() => {
expect(emit.getCall(0)).to.be.calledWith(
'navigation:changed',
'page navigation event (before:load)',
)
expect(emit.getCall(1)).to.be.calledWith(
'navigation:changed',
'page navigation event (load)',
)
expect(emit.getCall(2)).to.be.calledWith(
'navigation:changed',
'hashchange',
)
expect(emit.getCall(3)).to.be.calledWithMatch(
'navigation:changed',
'hashchange',
)
expect(emit.getCall(4)).to.be.calledWithMatch(
'navigation:changed',
'hashchange',
)
expect(emit.getCall(5)).to.be.calledWithMatch(
'navigation:changed',
'page navigation event (before:load)',
)
expect(emit.getCall(6)).to.be.calledWith(
'navigation:changed',
'page navigation event (load)',
)
expect(emit.getCall(7)).to.be.calledWith(
'navigation:changed',
'page navigation event (before:load)',
)
expect(emit.getCall(8)).to.be.calledWith(
'navigation:changed',
'page navigation event (load)',
)
expect(emit.getCall(9)).to.be.calledWith(
'navigation:changed',
'hashchange',
)
expect(emit.callCount).to.eq(10)
})
})
})
}
})
it('logs url changed event', () => {
cy
@@ -746,50 +746,6 @@ describe('cy.session', { retries: 0 }, () => {
return null
})
it('throws error when experimentalSessionAndOrigin not enabled', { experimentalSessionAndOrigin: false, experimentalSessionSupport: false }, (done) => {
cy.once('fail', (err) => {
expect(lastSessionLog).to.eq(lastLog)
expect(lastSessionLog.get('error')).to.eq(err)
expect(lastSessionLog.get('state')).to.eq('failed')
expect(err.message).to.eq('`cy.session()` requires enabling the `experimentalSessionAndOrigin` flag.')
expect(err.docsUrl).to.eq('https://on.cypress.io/session')
done()
})
cy.session('sessions-not-enabled')
})
it('throws error when experimentalSessionSupport is enabled through test config', { experimentalSessionAndOrigin: false, experimentalSessionSupport: true }, (done) => {
cy.once('fail', (err) => {
expect(lastSessionLog).to.eq(lastLog)
expect(lastSessionLog.get('error')).to.eq(err)
expect(lastSessionLog.get('state')).to.eq('failed')
expect(err.message).to.eq('\`cy.session()\` requires enabling the \`experimentalSessionAndOrigin\` flag. The \`experimentalSessionSupport\` flag was enabled but was removed in Cypress version 9.6.0.')
expect(err.docsUrl).to.eq('https://on.cypress.io/session')
done()
})
cy.session('sessions-not-enabled')
})
it('throws error when experimentalSessionSupport is enabled through Cypress.config', { experimentalSessionAndOrigin: false }, (done) => {
Cypress.config('experimentalSessionSupport', true)
cy.once('fail', (err) => {
Cypress.config('experimentalSessionSupport', false)
expect(lastSessionLog).to.eq(lastLog)
expect(lastLog.get('error')).to.eq(err)
expect(lastLog.get('state')).to.eq('failed')
expect(err.message).to.eq('\`cy.session()\` requires enabling the \`experimentalSessionAndOrigin\` flag. The \`experimentalSessionSupport\` flag was enabled but was removed in Cypress version 9.6.0.')
expect(err.docsUrl).to.eq('https://on.cypress.io/session')
done()
})
cy.session('sessions-not-enabled')
})
it('throws when sessionId argument was not provided', function (done) {
cy.once('fail', (err) => {
expect(lastSessionLog).to.eq(lastLog)
@@ -1,4 +1,3 @@
const { stripIndent } = require('common-tags')
import { findCrossOriginLogs } from '../../../../support/utils'
context('cy.origin navigation', { browser: '!webkit' }, () => {
@@ -195,35 +194,6 @@ context('cy.origin navigation', { browser: '!webkit' }, () => {
})
})
// @ts-ignore
it('informs user to use cy.origin with experimental flag off', { experimentalSessionAndOrigin: false }, (done) => {
cy.on('fail', (e) => {
expect(e.message).to.equal(stripIndent`\
\`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.\n
In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:\n
\`cy.visit('http://localhost:3500/fixtures/primary-origin.html')\`
\`<commands targeting http://localhost:3500 go here>\`\n
\`cy.origin('http://www.foobar.com:3500', () => {\`
\` cy.visit('http://www.foobar.com:3500/fixtures/dom.html')\`
\` <commands targeting http://www.foobar.com:3500 go here>\`
\`})\`\n
The new URL is considered a different origin because the following parts of the URL are different:\n
> superdomain\n
You may only \`cy.visit()\` same-origin URLs within a single test.\n
The previous URL you visited was:\n
> 'http://localhost:3500'\n
You're attempting to visit this URL:\n
> 'http://www.foobar.com:3500'`)
done()
})
cy.visit('/fixtures/primary-origin.html')
// this call should error since we can't visit a cross-origin
cy.visit('http://www.foobar.com:3500/fixtures/dom.html')
})
it('supports the query string option', () => {
cy.visit('/fixtures/primary-origin.html')
@@ -1,4 +1,4 @@
describe('Cookie Behavior with experimentalSessionAndOrigin=true', { browser: '!webkit' }, () => {
describe('Cookie Behavior', { browser: '!webkit' }, () => {
const makeRequest = (
win: Cypress.AUTWindow,
url: string,
@@ -917,7 +917,6 @@ describe('Cookie Behavior with experimentalSessionAndOrigin=true', { browser: '!
})
// without cy.origin means the AUT has the same origin as top
// TODO: In the future, this test should be run with the experimentalSessionAndOrigin=true and experimentalSessionAndOrigin=false
describe('w/o cy.origin', () => {
describe('same site / same origin', () => {
describe('XMLHttpRequest', () => {
@@ -2,7 +2,6 @@ import CryptoJS from 'crypto-js'
import type { TemplateExecutor } from 'lodash'
// NOTE: in order to run these tests, the following config flags need to be set
// experimentalSessionAndOrigin=true
// experimentalModifyObstructiveThirdPartyCode=true
describe('Integrity Preservation', { browser: '!webkit' }, () => {
// Add common SRI hashes used when setting script/link integrity.
@@ -261,18 +261,6 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})
describe('errors', () => {
// @ts-ignore
it('errors if experimental flag is not enabled', { experimentalSessionAndOrigin: false }, (done) => {
cy.on('fail', (err) => {
expect(err.message).to.equal('`cy.origin()` requires enabling the experimentalSessionAndOrigin flag')
done()
})
// @ts-ignore
cy.origin()
})
it('errors if passed a non-string for the origin argument', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.equal('`cy.origin()` requires the first argument to be either a url (`https://www.example.com/path`) or a domain name (`example.com`). Query parameters are not allowed. You passed: ``')
+3 -2
View File
@@ -348,8 +348,9 @@ httpPorts.forEach((port) => {
})
})
// Have two HTTPS ports in order to test same-site cookie behavior in `cookie_behavior.cy.ts` for experimentalSessionAndOrigin
// Cookies can be same site if the port is different, and we need a way to test this E2E style to make sure we implement cookie handling correctly
// Have two HTTPS ports in order to test same-site cookie behavior in `cookie_behavior.cy.ts`
// Cookies can be same site if the port is different, and we need a way to test this E2E
// style to make sure we implement cookie handling correctly
httpsPorts.forEach((port) => {
const httpsApp = createApp(port)
const httpsServer = httpsProxy.httpsServer(httpsApp)
-2
View File
@@ -7,8 +7,6 @@
"clean-deps": "rimraf node_modules",
"cypress:open": "node ../../scripts/cypress open",
"cypress:run": "node ../../scripts/cypress run --spec \"cypress/e2e/*/*\",\"cypress/e2e/*/!(origin|sessions)/**/*\"",
"cypress:open-experimentalSessionAndOrigin": "node ../../scripts/cypress open --config experimentalSessionAndOrigin=true,experimentalModifyObstructiveThirdPartyCode=true",
"cypress:run-experimentalSessionAndOrigin": "node ../../scripts/cypress run --config experimentalSessionAndOrigin=true,experimentalModifyObstructiveThirdPartyCode=true",
"postinstall": "patch-package",
"start": "node -e 'console.log(require(`chalk`).red(`\nError:\n\tRunning \\`yarn start\\` is no longer needed for driver/cypress tests.\n\tWe now automatically spawn the server in e2e.setupNodeEvents config.\n\tChanges to the server will be watched and reloaded automatically.`))'"
},
@@ -4,7 +4,7 @@ export const patchFetch = (Cypress: Cypress.Cypress, window) => {
// if fetch is available in the browser, or is polyfilled by whatwg fetch
// intercept method calls and add cypress headers to determine cookie applications in the proxy
// for simulated top. @see https://github.github.io/fetch/ for default options
if (!Cypress.config('experimentalSessionAndOrigin') || !window.fetch) {
if (!window.fetch) {
return
}
@@ -1,13 +1,7 @@
import { captureFullRequestUrl } from './utils'
// intercept method calls and add cypress headers to determine cookie applications in the proxy for simulated top
export const patchXmlHttpRequest = (Cypress: Cypress.Cypress, window: Window) => {
// intercept method calls and add cypress headers to determine cookie applications in the proxy
// for simulated top
if (!Cypress.config('experimentalSessionAndOrigin')) {
return
}
const originalXmlHttpRequestOpen = window.XMLHttpRequest.prototype.open
const originalXmlHttpRequestSend = window.XMLHttpRequest.prototype.send
@@ -174,19 +174,6 @@ export default function (Commands, Cypress, cy, state, config) {
}
}
// TODO: https://github.com/cypress-io/cypress/issues/23093
// Cypress sessions will clear cookies on its own before each test.
// Once experimentalSessionAndOrigin is made GA, remove this logic. Leave clearing
// session data (cookies / local storage / session storage) to reset functionality.
if (!Cypress.config('experimentalSessionAndOrigin')) {
// TODO: handle failure here somehow
// maybe by tapping into the Cypress reset
// stuff, or handling this in the runner itself?
Cypress.on('test:before:run:async', () => {
return getAndClear()
})
}
return Commands.addAll({
getCookie (name, userOptions: Partial<Cypress.Loggable & Cypress.Timeoutable> = {}) {
const options: InternalGetCookieOptions = _.defaults({}, userOptions, {
@@ -21,22 +21,6 @@ const clearLocalStorage = (state, keys) => {
}
export default (Commands, Cypress, cy, state) => {
// TODO: Cypress sessions will clear local storage on its own before each test.
// Once experimentalSessionAndOrigin is made GA, remove this logic. Leave clearing
// session data (cookies / local storage / session storage) to reset functionality
if (!Cypress.config('experimentalSessionAndOrigin')) {
// this MUST be prepended before anything else
Cypress.prependListener('test:before:run', () => {
try {
// this may fail if the current
// window is bound to another origin
return clearLocalStorage(state, [])
} catch (error) {
return null
}
})
}
Commands.addAll({
clearLocalStorage (keys, options: Partial<Cypress.Loggable> = {}) {
if (_.isPlainObject(keys)) {
+5 -55
View File
@@ -35,11 +35,9 @@ const reset = (test: any = {}) => {
// before each test run!
previouslyVisitedLocation = undefined
const { experimentalSessionAndOrigin, testIsolation } = Cypress.config()
// make sure we reset that we haven't visited about blank again
// strict test isolation resets the navigation history for us.
hasVisitedAboutBlank = experimentalSessionAndOrigin && testIsolation === 'strict'
hasVisitedAboutBlank = Cypress.config('testIsolation') === 'strict'
currentlyVisitingAboutBlank = false
@@ -64,40 +62,6 @@ const timedOutWaitingForPageLoad = (ms, log) => {
})
}
// TODO: remove with experimentalSessionAndOrigin. Fixed with: https://github.com/cypress-io/cypress/issues/21471
const cannotVisitDifferentOrigin = ({ remote, existing, originalUrl, previouslyVisitedLocation, log, isCrossOriginSpecBridge = false }) => {
const differences: string[] = []
if (remote.protocol !== existing.protocol) {
differences.push('protocol')
}
if (remote.port !== existing.port) {
differences.push('port')
}
if (remote.superDomain !== existing.superDomain) {
differences.push('superdomain')
}
const errOpts = {
onFail: log,
args: {
differences: differences.join(', '),
previousUrl: previouslyVisitedLocation,
attemptedUrl: remote,
originalUrl,
isCrossOriginSpecBridge,
experimentalSessionAndOrigin: Cypress.config('experimentalSessionAndOrigin'),
},
errProps: {
isCrossOrigin: true,
},
}
$errUtils.throwErrByPath('visit.cannot_visit_different_origin', errOpts)
}
const specifyFileByRelativePath = (url, log) => {
$errUtils.throwErrByPath('visit.specify_file_by_relative_path', {
onFail: log,
@@ -1084,13 +1048,12 @@ export default (Commands, Cypress, cy, state, config) => {
remote = $Location.create(url)
// if the super domain origin currently matches
// or if we have previously visited a location or are a spec bridge
// if the origin currently matches,
// or we have previously visited a location,
// or are a spec bridge,
// then go ahead and change the iframe's src
// we use the super domain origin as we can interact with subdomains based document.domain set to the super domain origin
if (remote.superDomainOrigin === existing.superDomainOrigin
|| ((previouslyVisitedLocation || Cypress.isCrossOriginSpecBridge) && Cypress.config('experimentalSessionAndOrigin'))
) {
if (remote.superDomainOrigin === existing.superDomainOrigin || previouslyVisitedLocation || Cypress.isCrossOriginSpecBridge) {
if (!previouslyVisitedLocation) {
previouslyVisitedLocation = remote
}
@@ -1103,19 +1066,6 @@ export default (Commands, Cypress, cy, state, config) => {
})
}
// if we've already cy.visit'ed in the test and we are visiting a new origin,
// throw an error, else we'd be in a endless loop,
// we also need to disable retries to prevent the endless loop
if (previouslyVisitedLocation) {
// _retries is `private`. We're not using `retries()` method here because it breaks some tests.
// @ts-ignore
$utils.getTestFromRunnable(state('runnable'))._retries = 0
const params = { remote, existing, originalUrl, previouslyVisitedLocation, log: options._log }
return cannotVisitDifferentOrigin(params)
}
// tell our backend we're changing origins
// TODO: add in other things we want to preserve
// state for like scrollTop
@@ -41,10 +41,6 @@ export default (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: State
// origin run, so it can't have its own timeout
cy.clearTimeout()
if (!config('experimentalSessionAndOrigin')) {
$errUtils.throwErrByPath('origin.experiment_not_enabled')
}
let options
let callbackFn
@@ -22,20 +22,6 @@ type SessionData = Cypress.Commands.Session.SessionData
*/
export default function (Commands, Cypress, cy) {
// @ts-ignore
function throwIfNoSessionSupport () {
if (!Cypress.config('experimentalSessionAndOrigin')) {
$errUtils.throwErrByPath('sessions.experimentNotEnabled', {
args: {
// determine if using experimental session opt-in flag (removed in 9.6.0) to
// generate a coherent error message
experimentalSessionSupport: Cypress.config('experimentalSessionSupport'),
},
})
}
}
const sessionsManager = new SessionsManager(Cypress, cy)
const sessions = sessionsManager.sessions
@@ -48,22 +34,16 @@ export default function (Commands, Cypress, cy) {
})
Cypress.on('test:before:run:async', () => {
if (Cypress.config('experimentalSessionAndOrigin')) {
const clearPage = Cypress.config('testIsolation') === 'strict' ? navigateAboutBlank(false) : new Cypress.Promise.resolve()
const clearPage = (Cypress.config('testIsolation') === 'strict' && Cypress.testingType === 'e2e') ? navigateAboutBlank(false) : new Cypress.Promise.resolve()
return clearPage
.then(() => sessions.clearCurrentSessionData())
.then(() => Cypress.backend('reset:rendered:html:origins'))
}
return
return clearPage
.then(() => sessions.clearCurrentSessionData())
.then(() => Cypress.backend('reset:rendered:html:origins'))
})
})
Commands.addAll({
session (id: string | object, setup?: () => void, options: Cypress.SessionOptions = { cacheAcrossSpecs: false }) {
throwIfNoSessionSupport()
if (!id || !_.isString(id) && !_.isObject(id)) {
$errUtils.throwErrByPath('sessions.session.wrongArgId')
}
+1 -5
View File
@@ -47,11 +47,7 @@ export const create = (state: StateFunc) => ({
autLocation = $Location.create(remoteUrl)
} catch (e) {
if (Cypress.config('experimentalSessionAndOrigin')) {
autLocation = await getRemoteLocationFromCrossOriginWindow(autWindow)
} else {
autLocation = $Location.create('')
}
autLocation = await getRemoteLocationFromCrossOriginWindow(autWindow)
}
return autLocation
-4
View File
@@ -556,10 +556,6 @@ export class $Cy extends EventEmitter2 implements ITimeouts, IStability, IAssert
autWindow.location.href
isRunnerAbleToCommunicateWithAUT = true
} catch (err: any) {
if (!this.config('experimentalSessionAndOrigin') && err.name === 'SecurityError') {
throw err
}
isRunnerAbleToCommunicateWithAUT = false
}
@@ -1116,9 +1116,6 @@ export default {
origin: {
docsUrl: 'https://on.cypress.io/origin',
experiment_not_enabled: {
message: `${cmd('origin')} requires enabling the experimentalSessionAndOrigin flag`,
},
invalid_url_argument: {
message: `${cmd('origin')} requires the first argument to be either a url (\`https://www.example.com/path\`) or a domain name (\`example.com\`). Query parameters are not allowed. You passed: \`{{arg}}\``,
},
@@ -1674,20 +1671,6 @@ export default {
validate_callback_false: {
message: 'Your `cy.session` **validate** callback {{reason}}.',
},
experimentNotEnabled ({ experimentalSessionSupport }) {
if (experimentalSessionSupport) {
return {
message: stripIndent`
${cmd('session')} requires enabling the \`experimentalSessionAndOrigin\` flag. The \`experimentalSessionSupport\` flag was enabled but was removed in Cypress version 9.6.0.`,
docsUrl: 'https://on.cypress.io/session',
}
}
return {
message: `${cmd('session')} requires enabling the \`experimentalSessionAndOrigin\` flag.`,
docsUrl: 'https://on.cypress.io/session',
}
},
session: {
duplicateId ({ id, hasUniqSetupDefinition, hasUniqValidateDefinition, hasUniqPersistence }) {
const differences: string[] = []
@@ -2210,43 +2193,6 @@ export default {
\`url\` from the \`url\` parameter: {{url}}`,
docsUrl: 'https://on.cypress.io/visit',
},
cannot_visit_different_origin (args) {
return {
message: stripIndent`\
${cmd('visit')} failed because you are attempting to visit a URL that is of a different origin.
${args.experimentalSessionAndOrigin ? `You likely forgot to use ${cmd('origin')}:` : `In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use ${cmd('origin')}:` }
${args.isCrossOriginSpecBridge ?
`\`cy.origin('${args.previousUrl.origin}', () => {\`
\` cy.visit('${args.previousUrl}')\`
\` <commands targeting ${args.previousUrl.origin} go here>\`
\`})\`` :
`\`cy.visit('${args.previousUrl}')\`
\`<commands targeting ${args.previousUrl.origin} go here>\``
}
\`cy.origin('${args.attemptedUrl.origin}', () => {\`
\` cy.visit('${args.originalUrl}')\`
\` <commands targeting ${args.attemptedUrl.origin} go here>\`
\`})\`
The new URL is considered a different origin because the following parts of the URL are different:
> {{differences}}
You may only ${cmd('visit')} same-origin URLs within ${args.isCrossOriginSpecBridge ? cmd('origin') : 'a single test'}.
The previous URL you visited was:
> '${args.previousUrl.origin}'
You're attempting to visit this URL:
> '${args.attemptedUrl.origin}'`,
docsUrl: 'https://on.cypress.io/cannot-visit-different-origin-domain',
}
},
loading_network_failed: stripIndent`\
${cmd('visit')} failed trying to load:
+1 -1
View File
@@ -373,7 +373,7 @@ export class Log {
this.set('next', null)
}
if (this.config('experimentalSessionAndOrigin') && !Cypress.isCrossOriginSpecBridge) {
if (!Cypress.isCrossOriginSpecBridge) {
const activeSpecBridgeOriginIfApplicable = this.state('currentActiveOrigin') || undefined
// @ts-ignore
const { origin: originThatIsSoonToBeOrIsActive } = Cypress.Location.create(this.state('url'))
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">The <span style="color:#e5e510">experimentalSessionAndOrigin<span style="color:#e05561"> configuration option was removed in Cypress version 11.0.0.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">You can safely remove this option from your config.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">https://on.cypress.io/session<span style="color:#e6e6e6">
<span style="color:#e05561">https://on.cypress.io/origin<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -34,7 +34,9 @@
</style>
</head>
<body><pre><span style="color:#e05561">The <span style="color:#e5e510">experimentalSessionSupport<span style="color:#e05561"> configuration option was removed in Cypress version 9.6.0 and replaced with <span style="color:#e5e510">experimentalSessionAndOrigin<span style="color:#e05561">. Please update your config to use <span style="color:#e5e510">experimentalSessionAndOrigin<span style="color:#e05561"> instead.<span style="color:#e6e6e6">
<body><pre><span style="color:#e05561">The <span style="color:#e5e510">experimentalSessionSupport<span style="color:#e05561"> configuration option was removed in Cypress version 9.6.0.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">You can safely remove this option from your config.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">https://on.cypress.io/session<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
+12 -1
View File
@@ -1059,10 +1059,21 @@ export const AllCypressErrors = {
},
EXPERIMENTAL_SESSION_SUPPORT_REMOVED: () => {
return errTemplate`\
The ${fmt.highlight(`experimentalSessionSupport`)} configuration option was removed in ${fmt.cypressVersion(`9.6.0`)} and replaced with ${fmt.highlight(`experimentalSessionAndOrigin`)}. Please update your config to use ${fmt.highlight(`experimentalSessionAndOrigin`)} instead.
The ${fmt.highlight(`experimentalSessionSupport`)} configuration option was removed in ${fmt.cypressVersion(`9.6.0`)}.
You can safely remove this option from your config.
https://on.cypress.io/session`
},
EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED: () => {
return errTemplate`\
The ${fmt.highlight(`experimentalSessionAndOrigin`)} configuration option was removed in ${fmt.cypressVersion(`11.0.0`)}.
You can safely remove this option from your config.
https://on.cypress.io/session
https://on.cypress.io/origin`
},
EXPERIMENTAL_SHADOW_DOM_REMOVED: () => {
return errTemplate`\
The ${fmt.highlight(`experimentalShadowDomSupport`)} configuration option was removed in ${fmt.cypressVersion(`5.2.0`)}. It is no longer necessary when utilizing the ${fmt.highlightSecondary(`includeShadowDom`)} option.
@@ -996,6 +996,11 @@ describe('visual error templates', () => {
default: [],
}
},
EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED: () => {
return {
default: [],
}
},
EXPERIMENTAL_SHADOW_DOM_REMOVED: () => {
return {
default: [],
+1 -4
View File
@@ -159,10 +159,7 @@ const connect = function (host, path, extraOpts) {
// Non-Firefox browsers use CDP for these instead
if (isFirefox) {
listenToDownloads()
if (config.experimentalSessionAndOrigin) {
listenToOnBeforeHeaders()
}
listenToOnBeforeHeaders()
}
})
@@ -274,18 +274,6 @@ describe('app/background', () => {
})
context('add header to aut iframe requests', () => {
const withExperimentalFlagOn = {
experimentalSessionAndOrigin: true,
}
it('does not listen to `onBeforeSendHeaders` if experimental flag is off', async function () {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect()
expect(browser.webRequest.onBeforeSendHeaders.addListener).not.to.be.called
})
it('does not add header if it is the top frame', async function () {
const details = {
parentFrameId: -1,
@@ -293,7 +281,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
@@ -307,7 +295,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
@@ -322,7 +310,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
@@ -338,7 +326,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
expect(result).to.deep.equal({ requestHeaders: [] })
@@ -356,7 +344,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
expect(result).to.deep.equal({
@@ -385,7 +373,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
expect(result).to.deep.equal({
@@ -414,7 +402,7 @@ describe('app/background', () => {
sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details)
expect(result).to.not.deep.equal({
@@ -432,7 +420,7 @@ describe('app/background', () => {
const onBeforeSendHeaders = sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener')
await this.connect(withExperimentalFlagOn)
await this.connect()
expect(onBeforeSendHeaders).not.to.be.called
})
@@ -97,11 +97,6 @@
"from": "default",
"field": "experimentalSourceRewriting"
},
{
"value": false,
"from": "default",
"field": "experimentalSessionAndOrigin"
},
{
"value": false,
"from": "default",
@@ -491,10 +491,6 @@
"name": "Interactive run events",
"description": "Allows listening to the [`before:run`](https://on.cypress.io/before-run), [`after:run`](https://on.cypress.io/after-run), [`before:spec`](https://on.cypress.io/before-spec), and [`after:spec`](https://on.cypress.io/after-spec) events in plugins during interactive mode."
},
"experimentalSessionAndOrigin": {
"name": "Cross-origin and session",
"description": "Enables cross-origin and improved session support, including the [`cy.origin()`](https://on.cypress.io/origin) and [`cy.session()`](https://on.cypress.io/session) commands."
},
"experimentalModifyObstructiveThirdPartyCode": {
"name": "Modify obstructive third party code",
"description": "Applies `modifyObstructiveCode` to third party `.html` and `.js`, removes subresource integrity, and modifies the user agent in Electron."
+1 -1
View File
@@ -291,7 +291,7 @@ union CloudProjectSpecFlakyResult =
type CloudProjectSpecFlakyStatus {
"""
URL linking to the flaky data in the Cypress Dashboard for this spec
URL linking to the flaky data in the Cypress dashboard for this spec
"""
dashboardUrl: String
+2 -1
View File
@@ -264,7 +264,7 @@ type CloudProjectSpec implements Node {
union CloudProjectSpecFlakyResult = CloudFeatureNotEnabled | CloudProjectSpecFlakyStatus
type CloudProjectSpecFlakyStatus {
"""URL linking to the flaky data in the Cypress Dashboard for this spec"""
"""URL linking to the flaky data in the Cypress dashboard for this spec"""
dashboardUrl: String
"""Number of flaky runs from the considered runs"""
@@ -785,6 +785,7 @@ enum ErrorTypeEnum {
EXPERIMENTAL_NETWORK_STUBBING_REMOVED
EXPERIMENTAL_RUN_EVENTS_REMOVED
EXPERIMENTAL_SAMESITE_REMOVED
EXPERIMENTAL_SESSION_AND_ORIGIN_REMOVED
EXPERIMENTAL_SESSION_SUPPORT_REMOVED
EXPERIMENTAL_SHADOW_DOM_REMOVED
EXPERIMENTAL_SINGLE_TAB_RUN_MODE
@@ -35,8 +35,7 @@ const ExtractCypressMetadataHeaders: RequestMiddleware = function () {
delete this.req.headers['x-cypress-is-xhr-or-fetch']
}
if (!this.config.experimentalSessionAndOrigin ||
!doesTopNeedToBeSimulated(this) ||
if (!doesTopNeedToBeSimulated(this) ||
// this should be unreachable, as the x-cypress-is-xhr-or-fetch header is only attached if
// the resource type is 'xhr' or 'fetch or 'true' (in the case of electron|extension).
// This is only needed for defensive purposes.
@@ -72,7 +71,7 @@ const MaybeSimulateSecHeaders: RequestMiddleware = function () {
}
const MaybeAttachCrossOriginCookies: RequestMiddleware = function () {
if (!this.config.experimentalSessionAndOrigin || !doesTopNeedToBeSimulated(this)) {
if (!doesTopNeedToBeSimulated(this)) {
return this.next()
}
@@ -157,9 +156,8 @@ const MaybeEndRequestWithBufferedResponse: RequestMiddleware = function () {
if (buffer) {
this.debug('ending request with buffered response')
// NOTE: Only inject fullCrossOrigin here if experimental is on and
// the super domain origins do not match in order to keep parity with cypress application reloads
this.res.wantsInjection = this.config.experimentalSessionAndOrigin && buffer.isCrossSuperDomainOrigin ? 'fullCrossOrigin' : 'full'
// NOTE: Only inject fullCrossOrigin here if the super domain origins do not match in order to keep parity with cypress application reloads
this.res.wantsInjection = buffer.isCrossSuperDomainOrigin ? 'fullCrossOrigin' : 'full'
return this.onResponse(buffer.response, buffer.stream)
}
@@ -261,7 +261,7 @@ const SetInjectionLevel: ResponseMiddleware = function () {
const isCrossSuperDomainOrigin = !reqMatchesSuperDomainOrigin(this.req, this.remoteStates.getPrimary())
const isAUTFrame = this.req.isAUTFrame
if (this.config.experimentalSessionAndOrigin && isCrossSuperDomainOrigin && isAUTFrame && (isHTML || isRenderedHTML)) {
if (isCrossSuperDomainOrigin && isAUTFrame && (isHTML || isRenderedHTML)) {
this.debug('- cross origin injection')
return 'fullCrossOrigin'
@@ -412,7 +412,7 @@ const MaybeCopyCookiesFromIncomingRes: ResponseMiddleware = async function () {
}
}
if (!this.config.experimentalSessionAndOrigin || !doesTopNeedSimulating) {
if (!doesTopNeedSimulating) {
([] as string[]).concat(cookies).forEach((cookie) => {
appendCookie(cookie)
})
@@ -33,6 +33,10 @@ describe('http/request-middleware', () => {
it('removes x-cypress-is-aut-frame header when it exists, sets in on the req', async () => {
const ctx = {
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
},
req: {
headers: {
'x-cypress-is-aut-frame': 'true',
@@ -49,6 +53,10 @@ describe('http/request-middleware', () => {
it('removes x-cypress-is-aut-frame header when it does not exist, sets in on the req', async () => {
const ctx = {
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
},
req: {
headers: {},
} as Partial<CypressIncomingRequest>,
@@ -63,6 +71,10 @@ describe('http/request-middleware', () => {
it('removes x-cypress-is-xhr-or-fetch header when it exists', async () => {
const ctx = {
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(true),
},
req: {
headers: {
'x-cypress-is-xhr-or-fetch': 'true',
@@ -78,6 +90,10 @@ describe('http/request-middleware', () => {
it('removes x-cypress-is-xhr-or-fetch header when it does not exist', async () => {
const ctx = {
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
},
req: {
headers: {},
} as Partial<CypressIncomingRequest>,
@@ -89,30 +105,8 @@ describe('http/request-middleware', () => {
})
})
it('does not set requestedWith or credentialLevel on the request if the the experimentalSessionAndOrigin flag is off', async () => {
const ctx = {
config: {
experimentalSessionAndOrigin: false,
},
req: {
headers: {
'x-cypress-is-xhr-or-fetch': 'true',
},
} as Partial<CypressIncomingRequest>,
}
await testMiddleware([ExtractCypressMetadataHeaders], ctx)
.then(() => {
expect(ctx.req.requestedWith).not.to.exist
expect(ctx.req.credentialsLevel).not.to.exist
})
})
it('does not set requestedWith or credentialLevel on the request if top does NOT need to be simulated', async () => {
const ctx = {
config: {
experimentalSessionAndOrigin: true,
},
getAUTUrl: sinon.stub().returns(undefined),
req: {
headers: {
@@ -130,9 +124,6 @@ describe('http/request-middleware', () => {
it('does not set requestedWith or credentialLevel on the request if x-cypress-is-xhr-or-fetch has invalid values', async () => {
const ctx = {
config: {
experimentalSessionAndOrigin: true,
},
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
@@ -154,9 +145,6 @@ describe('http/request-middleware', () => {
// CDP can determine whether or not the request is xhr | fetch, but the extension or electron cannot
it('provides resourceTypeAndCredentialManager with resourceType if able to determine from header (xhr)', async () => {
const ctx = {
config: {
experimentalSessionAndOrigin: true,
},
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
@@ -181,9 +169,6 @@ describe('http/request-middleware', () => {
// CDP can determine whether or not the request is xhr | fetch, but the extension or electron cannot
it('provides resourceTypeAndCredentialManager with resourceType if able to determine from header (fetch)', async () => {
const ctx = {
config: {
experimentalSessionAndOrigin: true,
},
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
@@ -207,9 +192,6 @@ describe('http/request-middleware', () => {
it('sets the resourceType and credentialsLevel on the request from whatever is returned by resourceTypeAndCredentialManager if conditions apply', async () => {
const ctx = {
config: {
experimentalSessionAndOrigin: true,
},
getAUTUrl: sinon.stub().returns('http://localhost:8080'),
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
@@ -314,16 +296,6 @@ describe('http/request-middleware', () => {
describe('MaybeAttachCrossOriginCookies', () => {
const { MaybeAttachCrossOriginCookies } = RequestMiddleware
it('is a noop if experimental flag is off', async () => {
const ctx = await getContext()
ctx.config.experimentalSessionAndOrigin = false
await testMiddleware([MaybeAttachCrossOriginCookies], ctx)
expect(ctx.req.headers['cookie']).to.equal('request=cookie')
})
it('is a noop if no current AUT URL', async () => {
const ctx = await getContext()
@@ -531,7 +503,6 @@ describe('http/request-middleware', () => {
remoteStates: {
isPrimarySuperDomainOrigin: sinon.stub().returns(false),
},
config: { experimentalSessionAndOrigin: true },
req: {
proxiedUrl: requestUrl,
isAUTFrame: true,
@@ -566,7 +537,7 @@ describe('http/request-middleware', () => {
})
})
it('sets wantsInjection to fullCrossOrigin when a cross origin request is buffered and experimentalSessionAndOrigin=true', async () => {
it('sets wantsInjection to fullCrossOrigin when a cross origin request is buffered', async () => {
const buffers = new HttpBuffers()
const buffer = { url: 'https://www.cypress.io/', isCrossSuperDomainOrigin: true } as HttpBuffer
@@ -577,9 +548,6 @@ describe('http/request-middleware', () => {
req: {
proxiedUrl: 'https://www.cypress.io/',
},
config: {
experimentalSessionAndOrigin: true,
},
res: {} as Partial<CypressOutgoingResponse>,
}
@@ -589,29 +557,6 @@ describe('http/request-middleware', () => {
})
})
it('sets wantsInjection to full when a cross origin request is buffered and experimentalSessionAndOrigin=false', async () => {
const buffers = new HttpBuffers()
const buffer = { url: 'https://www.cypress.io/', isCrossSuperDomainOrigin: true } as HttpBuffer
buffers.set(buffer)
const ctx = {
buffers,
req: {
proxiedUrl: 'https://www.cypress.io/',
},
config: {
experimentalSessionAndOrigin: false,
},
res: {} as Partial<CypressOutgoingResponse>,
}
await testMiddleware([MaybeEndRequestWithBufferedResponse], ctx)
.then(() => {
expect(ctx.res.wantsInjection).to.equal('full')
})
})
it('wantsInjection is not set when the request is not buffered', async () => {
const buffers = new HttpBuffers()
const buffer = { url: 'https://www.cypress.io/', isCrossSuperDomainOrigin: true } as HttpBuffer
@@ -220,53 +220,7 @@ describe('http/response-middleware', function () {
})
})
it('doesn\'t inject anything when html does not match origin policy and "experimentalSessionAndOrigin" config flag is NOT set to true', function () {
prepareContext({
req: {
proxiedUrl: 'http://foobar.com',
isAUTFrame: true,
cookies: {},
headers: {},
},
incomingRes: {
headers: {
'content-type': 'text/html',
},
},
})
return testMiddleware([SetInjectionLevel], ctx)
.then(() => {
expect(ctx.res.wantsInjection).to.be.false
})
})
it('injects "fullCrossOrigin" when "experimentalSessionAndOrigin" config flag is set to true for cross-origin html"', function () {
prepareContext({
req: {
proxiedUrl: 'http://foobar.com',
isAUTFrame: true,
cookies: {},
headers: {},
},
incomingRes: {
headers: {
'content-type': 'text/html',
},
},
secondaryOrigins: ['http://foobar.com'],
config: {
experimentalSessionAndOrigin: true,
},
})
return testMiddleware([SetInjectionLevel], ctx)
.then(() => {
expect(ctx.res.wantsInjection).to.equal('fullCrossOrigin')
})
})
it('injects "fullCrossOrigin" when request is in origin stack for cross-origin html"', function () {
it('injects "fullCrossOrigin" when request is cross-origin html', function () {
prepareContext({
req: {
proxiedUrl: 'http://example.com',
@@ -279,10 +233,6 @@ describe('http/response-middleware', function () {
'content-type': 'text/html',
},
},
secondaryOrigins: ['http://example.com', 'http://foobar.com'],
config: {
experimentalSessionAndOrigin: true,
},
})
return testMiddleware([SetInjectionLevel], ctx)
@@ -320,7 +270,7 @@ describe('http/response-middleware', function () {
return this.renderedHTMLOrigins
},
req: {
proxiedUrl: 'http://foobar.com',
proxiedUrl: 'http://127.0.0.1:3501/',
isAUTFrame: true,
cookies: {},
headers: {
@@ -365,10 +315,6 @@ describe('http/response-middleware', function () {
'content-type': 'text/html',
},
},
secondaryOrigins: ['http://foobar.com'],
config: {
experimentalSessionAndOrigin: true,
},
})
return testMiddleware([SetInjectionLevel], ctx)
@@ -549,11 +495,6 @@ describe('http/response-middleware', function () {
// set the primary remote state
remoteStates.set('http://127.0.0.1:3501')
// set the secondary remote states
props.secondaryOrigins?.forEach((origin) => {
remoteStates.set(origin, {}, false)
})
ctx = {
incomingRes: {
headers: {},
@@ -655,38 +596,6 @@ describe('http/response-middleware', function () {
expect(appendStub).to.be.calledWith('Set-Cookie', 'cookie=value')
})
it('is a noop in the cookie jar when experimentalSessionAndOrigin is false', async function () {
const appendStub = sinon.stub()
const cookieJar = {
getAllCookies: () => [{ key: 'cookie', value: 'value' }],
setCookie: sinon.stub(),
}
const ctx = prepareContext({
cookieJar,
res: {
append: appendStub,
},
incomingRes: {
headers: {
'set-cookie': 'cookie=value',
},
},
})
ctx.config.experimentalSessionAndOrigin = false
// a case where top would need to be simulated, but the experimental flag is off
ctx.getAUTUrl = () => 'http://www.foobar.com/index.html'
ctx.remoteStates.isPrimarySuperDomainOrigin = () => false
await testMiddleware([MaybeCopyCookiesFromIncomingRes], ctx)
expect(cookieJar.setCookie).not.to.have.been.called
expect(appendStub).to.be.calledWith('Set-Cookie', 'cookie=value')
})
describe('same-origin', () => {
['same-origin', 'include'].forEach((credentialLevel) => {
it(`sets first-party cookie context in the jar when simulating top if credentials included with fetch with credential ${credentialLevel}`, async function () {
@@ -1396,11 +1305,6 @@ describe('http/response-middleware', function () {
// set the primary remote state
remoteStates.set('http://foobar.com')
// set the secondary remote states
props.secondaryOrigins?.forEach((origin) => {
remoteStates.set(origin, {}, false)
})
remoteStates.isPrimarySuperDomainOrigin = () => false
const cookieJar = props.cookieJar || {
@@ -1427,9 +1331,6 @@ describe('http/response-middleware', function () {
return { on () {} }
},
},
config: {
experimentalSessionAndOrigin: true,
},
getCookieJar: () => cookieJar,
getAUTUrl: () => 'http://www.foobar.com/primary-origin.html',
remoteStates,
+7 -13
View File
@@ -184,7 +184,7 @@ const ffToStandardResourceTypeMap: { [ff: string]: ResourceType } = {
}
export class CdpAutomation {
private constructor (private sendDebuggerCommandFn: SendDebuggerCommand, private onFn: OnFn, private sendCloseCommandFn: SendCloseCommand, private automation: Automation, private experimentalSessionAndOrigin: boolean) {
private constructor (private sendDebuggerCommandFn: SendDebuggerCommand, private onFn: OnFn, private sendCloseCommandFn: SendCloseCommand, private automation: Automation) {
onFn('Network.requestWillBeSent', this.onNetworkRequestWillBeSent)
onFn('Network.responseReceived', this.onResponseReceived)
}
@@ -198,8 +198,8 @@ export class CdpAutomation {
await this.sendDebuggerCommandFn('Page.startScreencast', screencastOpts)
}
static async create (sendDebuggerCommandFn: SendDebuggerCommand, onFn: OnFn, sendCloseCommandFn: SendCloseCommand, automation: Automation, experimentalSessionAndOrigin: boolean): Promise<CdpAutomation> {
const cdpAutomation = new CdpAutomation(sendDebuggerCommandFn, onFn, sendCloseCommandFn, automation, experimentalSessionAndOrigin)
static async create (sendDebuggerCommandFn: SendDebuggerCommand, onFn: OnFn, sendCloseCommandFn: SendCloseCommand, automation: Automation): Promise<CdpAutomation> {
const cdpAutomation = new CdpAutomation(sendDebuggerCommandFn, onFn, sendCloseCommandFn, automation)
await sendDebuggerCommandFn('Network.enable', {
maxTotalBufferSize: 0,
@@ -277,16 +277,10 @@ export class CdpAutomation {
// be sent with a request. This standardizes it by filtering out ones
// that are secure but not on a secure context
if (this.experimentalSessionAndOrigin) {
// localhost is considered a secure context (even when http:)
// and it's required for cross origin support when visiting a secondary
// origin so that all its cookies are sent. This may be a
// breaking change, so put it behind the flag for now. Need to
// investigate further when we remove the experimental flag.
return !(cookie.secure && url.startsWith('http:') && !isLocalhost)
}
return !(url.startsWith('http:') && cookie.secure)
// localhost is considered a secure context (even when http:)
// and it's required for cross origin support when visiting a secondary
// origin so that all its cookies are sent.
return !(cookie.secure && url.startsWith('http:') && !isLocalhost)
})
})
}
+3 -5
View File
@@ -442,7 +442,7 @@ const _handlePausedRequests = async (client) => {
}
const _setAutomation = async (client: CriClient, automation: Automation, resetBrowserTargets: (shouldKeepTabOpen: boolean) => Promise<void>, options: BrowserLaunchOpts) => {
const cdpAutomation = await CdpAutomation.create(client.send, client.on, resetBrowserTargets, automation, !!options.experimentalSessionAndOrigin)
const cdpAutomation = await CdpAutomation.create(client.send, client.on, resetBrowserTargets, automation)
automation.use(cdpAutomation)
@@ -612,10 +612,8 @@ export = {
await this._navigateUsingCRI(pageCriClient, url)
if (options.experimentalSessionAndOrigin) {
await this._handlePausedRequests(pageCriClient)
_listenForFrameTreeChanges(pageCriClient)
}
await this._handlePausedRequests(pageCriClient)
_listenForFrameTreeChanges(pageCriClient)
return cdpAutomation
},
+2 -4
View File
@@ -64,7 +64,7 @@ const _getAutomation = async function (win, options: BrowserLaunchOpts, parent)
win.destroy()
}
const automation = await CdpAutomation.create(sendCommand, on, sendClose, parent, options.experimentalSessionAndOrigin)
const automation = await CdpAutomation.create(sendCommand, on, sendClose, parent)
automation.onRequest = _.wrap(automation.onRequest, async (fn, message, data) => {
switch (message) {
@@ -287,9 +287,7 @@ export = {
await this._enableDebugger(win.webContents)
await win.loadURL(url)
if (options.experimentalSessionAndOrigin) {
this._listenToOnBeforeHeaders(win)
}
this._listenToOnBeforeHeaders(win)
return win
},
+4 -5
View File
@@ -126,7 +126,7 @@ async function connectToNewSpec (options, automation: Automation, browserCriClie
const pageCriClient = await browserCriClient.attachToTargetUrl('about:blank')
await CdpAutomation.create(pageCriClient.send, pageCriClient.on, browserCriClient.resetBrowserTargets, automation, options.experimentalSessionAndOrigin)
await CdpAutomation.create(pageCriClient.send, pageCriClient.on, browserCriClient.resetBrowserTargets, automation)
await options.onInitializeNewBrowserTab()
@@ -134,11 +134,11 @@ async function connectToNewSpec (options, automation: Automation, browserCriClie
await navigateToUrl(options.url)
}
async function setupRemote (remotePort, automation, onError, options): Promise<BrowserCriClient> {
async function setupRemote (remotePort, automation, onError): Promise<BrowserCriClient> {
const browserCriClient = await BrowserCriClient.create(['127.0.0.1', '::1'], remotePort, 'Firefox', onError)
const pageCriClient = await browserCriClient.attachToTargetUrl('about:blank')
await CdpAutomation.create(pageCriClient.send, pageCriClient.on, browserCriClient.resetBrowserTargets, automation, options.experimentalSessionAndOrigin)
await CdpAutomation.create(pageCriClient.send, pageCriClient.on, browserCriClient.resetBrowserTargets, automation)
return browserCriClient
}
@@ -222,12 +222,11 @@ export default {
marionettePort,
foxdriverPort,
remotePort,
options,
}): Bluebird<BrowserCriClient> {
return Bluebird.all([
this.setupFoxdriver(foxdriverPort),
this.setupMarionette(extensions, url, marionettePort),
remotePort && setupRemote(remotePort, automation, onError, options),
remotePort && setupRemote(remotePort, automation, onError),
]).then(([,, browserCriClient]) => navigateToUrl(url).then(() => browserCriClient))
},
+1 -1
View File
@@ -540,7 +540,7 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
})
try {
browserCriClient = await firefoxUtil.setup({ automation, extensions: launchOptions.extensions, url, foxdriverPort, marionettePort, remotePort, onError: options.onError, options })
browserCriClient = await firefoxUtil.setup({ automation, extensions: launchOptions.extensions, url, foxdriverPort, marionettePort, remotePort, onError: options.onError })
if (os.platform() === 'win32') {
// override the .kill method for Windows so that the detached Firefox process closes between specs
@@ -95,7 +95,6 @@ let downloadIdCounter = 1
type WebKitAutomationOpts = {
automation: Automation
browser: playwright.Browser
shouldMarkAutIframeRequests: boolean
initialUrl: string
downloadsFolder: string
videoApi?: RunModeVideoApi
@@ -106,12 +105,10 @@ export class WebKitAutomation {
private browser: playwright.Browser
private context!: playwright.BrowserContext
private page!: playwright.Page
private shouldMarkAutIframeRequests: boolean
private constructor (opts: WebKitAutomationOpts) {
this.automation = opts.automation
this.browser = opts.browser
this.shouldMarkAutIframeRequests = opts.shouldMarkAutIframeRequests
}
// static initializer to avoid "not definitively declared"
@@ -147,8 +144,7 @@ export class WebKitAutomation {
let promises: Promise<any>[] = []
// TODO: remove with experimentalSessionAndOrigin
if (this.shouldMarkAutIframeRequests) promises.push(this.markAutIframeRequests())
promises.push(this.markAutIframeRequests())
if (oldPwPage) promises.push(oldPwPage.context().close())
-1
View File
@@ -97,7 +97,6 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
browser: pwBrowser,
initialUrl: url,
downloadsFolder: options.downloadsFolder,
shouldMarkAutIframeRequests: !!options.experimentalSessionAndOrigin,
videoApi: options.videoApi,
})
-2
View File
@@ -53,7 +53,6 @@ interface StringValues {
const _summaries: StringValues = {
experimentalFetchPolyfill: 'Polyfills `window.fetch` to enable Network spying and stubbing.',
experimentalInteractiveRunEvents: 'Allows listening to the `before:run`, `after:run`, `before:spec`, and `after:spec` events in the plugins file during interactive mode.',
experimentalSessionAndOrigin: 'Enables cross-origin and improved session support, including the `cy.origin` and `cy.session` commands.',
experimentalModifyObstructiveThirdPartyCode: 'Applies `modifyObstructiveCode` to third party `.html` and `.js`, removes subresource integrity, and modifies the user agent in Electron.',
experimentalSourceRewriting: 'Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm.',
experimentalSingleTabRunMode: 'Runs all component specs in a single tab, trading spec isolation for faster run mode execution.',
@@ -74,7 +73,6 @@ const _summaries: StringValues = {
const _names: StringValues = {
experimentalFetchPolyfill: 'Fetch Polyfill',
experimentalInteractiveRunEvents: 'Interactive Mode Run Events',
experimentalSessionAndOrigin: 'Cross-origin and Session',
experimentalModifyObstructiveThirdPartyCode: 'Modify Obstructive Third Party Code',
experimentalSingleTabRunMode: 'Single Tab Run Mode',
experimentalSourceRewriting: 'Improved Source Rewriting',
-1
View File
@@ -94,7 +94,6 @@ export class OpenProject {
isTextTerminal: !!cfg.isTextTerminal,
downloadsFolder: cfg.downloadsFolder,
experimentalModifyObstructiveThirdPartyCode: cfg.experimentalModifyObstructiveThirdPartyCode,
experimentalSessionAndOrigin: cfg.experimentalSessionAndOrigin,
experimentalWebKitSupport: cfg.experimentalWebKitSupport,
...prevOptions || {},
}
@@ -126,13 +126,9 @@ class RunPlugins {
.then((modifiedCfg) => {
debug('plugins file successfully loaded')
// if the experimentalSessionAndOrigin flag is true, specify which
// commands should (potentially) have their callbacks replaced. this is
// currently used by the webpack preprocessor. see its implmentation for
// more details
if (this._getExperimentalSessionAndOriginValue(initialConfig, modifiedCfg)) {
global.__cypressCallbackReplacementCommands = ['origin']
}
// specify which commands should (potentially) have their callbacks replaced. this is
// currently used by the webpack preprocessor. see its implementation for more details
global.__cypressCallbackReplacementCommands = ['origin']
this.ipc.send('setupTestingType:reply', {
setupConfig: modifiedCfg,
@@ -151,19 +147,6 @@ class RunPlugins {
})
}
_getExperimentalSessionAndOriginValue (initialConfig, modifiedConfig) {
// prefer the modified value if it's specified
if (
typeof modifiedConfig === 'object'
&& typeof modifiedConfig.experimentalSessionAndOrigin === 'boolean'
) {
return modifiedConfig.experimentalSessionAndOrigin
}
// otherwise, use the initial value
return initialConfig.experimentalSessionAndOrigin
}
execute (event, ids, args = []) {
debug(`execute plugin event: ${event} (%o)`, ids)
+1 -5
View File
@@ -68,14 +68,12 @@ export class SocketBase {
private _sendFocusBrowserMessage
protected supportsRunEvents: boolean
protected experimentalSessionAndOrigin: boolean
protected ended: boolean
protected _io?: socketIo.SocketIOServer
localBus: EventEmitter
constructor (config: Record<string, any>) {
this.supportsRunEvents = config.isTextTerminal || config.experimentalInteractiveRunEvents
this.experimentalSessionAndOrigin = config.experimentalSessionAndOrigin
this.ended = false
this.localBus = new EventEmitter()
}
@@ -226,9 +224,7 @@ export class SocketBase {
debug('automation:client connected')
// only send the necessary config
automationClient.emit('automation:config', {
experimentalSessionAndOrigin: this.experimentalSessionAndOrigin,
})
automationClient.emit('automation:config', {})
// if our automation disconnects then we're
// in trouble and should probably bomb everything
@@ -1670,9 +1670,9 @@ describe('lib/cypress', () => {
// this should be overridden by the env argument
json.baseUrl = 'http://localhost:8080'
const { supportFile, specPattern, excludeSpecPattern, baseUrl, experimentalSessionAndOrigin, slowTestThreshold, testIsolation, ...rest } = json
const { supportFile, specPattern, excludeSpecPattern, baseUrl, slowTestThreshold, testIsolation, ...rest } = json
return settings.writeForTesting(this.todosPath, { ...rest, e2e: { baseUrl, experimentalSessionAndOrigin, supportFile, specPattern, testIsolation, excludeSpecPattern } })
return settings.writeForTesting(this.todosPath, { ...rest, e2e: { baseUrl, supportFile, specPattern, testIsolation, excludeSpecPattern } })
}).then(async () => {
await clearCtx()
@@ -1703,7 +1703,6 @@ describe('lib/cypress', () => {
expect(cfg.pageLoadTimeout).to.eq(1000)
expect(cfg.port).to.eq(2121)
expect(cfg.baseUrl).to.eq('http://localhost')
expect(cfg.experimentalSessionAndOrigin).to.be.false
expect(cfg.watchForFileChanges).to.be.false
expect(cfg.responseTimeout).to.eq(5555)
expect(cfg.env.baz).to.eq('baz')
@@ -76,17 +76,18 @@ describe('lib/browsers/chrome', () => {
expect(this.browserCriClient.ensureMinimumProtocolVersion).to.be.calledOnce
})
it('focuses on the page, calls CRI Page.visit, enables Page events, and sets download behavior', function () {
it('focuses on the page, calls CRI Page.navigate, enables Page/Network/Fetch events, and sets download behavior', function () {
return chrome.open({ isHeadless: true }, 'http://', openOpts, this.automation)
.then(() => {
expect(utils.getPort).to.have.been.calledOnce // to get remote interface port
expect(this.pageCriClient.send.callCount).to.equal(5)
expect(this.pageCriClient.send).to.have.been.calledWith('Page.bringToFront')
expect(this.pageCriClient.send.callCount).to.equal(6)
expect(this.pageCriClient.send).to.have.been.calledWith('Page.bringToFront')
expect(this.pageCriClient.send).to.have.been.calledWith('Page.navigate')
expect(this.pageCriClient.send).to.have.been.calledWith('Page.enable')
expect(this.pageCriClient.send).to.have.been.calledWith('Page.setDownloadBehavior')
expect(this.pageCriClient.send).to.have.been.calledWith('Network.enable')
expect(this.pageCriClient.send).to.have.been.calledWith('Fetch.enable')
})
})
@@ -360,11 +361,6 @@ describe('lib/browsers/chrome', () => {
})
describe('adding header to AUT iframe request', function () {
const withExperimentalFlagOn = {
...openOpts,
experimentalSessionAndOrigin: true,
}
beforeEach(function () {
const frameTree = {
frameTree: {
@@ -388,20 +384,14 @@ describe('lib/browsers/chrome', () => {
this.pageCriClient.send.withArgs('Page.getFrameTree').resolves(frameTree)
})
it('does not listen to Fetch.requestPaused if experimental flag is off', async function () {
await chrome.open('chrome', 'http://', { ...openOpts, experimentalSessionAndOrigin: false }, this.automation)
expect(this.pageCriClient.on).not.to.be.calledWith('Fetch.requestPaused')
})
it('sends Fetch.enable', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
expect(this.pageCriClient.send).to.have.been.calledWith('Fetch.enable')
})
it('does not add header when not a document', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Fetch.requestPaused').yield({
requestId: '1234',
@@ -414,7 +404,7 @@ describe('lib/browsers/chrome', () => {
})
it('does not add header when it is a spec frame request', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Page.frameAttached').yield()
@@ -433,7 +423,7 @@ describe('lib/browsers/chrome', () => {
})
it('appends X-Cypress-Is-AUT-Frame header to AUT iframe request', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Page.frameAttached').yield()
@@ -465,7 +455,7 @@ describe('lib/browsers/chrome', () => {
})
it('appends X-Cypress-Is-XHR-Or-Fetch header to fetch request', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Page.frameAttached').yield()
@@ -497,7 +487,7 @@ describe('lib/browsers/chrome', () => {
})
it('appends X-Cypress-Is-XHR-Or-Fetch header to xhr request', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Page.frameAttached').yield()
@@ -529,7 +519,7 @@ describe('lib/browsers/chrome', () => {
})
it('gets frame tree on Page.frameAttached', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Page.frameAttached').yield()
@@ -537,7 +527,7 @@ describe('lib/browsers/chrome', () => {
})
it('gets frame tree on Page.frameDetached', async function () {
await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation)
await chrome.open('chrome', 'http://', openOpts, this.automation)
this.pageCriClient.on.withArgs('Page.frameDetached').yield()
@@ -330,21 +330,7 @@ describe('lib/browsers/electron', () => {
})
})
it('does not listen to `onBeforeSendHeaders` if experimental flag is off', function () {
this.options.experimentalSessionAndOrigin = false
sinon.stub(this.win.webContents.session.webRequest, 'onBeforeSendHeaders')
return electron._launch(this.win, this.url, this.automation, this.options)
.then(() => {
expect(this.win.webContents.session.webRequest.onBeforeSendHeaders).not.to.be.called
})
})
describe('adding header aut iframe requests', function () {
beforeEach(function () {
this.options.experimentalSessionAndOrigin = true
})
it('does not add header if not a sub frame', function () {
sinon.stub(this.win.webContents.session.webRequest, 'onBeforeSendHeaders')
@@ -534,7 +534,7 @@ describe('lib/browsers/firefox', () => {
sinon.stub(BrowserCriClient, 'create').resolves(browserCriClient)
sinon.stub(CdpAutomation, 'create').resolves()
const actual = await firefoxUtil.setupRemote(port, null, null, { experimentalSessionAndOrigin: false })
const actual = await firefoxUtil.setupRemote(port, null, null)
expect(actual).to.equal(browserCriClient)
expect(browserCriClient.attachToTargetUrl).to.be.calledWith('about:blank')
@@ -544,7 +544,6 @@ describe('lib/browsers/firefox', () => {
criClientStub.on,
browserCriClient.resetBrowserTargets,
null,
false,
)
})
})
@@ -268,33 +268,15 @@ describe.skip('lib/plugins/child/run_plugins', () => {
})
})
it('defines global __cypressCallbackReplacementCommands if experimentalSessionAndOrigin: true', function () {
it('defines global __cypressCallbackReplacementCommands', function () {
const setupNodeEventsFn = sinon.spy()
runPlugins.runSetupNodeEvents(setupNodeEventsFn)
const config = {
experimentalSessionAndOrigin: true,
}
this.ipc.on.withArgs('load:plugins').yield(config)
this.ipc.on.withArgs('load:plugins').yield()
expect(global.__cypressCallbackReplacementCommands).to.deep.equal(['origin'])
})
it('does not define global __cypressCallbackReplacementCommands if experimentalSessionAndOrigin: false', function () {
const setupNodeEventsFn = sinon.spy()
runPlugins.runSetupNodeEvents(setupNodeEventsFn)
const config = {
experimentalSessionAndOrigin: false,
}
this.ipc.on.withArgs('load:plugins').yield(config)
expect(global.__cypressCallbackReplacementCommands).to.be.undefined
})
})
describe('on \'execute\' message', () => {
+1 -1
View File
@@ -30,7 +30,7 @@ export interface FullConfig extends Partial<Cypress.RuntimeConfigOptions & Cypre
// and are required when creating a project.
export type ReceivedCypressOptions =
Pick<Cypress.RuntimeConfigOptions, 'hosts' | 'projectName' | 'clientRoute' | 'devServerPublicPathRoute' | 'namespace' | 'report' | 'socketIoCookie' | 'configFile' | 'isTextTerminal' | 'isNewProject' | 'proxyUrl' | 'browsers' | 'browserUrl' | 'socketIoRoute' | 'arch' | 'platform' | 'spec' | 'specs' | 'browser' | 'version' | 'remote'>
& Pick<Cypress.ResolvedConfigOptions, 'chromeWebSecurity' | 'supportFolder' | 'experimentalSourceRewriting' | 'fixturesFolder' | 'reporter' | 'reporterOptions' | 'screenshotsFolder' | 'supportFile' | 'baseUrl' | 'viewportHeight' | 'viewportWidth' | 'port' | 'experimentalInteractiveRunEvents' | 'userAgent' | 'downloadsFolder' | 'env' | 'excludeSpecPattern' | 'specPattern' | 'experimentalSessionAndOrigin' | 'experimentalModifyObstructiveThirdPartyCode' | 'video' | 'videoCompression' | 'videosFolder' | 'videoUploadOnPasses' | 'resolvedNodeVersion' | 'resolvedNodePath' | 'trashAssetsBeforeRuns' | 'experimentalWebKitSupport'> // TODO: Figure out how to type this better.
& Pick<Cypress.ResolvedConfigOptions, 'chromeWebSecurity' | 'supportFolder' | 'experimentalSourceRewriting' | 'fixturesFolder' | 'reporter' | 'reporterOptions' | 'screenshotsFolder' | 'supportFile' | 'baseUrl' | 'viewportHeight' | 'viewportWidth' | 'port' | 'experimentalInteractiveRunEvents' | 'userAgent' | 'downloadsFolder' | 'env' | 'excludeSpecPattern' | 'specPattern' | 'experimentalModifyObstructiveThirdPartyCode' | 'video' | 'videoCompression' | 'videosFolder' | 'videoUploadOnPasses' | 'resolvedNodeVersion' | 'resolvedNodePath' | 'trashAssetsBeforeRuns' | 'experimentalWebKitSupport'> // TODO: Figure out how to type this better.
export interface SettingsOptions {
testingType?: 'component' |'e2e'
+1 -1
View File
@@ -21,7 +21,7 @@ export type BrowserLaunchOpts = {
onBrowserClose?: (...args: unknown[]) => void
onBrowserOpen?: (...args: unknown[]) => void
} & Partial<OpenProjectLaunchOpts> // TODO: remove the `Partial` here by making it impossible for openProject.launch to be called w/o OpenProjectLaunchOpts
& Pick<ReceivedCypressOptions, 'userAgent' | 'proxyUrl' | 'socketIoRoute' | 'chromeWebSecurity' | 'downloadsFolder' | 'experimentalSessionAndOrigin' | 'experimentalModifyObstructiveThirdPartyCode' | 'experimentalWebKitSupport'>
& Pick<ReceivedCypressOptions, 'userAgent' | 'proxyUrl' | 'socketIoRoute' | 'chromeWebSecurity' | 'downloadsFolder' | 'experimentalModifyObstructiveThirdPartyCode' | 'experimentalWebKitSupport'>
export type BrowserNewTabOpts = { onInitializeNewBrowserTab: () => void } & BrowserLaunchOpts
-15
View File
@@ -409,21 +409,6 @@ https://on.cypress.io/migration-guide
`
exports['e2e config throws an error if experimentalSessionAndOrigin is set on the component level 1'] = `
The component.experimentalSessionAndOrigin configuration option is not valid for component testing.
Please remove this option or add this as an e2e testing type property: e2e.experimentalSessionAndOrigin
{
e2e: {
experimentalSessionAndOrigin: '...',
}
}
https://on.cypress.io/migration-guide
`
exports['e2e config finds supportFiles in projects containing glob syntax 1'] = `
====================================================================================================
@@ -5,11 +5,10 @@ exports['e2e cy.origin errors / captures the stack trace correctly for errors in
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (cy_origin_error.cy.ts)
Searched: cypress/e2e/cy_origin_error.cy.ts
Experiments: experimentalSessionAndOrigin=true
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (cy_origin_error.cy.ts)
Searched: cypress/e2e/cy_origin_error.cy.ts
@@ -5,11 +5,10 @@ exports['e2e cy.origin retries / Appropriately displays test retry errors withou
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (cy_origin_retries.cy.ts)
Searched: cypress/e2e/cy_origin_retries.cy.ts
Experiments: experimentalSessionAndOrigin=true
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (cy_origin_retries.cy.ts)
Searched: cypress/e2e/cy_origin_retries.cy.ts
@@ -1,140 +1,3 @@
exports['e2e runnable execution / cannot navigate in before hook and test'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (beforehook-and-test-navigation.cy.js)
Searched: cypress/e2e/beforehook-and-test-navigation.cy.js
Running: beforehook-and-test-navigation.cy.js (1 of 1)
initial domain change
test
suite
test
1) causes domain navigation
navigation error in beforeEach
2) "before each" hook for "never gets here"
2 passing
2 failing
1) suite
causes domain navigation:
CypressError: \`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.
In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:
\`cy.visit('http://localhost:4545/')\`
\`<commands targeting http://localhost:4545 go here>\`
\`cy.origin('http://localhost:5656', () => {\`
\` cy.visit('http://localhost:5656/')\`
\` <commands targeting http://localhost:5656 go here>\`
\`})\`
The new URL is considered a different origin because the following parts of the URL are different:
> port
You may only \`cy.visit()\` same-origin URLs within a single test.
The previous URL you visited was:
> 'http://localhost:4545'
You're attempting to visit this URL:
> 'http://localhost:5656'
https://on.cypress.io/cannot-visit-different-origin-domain
[stack trace lines]
2) navigation error in beforeEach
"before each" hook for "never gets here":
CypressError: \`cy.visit()\` failed because you are attempting to visit a URL that is of a different origin.
In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use \`cy.origin()\`:
\`cy.visit('http://localhost:4545/')\`
\`<commands targeting http://localhost:4545 go here>\`
\`cy.origin('http://localhost:5656', () => {\`
\` cy.visit('http://localhost:5656/')\`
\` <commands targeting http://localhost:5656 go here>\`
\`})\`
The new URL is considered a different origin because the following parts of the URL are different:
> port
You may only \`cy.visit()\` same-origin URLs within a single test.
The previous URL you visited was:
> 'http://localhost:4545'
You're attempting to visit this URL:
> 'http://localhost:5656'
https://on.cypress.io/cannot-visit-different-origin-domain
Because this error occurred during a \`before each\` hook we are skipping the remaining tests in the current suite: \`navigation error in beforeEach\`
[stack trace lines]
(Results)
Tests: 4
Passing: 2
Failing: 2
Pending: 0
Skipped: 0
Screenshots: 0
Video: true
Duration: X seconds
Spec Ran: beforehook-and-test-navigation.cy.js
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /XXX/XXX/XXX/cypress/videos/beforehook-and-test-navigation. (X second)
cy.js.mp4
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
beforehook-and-test-navigation.cy.j XX:XX 4 2 2 - -
s
1 of 1 failed (100%) XX:XX 4 2 2 - -
`
exports['e2e runnable execution / runnables run correct number of times with navigation'] = `
====================================================================================================
@@ -278,3 +141,73 @@ exports['e2e runnable execution / runs correctly after top navigation with alrea
`
exports['e2e runnable execution / can navigate in before hook and test'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (beforehook-and-test-navigation.cy.js)
Searched: cypress/e2e/beforehook-and-test-navigation.cy.js
Running: beforehook-and-test-navigation.cy.js (1 of 1)
initial domain change
test
suite
test
causes domain navigation
navigation in beforeEach
test
4 passing
(Results)
Tests: 4
Passing: 4
Failing: 0
Pending: 0
Skipped: 0
Screenshots: 0
Video: true
Duration: X seconds
Spec Ran: beforehook-and-test-navigation.cy.js
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /XXX/XXX/XXX/cypress/videos/beforehook-and-test-navigation. (X second)
cy.js.mp4
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
beforehook-and-test-navigation.cy.j XX:XX 4 4 - - -
s
All specs passed! XX:XX 4 4 - - -
`
@@ -131,13 +131,13 @@ Because this error occurred during a \`after each\` hook we are skipping the rem
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/element.png (400x300)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/taking screenshots -- retries (200x1300)
each screenshot for up to XX:XX.png
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/retrying-test.png (1000x1316)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/retrying-test.png (1000x660)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/taking screenshots -- screens (1280x720)
hots in a retried test (failed).png
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/retrying-test (attempt 2).png (1000x1316)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/retrying-test (attempt 2).png (1000x660)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/taking screenshots -- screens (1280x720)
hots in a retried test (failed) (attempt 2).png
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/retrying-test (attempt 3).png (1000x1316)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/retrying-test (attempt 3).png (1000x660)
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/taking screenshots -- screens (1280x720)
hots in a retried test (failed) (attempt 3).png
- /XXX/XXX/XXX/cypress/screenshots/screenshots.cy.js/taking screenshots -- ensures (1280x720)
+9 -11
View File
@@ -5,11 +5,10 @@ exports['e2e sessions / session tests'] = `
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (session.cy.js)
Searched: cypress/e2e/session/session.cy.js
Experiments: experimentalSessionAndOrigin=true
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (session.cy.js)
Searched: cypress/e2e/session/session.cy.js
@@ -144,12 +143,11 @@ exports['e2e sessions / handles spec and global sessions persistence on spec rel
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 2 found (session_persist_1.cy.js, session_persist_2.cy.js)
Searched: cypress/e2e/session/session_persist_1.cy.js, cypress/e2e/session/session_persist
_2.cy.js
Experiments: experimentalSessionAndOrigin=true
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 2 found (session_persist_1.cy.js, session_persist_2.cy.js)
Searched: cypress/e2e/session/session_persist_1.cy.js, cypress/e2e/session/session_persist_2
.cy.js
@@ -90,6 +90,7 @@ Error: Webpack Compilation Error
./cypress/e2e/typescript_syntax_error.cy.tsXX:XX
Module parse failed: Unexpected token (3:19)
File was processed with these loaders:
* relative/path/to/webpack-preprocessor/dist/lib/cross-origin-callback-loader.js
* relative/path/to/webpack-batteries-included-preprocessor/node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| // The code below is ignored by eslint
+20 -177
View File
@@ -5,11 +5,10 @@ exports['e2e web security / when enabled / fails'] = `
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (web_security.cy.js)
Searched: cypress/e2e/web_security.cy.js
Experiments: experimentalSessionAndOrigin=false
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (web_security.cy.js)
Searched: cypress/e2e/web_security.cy.js
@@ -31,71 +30,32 @@ exports['e2e web security / when enabled / fails'] = `
1) web security
fails when clicking <a> to another origin:
CypressError: Cypress detected a cross origin error happened on page load:
> [Cross origin error message]
Timed out retrying after 4000ms
+ expected - actual
Before the page load, you were bound to the origin:
> http://localhost:4466
A cross origin error happens when your application navigates to a new URL which does not match the origin above.
A new URL does not match the origin if the 'protocol', 'port' (if specified), and/or 'host' are different.
Cypress does not allow you to navigate to a different origin URL within a single test.
You may need to restructure some of your test code to avoid this problem.
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false } in \`cypress.config.js\`.
https://on.cypress.io/cross-origin-violation
+'https://www.foo.com:44665/cross_origin'
[stack trace lines]
2) web security
fails when submitted a form and being redirected to another origin:
CypressError: Cypress detected a cross origin error happened on page load:
> [Cross origin error message]
Timed out retrying after 4000ms
+ expected - actual
Before the page load, you were bound to the origin:
> http://localhost:4466
A cross origin error happens when your application navigates to a new URL which does not match the origin above.
A new URL does not match the origin if the 'protocol', 'port' (if specified), and/or 'host' are different.
Cypress does not allow you to navigate to a different origin URL within a single test.
You may need to restructure some of your test code to avoid this problem.
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false } in \`cypress.config.js\`.
https://on.cypress.io/cross-origin-violation
+'https://www.foo.com:44665/cross_origin'
[stack trace lines]
3) web security
fails when using a javascript redirect to another origin:
CypressError: Cypress detected a cross origin error happened on page load:
> [Cross origin error message]
Timed out retrying after 4000ms
+ expected - actual
Before the page load, you were bound to the origin:
> http://localhost:4466
A cross origin error happens when your application navigates to a new URL which does not match the origin above.
A new URL does not match the origin if the 'protocol', 'port' (if specified), and/or 'host' are different.
Cypress does not allow you to navigate to a different origin URL within a single test.
You may need to restructure some of your test code to avoid this problem.
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false } in \`cypress.config.js\`.
https://on.cypress.io/cross-origin-violation
+'https://www.foo.com:44665/cross_origin'
[stack trace lines]
4) web security
@@ -160,11 +120,10 @@ exports['e2e web security / when disabled / passes'] = `
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (web_security.cy.js)
Searched: cypress/e2e/web_security.cy.js
Experiments: experimentalSessionAndOrigin=false
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (web_security.cy.js)
Searched: cypress/e2e/web_security.cy.js
@@ -284,119 +243,3 @@ TimeoutError: operation timed out
`
exports['e2e web security / when experimentalSessionAndOrigin is enabled / fails'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (web_security.cy.js)
Searched: cypress/e2e/web_security.cy.js
Experiments: experimentalSessionAndOrigin=true
Running: web_security.cy.js (1 of 1)
web security
1) fails when clicking <a> to another origin
2) fails when submitted a form and being redirected to another origin
3) fails when using a javascript redirect to another origin
4) fails when doing a CORS request cross-origin
finds the correct spec bridge even if a previous spec bridge host is a subset of the current host
1 passing
4 failing
1) web security
fails when clicking <a> to another origin:
Timed out retrying after 50ms
+ expected - actual
+'https://www.foo.com:44665/cross_origin'
[stack trace lines]
2) web security
fails when submitted a form and being redirected to another origin:
Timed out retrying after 50ms
+ expected - actual
+'https://www.foo.com:44665/cross_origin'
[stack trace lines]
3) web security
fails when using a javascript redirect to another origin:
Timed out retrying after 50ms
+ expected - actual
+'https://www.foo.com:44665/cross_origin'
[stack trace lines]
4) web security
fails when doing a CORS request cross-origin:
AssertionError: Timed out retrying after 500ms: Expected to find content: 'success!' but never did.
[stack trace lines]
(Results)
Tests: 5
Passing: 1
Failing: 4
Pending: 0
Skipped: 0
Screenshots: 4
Video: true
Duration: X seconds
Spec Ran: web_security.cy.js
(Screenshots)
- /XXX/XXX/XXX/cypress/screenshots/web_security.cy.js/web security -- fails when c (1280x720)
licking a to another origin (failed).png
- /XXX/XXX/XXX/cypress/screenshots/web_security.cy.js/web security -- fails when s (1280x720)
ubmitted a form and being redirected to another origin (failed).png
- /XXX/XXX/XXX/cypress/screenshots/web_security.cy.js/web security -- fails when u (1280x720)
sing a javascript redirect to another origin (failed).png
- /XXX/XXX/XXX/cypress/screenshots/web_security.cy.js/web security -- fails when d (1280x720)
oing a CORS request cross-origin (failed).png
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /XXX/XXX/XXX/cypress/videos/web_security.cy.js.mp4 (X second)
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
web_security.cy.js XX:XX 5 1 4 - -
1 of 1 failed (100%) XX:XX 5 1 4 - -
`
@@ -17,7 +17,8 @@ const abortXhr = (route) => {
}
}
describe('cy.route', { defaultCommandTimeout: 0 }, () => {
// TODO(origin): 'strict' testIsolation causes cy.route to fail, appears to be related to visiting about:blank
describe('cy.route', { defaultCommandTimeout: 0, testIsolation: 'legacy' }, () => {
it('callback assertion failure', () => {
cy.server().route(() => {
expect('actual').to.equal('expected')
@@ -17,7 +17,8 @@ const abortXhr = (route) => {
}
}
describe('cy.server', { defaultCommandTimeout: 0 }, () => {
// TODO(origin): 'strict' testIsolation causes cy.route to fail, appears to be related to visiting about:blank
describe('cy.server', { defaultCommandTimeout: 0, testIsolation: 'legacy' }, () => {
it('onAbort assertion failure', () => {
cy.server({
onAbort () {
@@ -1,9 +1,11 @@
describe('cy assertion', {
numTestsKeptInMemory: 1,
}, () => {
it('visits fixture', () => {
beforeEach(() => {
cy.visit('cypress/fixtures/example.html')
})
it('visits fixture', () => {
cy.get('html').should('exist')
})
@@ -37,10 +37,6 @@ describe('cookies', () => {
.and.eq(Cypress.config('baseUrl'))
})
beforeEach(() => {
cy.wrap({ foo: 'bar' })
})
it('sends set cookies to path', () => {
cy.clearCookies()
cy.setCookie('asdf', 'jkl')
@@ -82,9 +78,14 @@ describe('cookies', () => {
cy.request(`${httpsUrl}/requestCookies`)
.its('body').should('deep.eq', { shouldExpire: 'oneHour' })
// secure cookies should not have been attached
cy.request(`${httpUrl}/requestCookies`)
.its('body').should('deep.eq', {})
const hostName = new Cypress.Location(httpUrl).getHostName()
// TODO(origin): remove 'if' check once https://github.com/cypress-io/cypress/issues/24332 is resolved
if (!['localhost', '127.0.0.1'].includes(hostName)) {
// secure cookies should not have been attached
cy.request(`${httpUrl}/requestCookies`)
.its('body').should('deep.eq', {})
}
cy.visit(`${httpsUrl}/expirationMaxAge`)
cy.getCookies().should('be.empty')
@@ -46,9 +46,14 @@ describe('cookies', () => {
cy.request(`${httpsUrl}/requestCookies`)
.its('body').should('deep.eq', { shouldExpire: 'oneHour' })
// secure cookies should not have been attached
cy.request(`${httpUrl}/requestCookies`)
.its('body').should('deep.eq', {})
const hostName = new Cypress.Location(httpUrl).getHostName()
// TODO(origin): remove 'if' check once https://github.com/cypress-io/cypress/issues/24332 is resolved
if (!['localhost', '127.0.0.1'].includes(hostName)) {
// secure cookies should not have been attached
cy.request(`${httpUrl}/requestCookies`)
.its('body').should('deep.eq', {})
}
cy.visit(`${httpsUrl}/expirationMaxAge`)
cy.getCookies().should('be.empty')
@@ -53,23 +53,21 @@ describe('visits', () => {
count += 1
})
// about:blank yes (1)
cy.visit('/hash.html?foo#bar') // yes (2)
cy.visit('/hash.html?foo#foo') // no (2)
cy.visit('/hash.html?foo#bar') // yes (1)
cy.visit('/hash.html?foo#foo') // no (1)
cy.window().its('scrollY').should('eq', 1000)
cy.visit('/hash.html?bar#bar') // yes (3)
cy.visit('/hash.html?bar#bar') // yes (2)
cy.window().its('scrollY').should('eq', 0)
cy.visit('/index.html?bar#bar') // yes (4)
cy.visit('/index.html?baz#bar') // yes (5)
cy.visit('/index.html#bar') // yes (6)
cy.visit('/index.html') // yes (7)
cy.visit('/index.html#baz') // no (7)
cy.visit('/index.html#') // no (7)
cy.visit('/index.html?bar#bar') // yes (3)
cy.visit('/index.html?baz#bar') // yes (4)
cy.visit('/index.html#bar') // yes (5)
cy.visit('/index.html') // yes (6)
cy.visit('/index.html#baz') // no (6)
cy.visit('/index.html#') // no (6)
.then(() => {
expect(count).to.eq(7)
expect(count).to.eq(6)
expect(urls).to.deep.eq([
'about:blank',
`${origin}/hash.html?foo#bar`,
`${origin}/hash.html?bar#bar`,
`${origin}/index.html?bar#bar`,
@@ -27,12 +27,10 @@ describe('web security', function () {
it('finds the correct spec bridge even if a previous spec bridge host is a subset of the current host', () => {
// Establish a spec bridge with a 'bar.com' host prior to loading 'foobar.com'
if (Cypress.config('experimentalSessionAndOrigin')) {
cy.origin('http://www.bar.com:4466', () => undefined)
cy.origin('http://www.bar.com:4466', () => undefined)
cy.origin('http://www.app.foobar.com:4466', () => {
cy.visit('/link')
})
}
cy.origin('http://www.app.foobar.com:4466', () => {
cy.visit('/link')
})
})
})
@@ -129,11 +129,8 @@ describe('xhrs', () => {
})
describe('server with 1 visit', () => {
before(() => {
cy.visit('/xhr.html')
})
beforeEach(() => {
cy.visit('/xhr.html')
cy.server()
cy.route(/users/, [{}, {}]).as('getUsers')
})
@@ -1,5 +1,3 @@
// should fail since before hooks are rerun on domain change
const urls = [
'http://localhost:3434',
'http://localhost:4545',
@@ -24,7 +22,7 @@ describe('suite', () => {
})
})
describe('navigation error in beforeEach', () => {
describe('navigation in beforeEach', () => {
before(() => {
cy.visit(urls[1])
})
@@ -33,5 +31,5 @@ describe('navigation error in beforeEach', () => {
cy.visit(urls[2])
})
it('never gets here', () => {})
it('test', () => {})
})
@@ -1,6 +1,5 @@
module.exports = {
component: {
experimentalSessionAndOrigin: true,
devServer: {
framework: 'create-react-app',
bundler: 'webpack',
@@ -6,7 +6,6 @@
"componentFolder": "src",
"testFiles": "**/*.spec.{tsx,js}",
"pluginsFile": "cypress/plugins/index.js",
"experimentalSessionAndOrigin": true,
"e2e": {
"defaultCommandTimeout": 10000,
"slowTestThreshold": 5000
@@ -15,7 +15,6 @@ module.exports = defineConfig({
slowTestThreshold: 5000,
baseUrl: 'http://localhost:3000',
specPattern: 'cypress/e2e/**/*.spec.{tsx,js}',
experimentalSessionAndOrigin: true,
},
component: {
setupNodeEvents (on, config) {},
@@ -3,7 +3,10 @@ import Dashboard from '@uppy/dashboard'
import Dropzone from 'dropzone'
describe('selectFile', () => {
// TODO(origin): fails in testIsolation: 'strict' mode with ResizeObserver loop limit exceeded
// error. Using Cypress.on('uncaught:exception') does not catch the error as it appears to be
// happening when we are visiting about:blank.
describe('selectFile', { testIsolation: 'legacy' }, () => {
describe('uppy', () => {
beforeEach(() => {
cy.document().then((doc) => {
@@ -1,7 +1,5 @@
module.exports = {
numTestsKeptInMemory: 0,
video: false,
e2e: {
experimentalSessionAndOrigin: true,
},
e2e: {},
}
@@ -560,19 +560,19 @@ describe.skip('consoleProps', () => {
// because browsers prevent an https page from embedding http domains, we filter out
// insecure origins (contexts) when top is a secure context when we clear cross origin session data
// the first test in each suite visits insecure origin with sessionSupport OFF so data is not cleared
// the first test in each suite visits insecure origin with so data is not cleared
// on test:before:run, which allows the next run to switch top back to a secure context
// and finally we turn sessionSupport back ON for the 3rd tests, which will now try to clear insecure
// and finally for the 3rd tests, which will now try to clear insecure
// bar.foo.com data.
describe('ignores setting insecure context data when on secure context', () => {
describe('no cross origin secure origins, nothing to clear', () => {
it('sets insecure content', { experimentalSessionAndOrigin: false }, () => {
it('sets insecure content', () => {
cy.visit('http://bar.foo.com:4465/form')
})
let logSpy
it('nothing to clear - 1/2', { experimentalSessionAndOrigin: false }, () => {
it('nothing to clear - 1/2', () => {
cy.visit('https://localhost:4466/form')
.then(() => {
logSpy = Cypress.sinon.spy(Cypress, 'log')
@@ -586,13 +586,13 @@ describe('ignores setting insecure context data when on secure context', () => {
})
describe('only secure origins cleared', () => {
it('sets insecure content', { experimentalSessionAndOrigin: false }, () => {
it('sets insecure content', () => {
cy.visit('http://bar.foo.com:4465/form')
})
let logSpy
it('switches to secure context - clears only secure context data - 1/2', { experimentalSessionAndOrigin: false }, () => {
it('switches to secure context - clears only secure context data - 1/2', () => {
cy.visit('https://localhost:4466/cross_origin_iframe/foo')
.then(() => {
logSpy = Cypress.sinon.spy(Cypress, 'log')
-12
View File
@@ -180,18 +180,6 @@ describe('e2e config', () => {
})
})
it('throws an error if experimentalSessionAndOrigin is set on the component level', async function () {
await Fixtures.scaffoldProject('invalid-root-level-config')
return systemTests.exec(this, {
project: 'invalid-root-level-config',
configFile: 'invalid-component-experimentalSessionAndOrigin-config.js',
testingType: 'component',
expectedExitCode: 1,
snapshot: true,
})
})
it('throws an error if indexHtml is set on the root level', async function () {
await Fixtures.scaffoldProject('invalid-root-level-config')
+1 -6
View File
@@ -163,13 +163,8 @@ const otherDomain = 'quux.bar.net'
const otherUrl = `http://${otherDomain}${haveRoot ? '' : `:${httpPort}`}`
const otherHttpsUrl = `https://${otherDomain}${haveRoot ? '' : `:${httpsPort}`}`
const chromiumSameSiteFeatures = '--enable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure'
// SameSite is loosely enforced in some versions of FF/Electron/Chromium,
// but all have options we can use to force it to be strict
const FORCED_SAMESITE_ENV = {
ELECTRON_EXTRA_LAUNCH_ARGS: chromiumSameSiteFeatures,
CHROMIUM_EXTRA_LAUNCH_ARGS: chromiumSameSiteFeatures,
// SameSite is loosely enforced in Firefox
FIREFOX_FORCE_STRICT_SAMESITE: 1,
}
@@ -11,7 +11,6 @@ const onServer = function (app) {
})
}
const commonConfig = {
experimentalSessionAndOrigin: true,
hosts: {
'*.foobar.com': '127.0.0.1',
},
@@ -33,7 +33,6 @@ describe('e2e cy.origin retries', () => {
snapshot: true,
expectedExitCode: 1,
config: {
experimentalSessionAndOrigin: true,
retries: 2,
},
async onRun (exec) {
+1 -5
View File
@@ -16,14 +16,10 @@ describe('e2e runnable execution', () => {
}],
})
// navigation in before and in test body doesn't cause infinite loop
// but throws correct error
// https://github.com/cypress-io/cypress/issues/1987
systemTests.it('cannot navigate in before hook and test', {
systemTests.it('can navigate in before hook and test', {
project: 'hooks-after-rerun',
spec: 'beforehook-and-test-navigation.cy.js',
snapshot: true,
expectedExitCode: 2,
})
systemTests.it('runnables run correct number of times with navigation', {
-2
View File
@@ -186,7 +186,6 @@ describe('e2e sessions', () => {
spec: 'session/session.cy.js',
snapshot: true,
config: {
experimentalSessionAndOrigin: true,
video: false,
},
})
@@ -198,7 +197,6 @@ describe('e2e sessions', () => {
snapshot: true,
config: {
env: { SYSTEM_TESTS: true },
experimentalSessionAndOrigin: true,
video: false,
},
})
@@ -18,6 +18,7 @@ describe('e2e typescript in spec and support file', function () {
expectedExitCode: 1,
onStdout: (stdout) => {
stdout = stdout.replace(new RegExp('^(.*)npm/(webpack-batteries-included-preprocessor/node_modules/ts-loader/index.js)$', 'm'), ' * relative/path/to/$2')
stdout = stdout.replace(new RegExp('^(.*)npm/(webpack-preprocessor/dist/lib/cross-origin-callback-loader.js)$', 'm'), ' * relative/path/to/$2')
return systemTests.normalizeWebpackErrors(stdout)
},
+2 -1
View File
@@ -71,7 +71,8 @@ describe('e2e video compression', () => {
const durationMs = videoCapture.getMsFromDuration(duration)
expect(durationMs).to.be.ok
expect(durationMs).to.be.closeTo(EXPECTED_DURATION_MS, humanInterval('15 seconds'))
// TODO(origin): this was taking longer and failing in webkit
expect(durationMs).to.be.closeTo(EXPECTED_DURATION_MS, humanInterval('20 seconds'))
const { chapters } = await videoCapture.getChapters(files[0])
-15
View File
@@ -75,7 +75,6 @@ describe('e2e web security', () => {
browser: '!webkit', // TODO(webkit): fix+unskip
spec: 'web_security.cy.js',
config: {
experimentalSessionAndOrigin: false,
pageLoadTimeout: 5000,
},
snapshot: true,
@@ -88,7 +87,6 @@ describe('e2e web security', () => {
spec: 'web_security.cy.js',
config: {
chromeWebSecurity: false,
experimentalSessionAndOrigin: false,
},
snapshot: true,
browser: ['chrome', 'electron'],
@@ -109,17 +107,4 @@ describe('e2e web security', () => {
},
})
})
context('when experimentalSessionAndOrigin is enabled', () => {
systemTests.it('fails', {
browser: '!webkit', // TODO(webkit): fix+unskip Fixed by: https://github.com/cypress-io/cypress/issues/23532
spec: 'web_security.cy.js',
config: {
experimentalSessionAndOrigin: true,
defaultCommandTimeout: 50,
},
snapshot: true,
expectedExitCode: 4,
})
})
})