mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-04 05:29:45 -06:00
Merge branch 'release/13.0.0' of https://github.com/cypress-io/cypress into chore/merge_develop_into_release_13
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
# Bump this version to force CI to re-create the cache from scratch.
|
||||
|
||||
08-10-23
|
||||
08-10-23
|
||||
|
||||
@@ -31,7 +31,7 @@ mainBuildFilters: &mainBuildFilters
|
||||
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
|
||||
- 'update-v8-snapshot-cache-on-develop'
|
||||
- 'publish-binary'
|
||||
- 'chore/merge_develop_into_release_13'
|
||||
- 'ryanm/feat/remove-protocol-environment-variable-from-binary'
|
||||
|
||||
# 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
|
||||
@@ -42,7 +42,7 @@ macWorkflowFilters: &darwin-workflow-filters
|
||||
- equal: [ develop, << pipeline.git.branch >> ]
|
||||
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
|
||||
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
|
||||
- equal: [ 'chore/merge_develop_into_release_13', << pipeline.git.branch >> ]
|
||||
- equal: [ 'ryanm/feat/remove-protocol-environment-variable-from-binary', << pipeline.git.branch >> ]
|
||||
- matches:
|
||||
pattern: /^release\/\d+\.\d+\.\d+$/
|
||||
value: << pipeline.git.branch >>
|
||||
@@ -53,6 +53,11 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
|
||||
- equal: [ develop, << pipeline.git.branch >> ]
|
||||
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
|
||||
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
|
||||
- equal: [ 'publish-binary', << pipeline.git.branch >> ]
|
||||
- equal: [ 'ryanm/feat/remove-protocol-environment-variable-from-binary', << pipeline.git.branch >> ]
|
||||
- matches:
|
||||
pattern: /^release\/\d+\.\d+\.\d+$/
|
||||
value: << pipeline.git.branch >>
|
||||
|
||||
# uncomment & add to the branch conditions below to disable the main linux
|
||||
# flow if we don't want to test it for a certain branch
|
||||
@@ -69,7 +74,7 @@ windowsWorkflowFilters: &windows-workflow-filters
|
||||
- equal: [ develop, << pipeline.git.branch >> ]
|
||||
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
|
||||
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
|
||||
- equal: [ 'chore/merge_develop_into_release_13', << pipeline.git.branch >> ]
|
||||
- equal: [ 'ryanm/feat/remove-protocol-environment-variable-from-binary', << pipeline.git.branch >> ]
|
||||
- matches:
|
||||
pattern: /^release\/\d+\.\d+\.\d+$/
|
||||
value: << pipeline.git.branch >>
|
||||
@@ -139,7 +144,7 @@ commands:
|
||||
name: Set environment variable to determine whether or not to persist artifacts
|
||||
command: |
|
||||
echo "Setting SHOULD_PERSIST_ARTIFACTS variable"
|
||||
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "publish-binary" && "$CIRCLE_BRANCH" != "update-v8-snapshot-cache-on-develop" && "$CIRCLE_BRANCH" != "chore/merge_develop_into_release_13" ]]; then
|
||||
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "publish-binary" && "$CIRCLE_BRANCH" != "update-v8-snapshot-cache-on-develop" && "$CIRCLE_BRANCH" != "ryanm/feat/remove-protocol-environment-variable-from-binary" ]]; then
|
||||
export SHOULD_PERSIST_ARTIFACTS=true
|
||||
fi' >> "$BASH_ENV"
|
||||
# You must run `setup_should_persist_artifacts` command and be using bash before running this command
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('Reporter Header', () => {
|
||||
cy.get('body').type('f')
|
||||
|
||||
cy.get('[data-selected-spec="true"]').should('contain', 'dom-content').should('have.length', '1')
|
||||
cy.get('[data-selected-spec="false"]').should('have.length', '29')
|
||||
cy.get('[data-selected-spec="false"]').should('have.length', '30')
|
||||
})
|
||||
|
||||
// TODO: Reenable as part of https://github.com/cypress-io/cypress/issues/23902
|
||||
|
||||
@@ -152,7 +152,7 @@ describe('App: Spec List (E2E)', () => {
|
||||
|
||||
it('displays only matching spec', function () {
|
||||
cy.get('button')
|
||||
.contains('25 matches')
|
||||
.contains('26 matches')
|
||||
.should('not.contain.text', 'of')
|
||||
|
||||
clearSearchAndType('content')
|
||||
@@ -160,13 +160,13 @@ describe('App: Spec List (E2E)', () => {
|
||||
.should('have.length', 3)
|
||||
.and('contain', 'dom-content.spec.js')
|
||||
|
||||
cy.get('button').contains('3 of 25 matches')
|
||||
cy.get('button').contains('3 of 26 matches')
|
||||
|
||||
cy.findByLabelText('Search specs').clear().type('asdf')
|
||||
cy.findAllByTestId('spec-item')
|
||||
.should('have.length', 0)
|
||||
|
||||
cy.get('button').contains('0 of 25 matches')
|
||||
cy.get('button').contains('0 of 26 matches')
|
||||
})
|
||||
|
||||
it('only shows matching folders', () => {
|
||||
@@ -217,7 +217,7 @@ describe('App: Spec List (E2E)', () => {
|
||||
cy.findByLabelText('Search specs')
|
||||
.should('have.value', '')
|
||||
|
||||
cy.get('button').contains('25 matches')
|
||||
cy.get('button').contains('26 matches')
|
||||
})
|
||||
|
||||
it('clears the filter if the user presses ESC key', function () {
|
||||
@@ -226,7 +226,7 @@ describe('App: Spec List (E2E)', () => {
|
||||
|
||||
cy.get('@searchField').should('have.value', '')
|
||||
|
||||
cy.get('button').contains('25 matches')
|
||||
cy.get('button').contains('26 matches')
|
||||
})
|
||||
|
||||
it('shows empty message if no results', function () {
|
||||
@@ -242,7 +242,7 @@ describe('App: Spec List (E2E)', () => {
|
||||
cy.findByText('Clear search').click()
|
||||
cy.focused().should('have.id', 'spec-filter')
|
||||
|
||||
cy.get('button').contains('25 matches')
|
||||
cy.get('button').contains('26 matches')
|
||||
})
|
||||
|
||||
it('normalizes directory path separators for Windows', function () {
|
||||
|
||||
@@ -76,6 +76,7 @@ describe('specChange subscription', () => {
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin_users_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin.user/foo_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation-describe-config.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z001.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z002.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z003.spec.js'),
|
||||
@@ -120,6 +121,7 @@ describe('specChange subscription', () => {
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin_users_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin.user/foo_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation-describe-config.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z001.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z002.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z003.spec.js'),
|
||||
@@ -190,7 +192,7 @@ e2e: {
|
||||
|
||||
cy.get('body').type('f')
|
||||
cy.get('[data-cy="spec-file-item"]')
|
||||
.should('have.length', 25)
|
||||
.should('have.length', 26)
|
||||
.should('contain', 'blank-contents.spec.js')
|
||||
.should('contain', 'dom-container.spec.js')
|
||||
.should('contain', 'dom-content.spec.js')
|
||||
@@ -201,7 +203,7 @@ e2e: {
|
||||
}, { path: getPathForPlatform('cypress/e2e/new-file.spec.js') })
|
||||
|
||||
cy.get('[data-cy="spec-file-item"]')
|
||||
.should('have.length', 26)
|
||||
.should('have.length', 27)
|
||||
.should('contain', 'blank-contents.spec.js')
|
||||
.should('contain', 'dom-container.spec.js')
|
||||
.should('contain', 'dom-content.spec.js')
|
||||
@@ -216,7 +218,7 @@ e2e: {
|
||||
|
||||
cy.get('body').type('f')
|
||||
cy.get('[data-cy="spec-file-item"]')
|
||||
.should('have.length', 25)
|
||||
.should('have.length', 26)
|
||||
.should('contain', 'blank-contents.spec.js')
|
||||
.should('contain', 'dom-container.spec.js')
|
||||
.should('contain', 'dom-content.spec.js')
|
||||
@@ -227,7 +229,7 @@ e2e: {
|
||||
}, { path: getPathForPlatform('cypress/e2e/dom-list.spec.js') })
|
||||
|
||||
cy.get('[data-cy="spec-file-item"]')
|
||||
.should('have.length', 24)
|
||||
.should('have.length', 25)
|
||||
.should('contain', 'blank-contents.spec.js')
|
||||
.should('contain', 'dom-container.spec.js')
|
||||
.should('contain', 'dom-content.spec.js')
|
||||
@@ -258,6 +260,7 @@ e2e: {
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin_users_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin.user/foo_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation-describe-config.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z001.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z002.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z003.spec.js'),
|
||||
@@ -289,7 +292,7 @@ e2e: {
|
||||
|
||||
cy.get('body').type('f')
|
||||
cy.get('[data-cy="spec-file-item"]')
|
||||
.should('have.length', 25)
|
||||
.should('have.length', 26)
|
||||
.should('contain', 'blank-contents.spec.js')
|
||||
.should('contain', 'dom-container.spec.js')
|
||||
.should('contain', 'dom-content.spec.js')
|
||||
@@ -332,14 +335,14 @@ e2e: {
|
||||
cy.get('[data-cy="spec-pattern"]').contains('cypress/e2e/**/*.spec.{js,ts}')
|
||||
|
||||
cy.get('[data-cy="file-match-indicator"]')
|
||||
.should('contain', '25 matches')
|
||||
.should('contain', '26 matches')
|
||||
|
||||
cy.withCtx(async (ctx, o) => {
|
||||
await ctx.actions.file.writeFileInProject(o.path, '')
|
||||
}, { path: getPathForPlatform('cypress/e2e/new-file.spec.js') })
|
||||
|
||||
cy.get('[data-cy="file-match-indicator"]')
|
||||
.should('contain', '26 matches')
|
||||
.should('contain', '27 matches')
|
||||
})
|
||||
|
||||
it('responds to specChange event for a removed file', () => {
|
||||
@@ -349,14 +352,14 @@ e2e: {
|
||||
cy.get('[data-cy="spec-pattern"]').contains('cypress/e2e/**/*.spec.{js,ts}')
|
||||
|
||||
cy.get('[data-cy="file-match-indicator"]')
|
||||
.should('contain', '25 matches')
|
||||
.should('contain', '26 matches')
|
||||
|
||||
cy.withCtx(async (ctx, o) => {
|
||||
await ctx.actions.file.removeFileInProject(o.path)
|
||||
}, { path: getPathForPlatform('cypress/e2e/dom-list.spec.js') })
|
||||
|
||||
cy.get('[data-cy="file-match-indicator"]')
|
||||
.should('contain', '24 matches')
|
||||
.should('contain', '25 matches')
|
||||
})
|
||||
|
||||
it('handles removing the last file', () => {
|
||||
@@ -384,6 +387,7 @@ e2e: {
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin_users_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/admin_users/admin.user/foo_list.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/test-isolation-describe-config.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z001.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z002.spec.js'),
|
||||
getPathForPlatform('cypress/e2e/z003.spec.js'),
|
||||
@@ -414,7 +418,7 @@ e2e: {
|
||||
cy.get('[data-cy="spec-pattern"]').contains('cypress/e2e/**/*.spec.{js,ts}')
|
||||
|
||||
cy.get('[data-cy="file-match-indicator"]')
|
||||
.should('contain', '25 matches')
|
||||
.should('contain', '26 matches')
|
||||
|
||||
cy.withCtx(async (ctx) => {
|
||||
await ctx.actions.file.writeFileInProject('cypress.config.js',
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
.then(async () => {
|
||||
cy.spy(Cypress, 'action').log(false)
|
||||
|
||||
await Cypress.action('runner:test:before:after:run:async', {}, Cypress.state('runnable'))
|
||||
await Cypress.action('runner:test:before:after:run:async', {}, Cypress.state('runnable'), { nextTestHasTestIsolationOn: true })
|
||||
|
||||
expect(Cypress.action).to.be.calledWith('cy:url:changed', '')
|
||||
expect(Cypress.action).to.be.calledWith('cy:visit:blank', { testIsolation: true })
|
||||
@@ -68,7 +68,21 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
.should('eq', 'about:blank')
|
||||
})
|
||||
|
||||
it('clears the browser cookie before each run', () => {
|
||||
it('does not clear the page before the end of each run if the next test has test isolation off', () => {
|
||||
cy.visit('/fixtures/form.html')
|
||||
.then(async () => {
|
||||
cy.spy(Cypress, 'action').log(false)
|
||||
|
||||
await Cypress.action('runner:test:before:after:run:async', {}, Cypress.state('runnable'), { nextTestHasTestIsolationOn: false })
|
||||
|
||||
expect(Cypress.action).not.to.be.calledWith('cy:url:changed', '')
|
||||
expect(Cypress.action).not.to.be.calledWith('cy:visit:blank', { testIsolation: true })
|
||||
})
|
||||
.url()
|
||||
.should('not.eq', 'about:blank')
|
||||
})
|
||||
|
||||
it('clears the browser cookie after each run', () => {
|
||||
cy.window()
|
||||
.then((win) => {
|
||||
win.cookie = 'key=value; SameSite=Strict; Secure; Path=/fixtures'
|
||||
@@ -76,11 +90,25 @@ describe('cy.session', { retries: 0 }, () => {
|
||||
.then(async () => {
|
||||
cy.spy(Cypress, 'action').log(false)
|
||||
|
||||
await Cypress.action('runner:test:before:after:run:async', {}, Cypress.state('runnable'))
|
||||
await Cypress.action('runner:test:before:after:run:async', {}, Cypress.state('runnable'), { nextTestHasTestIsolationOn: true })
|
||||
})
|
||||
|
||||
cy.window().its('cookie').should('be.undefined')
|
||||
})
|
||||
|
||||
it('does not clear the browser cookie after each run if the next test has test isolation off', () => {
|
||||
cy.window()
|
||||
.then((win) => {
|
||||
win.cookie = 'key=value; SameSite=Strict; Secure; Path=/fixtures'
|
||||
})
|
||||
.then(async () => {
|
||||
cy.spy(Cypress, 'action').log(false)
|
||||
|
||||
await Cypress.action('runner:test:before:after:run:async', {}, Cypress.state('runnable'), { nextTestHasTestIsolationOn: false })
|
||||
})
|
||||
|
||||
cy.window().its('cookie').should('eq', 'key=value; SameSite=Strict; Secure; Path=/fixtures')
|
||||
})
|
||||
})
|
||||
|
||||
describe('test:before:run:async', () => {
|
||||
|
||||
@@ -32,12 +32,12 @@ export default function (Commands, Cypress, cy) {
|
||||
}
|
||||
})
|
||||
|
||||
Cypress.on('test:before:after:run:async', () => {
|
||||
if (!Cypress.config('testIsolation')) {
|
||||
return
|
||||
Cypress.on('test:before:after:run:async', (test, Cypress, { nextTestHasTestIsolationOn }: {nextTestHasTestIsolationOn?: boolean} = {}) => {
|
||||
if (nextTestHasTestIsolationOn) {
|
||||
return navigateAboutBlank({ inBetweenTestsAndNextTestHasTestIsolationOn: true })
|
||||
}
|
||||
|
||||
return navigateAboutBlank()
|
||||
return
|
||||
})
|
||||
|
||||
Cypress.on('test:before:run:async', async () => {
|
||||
|
||||
@@ -191,9 +191,11 @@ const getPostMessageLocalStorage = (specWindow, origins): Promise<any[]> => {
|
||||
})
|
||||
}
|
||||
|
||||
function navigateAboutBlank () {
|
||||
// Component testing does not support navigation and handles clearing the page via mount utils
|
||||
if (Cypress.testingType === 'component' || !Cypress.config('testIsolation')) {
|
||||
function navigateAboutBlank ({ inBetweenTestsAndNextTestHasTestIsolationOn }: { inBetweenTestsAndNextTestHasTestIsolationOn?: boolean } = {}) {
|
||||
// Component testing never supports navigating to about:blank as that is handled by its unmount mechanism
|
||||
// When test isolation is off we typically don't navigate to about blank; however if we are in between tests and the next
|
||||
// test has test isolation on, we need to navigate to about blank to ensure the next test is not affected by the previous test
|
||||
if (Cypress.testingType === 'component' || (!Cypress.config('testIsolation') && !inBetweenTestsAndNextTestHasTestIsolationOn)) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ const duration = (before: Date, after: Date) => {
|
||||
return Number(before) - Number(after)
|
||||
}
|
||||
|
||||
const fire = (event: typeof RUNNER_EVENTS[number], runnable, Cypress) => {
|
||||
const fire = (event: typeof RUNNER_EVENTS[number], runnable, Cypress, ...args) => {
|
||||
debug('fire: %o', { event })
|
||||
if (runnable._fired == null) {
|
||||
runnable._fired = {}
|
||||
@@ -59,7 +59,7 @@ const fire = (event: typeof RUNNER_EVENTS[number], runnable, Cypress) => {
|
||||
return
|
||||
}
|
||||
|
||||
return Cypress.action(event, wrap(runnable), runnable)
|
||||
return Cypress.action(event, wrap(runnable), runnable, ...args)
|
||||
}
|
||||
|
||||
const fired = (event: typeof RUNNER_EVENTS[number], runnable) => {
|
||||
@@ -74,10 +74,10 @@ const testBeforeRunAsync = (test, Cypress) => {
|
||||
})
|
||||
}
|
||||
|
||||
const testBeforeAfterRunAsync = (test, Cypress) => {
|
||||
const testBeforeAfterRunAsync = (test, Cypress, ...args) => {
|
||||
return Promise.try(() => {
|
||||
if (!fired(TEST_BEFORE_AFTER_RUN_ASYNC_EVENT, test)) {
|
||||
return fire(TEST_BEFORE_AFTER_RUN_ASYNC_EVENT, test, Cypress)
|
||||
return fire(TEST_BEFORE_AFTER_RUN_ASYNC_EVENT, test, Cypress, ...args)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -369,6 +369,16 @@ const lastTestThatWillRunInSuite = (test, tests) => {
|
||||
return isLastTest(test, tests) || (test.failedFromHookId && (test.hookName === 'before all'))
|
||||
}
|
||||
|
||||
const nextTestThatWillRunInSuite = (test, tests) => {
|
||||
if (test.failedFromHookId && (test.hookName === 'before all')) {
|
||||
return null
|
||||
}
|
||||
|
||||
const index = _.findIndex(tests, { id: test.id })
|
||||
|
||||
return index < tests.length - 1 ? tests[index + 1] : null
|
||||
}
|
||||
|
||||
const isLastTest = (test, tests) => {
|
||||
return test.id === _.get(_.last(tests), 'id')
|
||||
}
|
||||
@@ -497,6 +507,11 @@ const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, get
|
||||
// If we're not in open mode or we're in open mode and not the last test we reset state.
|
||||
// The last test will needs to stay so that the user can see what the end result of the AUT was.
|
||||
if (shouldAlwaysResetPage || !lastTestThatWillRunInSuite(test, getAllSiblingTests(topSuite, getTestById))) {
|
||||
const nextTest = nextTestThatWillRunInSuite(test, getAllSiblingTests(topSuite, getTestById))
|
||||
const nextTestIsolationOverride = nextTest?._testConfig.unverifiedTestConfig.testIsolation
|
||||
const topLevelTestIsolation = Cypress.originalConfig['testIsolation']
|
||||
const nextTestHasTestIsolationOn = nextTestIsolationOverride || (nextTestIsolationOverride === undefined && topLevelTestIsolation)
|
||||
|
||||
cy.state('duringUserTestExecution', false)
|
||||
Cypress.primaryOriginCommunicator.toAllSpecBridges('sync:state', { 'duringUserTestExecution': false })
|
||||
// Remove window:load and window:before:load listeners so that navigating to about:blank doesn't fire in user code.
|
||||
@@ -505,7 +520,7 @@ const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, get
|
||||
cy.removeAllListeners('window:load')
|
||||
|
||||
// This will navigate to about:blank if test isolation is on
|
||||
await testBeforeAfterRunAsync(test, Cypress)
|
||||
await testBeforeAfterRunAsync(test, Cypress, { nextTestHasTestIsolationOn })
|
||||
}
|
||||
|
||||
testAfterRun(test, Cypress)
|
||||
|
||||
@@ -633,7 +633,6 @@ module.exports = {
|
||||
},
|
||||
|
||||
getCaptureProtocolScript (url: string) {
|
||||
// TODO(protocol): Ensure this is removed in production
|
||||
if (process.env.CYPRESS_LOCAL_PROTOCOL_PATH) {
|
||||
debugProtocol(`Loading protocol via script at local path %s`, process.env.CYPRESS_LOCAL_PROTOCOL_PATH)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ const path = require('path')
|
||||
const { setupV8Snapshots } = require('@tooling/v8-snapshot')
|
||||
const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses')
|
||||
const { buildEntryPointAndCleanup } = require('./binary/binary-cleanup')
|
||||
const { getIntegrityCheckSource, getBinaryEntryPointSource, getEncryptionFileSource, getCloudApiFileSource, validateEncryptionFile } = require('./binary/binary-sources')
|
||||
const { getIntegrityCheckSource, getBinaryEntryPointSource, getEncryptionFileSource, getCloudEnvironmentFileSource, validateEncryptionFile, getProtocolFileSource, validateCloudEnvironmentFile, validateProtocolFile } = require('./binary/binary-sources')
|
||||
|
||||
const CY_ROOT_DIR = path.join(__dirname, '..')
|
||||
|
||||
@@ -61,18 +61,26 @@ module.exports = async function (params) {
|
||||
const binaryEntryPointSource = await getBinaryEntryPointSource()
|
||||
const encryptionFilePath = path.join(CY_ROOT_DIR, 'packages/server/lib/cloud/encryption.ts')
|
||||
const encryptionFileSource = await getEncryptionFileSource(encryptionFilePath)
|
||||
const cloudApiFilePath = path.join(CY_ROOT_DIR, 'packages/server/lib/cloud/environment.ts')
|
||||
const cloudApiFileSource = await getCloudApiFileSource(cloudApiFilePath)
|
||||
const cloudEnvironmentFilePath = path.join(CY_ROOT_DIR, 'packages/server/lib/cloud/environment.ts')
|
||||
const cloudEnvironmentFileSource = await getCloudEnvironmentFileSource(cloudEnvironmentFilePath)
|
||||
const cloudApiFilePath = path.join(CY_ROOT_DIR, 'packages/server/lib/cloud/api.ts')
|
||||
const cloudApiFileSource = await getProtocolFileSource(cloudApiFilePath)
|
||||
const cloudProtocolFilePath = path.join(CY_ROOT_DIR, 'packages/server/lib/cloud/protocol.ts')
|
||||
const cloudProtocolFileSource = await getProtocolFileSource(cloudProtocolFilePath)
|
||||
|
||||
await Promise.all([
|
||||
fs.writeFile(encryptionFilePath, encryptionFileSource),
|
||||
fs.writeFile(cloudEnvironmentFilePath, cloudEnvironmentFileSource),
|
||||
fs.writeFile(cloudApiFilePath, cloudApiFileSource),
|
||||
fs.writeFile(cloudProtocolFilePath, cloudProtocolFileSource),
|
||||
fs.writeFile(path.join(outputFolder, 'index.js'), binaryEntryPointSource),
|
||||
])
|
||||
|
||||
await Promise.all([
|
||||
validateEncryptionFile(encryptionFilePath),
|
||||
validateEncryptionFile(cloudApiFilePath),
|
||||
validateCloudEnvironmentFile(cloudEnvironmentFilePath),
|
||||
validateProtocolFile(cloudApiFilePath),
|
||||
validateProtocolFile(cloudProtocolFilePath),
|
||||
])
|
||||
|
||||
await flipFuses(
|
||||
|
||||
@@ -58,7 +58,7 @@ const validateEncryptionFile = async (encryptionFilePath) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getCloudApiFileSource = async (cloudApiFilePath) => {
|
||||
const getCloudEnvironmentFileSource = async (cloudApiFilePath) => {
|
||||
const fileContents = await fs.readFile(cloudApiFilePath, 'utf8')
|
||||
|
||||
if (!fileContents.includes('process.env.CYPRESS_ENV_DEPENDENCIES')) {
|
||||
@@ -72,7 +72,7 @@ const getCloudApiFileSource = async (cloudApiFilePath) => {
|
||||
return fileContents
|
||||
}
|
||||
|
||||
const validateCloudApiFile = async (cloudApiFilePath) => {
|
||||
const validateCloudEnvironmentFile = async (cloudApiFilePath) => {
|
||||
if (process.env.CYPRESS_ENV_DEPENDENCIES) {
|
||||
const afterReplaceCloudApi = await fs.readFile(cloudApiFilePath, 'utf8')
|
||||
|
||||
@@ -82,11 +82,31 @@ const validateCloudApiFile = async (cloudApiFilePath) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getProtocolFileSource = async (protocolFilePath) => {
|
||||
const fileContents = await fs.readFile(protocolFilePath, 'utf8')
|
||||
|
||||
if (!fileContents.includes('process.env.CYPRESS_LOCAL_PROTOCOL_PATH')) {
|
||||
throw new Error(`Expected to find CYPRESS_LOCAL_PROTOCOL_PATH in protocol file`)
|
||||
}
|
||||
|
||||
return fileContents.replaceAll('process.env.CYPRESS_LOCAL_PROTOCOL_PATH', 'undefined')
|
||||
}
|
||||
|
||||
const validateProtocolFile = async (protocolFilePath) => {
|
||||
const afterReplaceProtocol = await fs.readFile(protocolFilePath, 'utf8')
|
||||
|
||||
if (afterReplaceProtocol.includes('process.env.CYPRESS_LOCAL_PROTOCOL_PATH')) {
|
||||
throw new Error(`Expected process.env.CYPRESS_LOCAL_PROTOCOL_PATH to be stripped from protocol file`)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getBinaryEntryPointSource,
|
||||
getIntegrityCheckSource,
|
||||
getEncryptionFileSource,
|
||||
getCloudApiFileSource,
|
||||
validateCloudApiFile,
|
||||
validateEncryptionFile,
|
||||
getCloudEnvironmentFileSource,
|
||||
validateCloudEnvironmentFile,
|
||||
getProtocolFileSource,
|
||||
validateProtocolFile,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
const shouldAlwaysResetPage = (config) => {
|
||||
const isRunMode = !config('isInteractive')
|
||||
const isHeadedNoExit = config('browser').isHeaded && !config('exit')
|
||||
|
||||
return isRunMode && !isHeadedNoExit
|
||||
}
|
||||
|
||||
const TEST_METADATA = {
|
||||
'passes 1': {
|
||||
start: 'about:blank',
|
||||
firesTestBeforeAfterRunAsync: true,
|
||||
end: 'about:blank',
|
||||
},
|
||||
'passes 2': {
|
||||
start: 'about:blank',
|
||||
firesTestBeforeAfterRunAsync: true,
|
||||
end: '/cypress/e2e/dom-content.html',
|
||||
},
|
||||
'passes 3': {
|
||||
start: '/cypress/e2e/dom-content.html',
|
||||
firesTestBeforeAfterRunAsync: true,
|
||||
end: '/cypress/e2e/dom-content.html',
|
||||
},
|
||||
'passes 4': {
|
||||
start: '/cypress/e2e/dom-content.html',
|
||||
firesTestBeforeAfterRunAsync: true,
|
||||
end: 'about:blank',
|
||||
},
|
||||
'passes 5': {
|
||||
start: 'about:blank',
|
||||
firesTestBeforeAfterRunAsync: true,
|
||||
end: 'about:blank',
|
||||
},
|
||||
'passes 6': {
|
||||
start: 'about:blank',
|
||||
firesTestBeforeAfterRunAsync: true,
|
||||
end: shouldAlwaysResetPage(Cypress.config) ? 'about:blank' : '/cypress/e2e/dom-content.html',
|
||||
},
|
||||
}
|
||||
|
||||
let cypressEventsHandled = 0
|
||||
|
||||
const testBeforeRun = (Cypress, ...args) => {
|
||||
expect(Cypress.state('window').location.href.endsWith(TEST_METADATA[args[1].title].start)).to.equal(true)
|
||||
cypressEventsHandled += 1
|
||||
}
|
||||
|
||||
const testBeforeRunAsync = (Cypress, ...args) => {
|
||||
expect(Cypress.state('window').location.href.endsWith(TEST_METADATA[args[1].title].start)).to.equal(true)
|
||||
cypressEventsHandled += 1
|
||||
}
|
||||
|
||||
const testBeforeAfterRunAsync = (Cypress, ...args) => {
|
||||
expect(TEST_METADATA[args[1].title].firesTestBeforeAfterRunAsync).to.be.true
|
||||
cypressEventsHandled += 1
|
||||
}
|
||||
|
||||
const testAfterRun = (Cypress, ...args) => {
|
||||
expect(Cypress.state('window').location.href.endsWith(TEST_METADATA[args[1].title].end)).to.equal(true)
|
||||
cypressEventsHandled += 1
|
||||
}
|
||||
|
||||
const testAfterRunAsync = (Cypress, ...args) => {
|
||||
expect(Cypress.state('window').location.href.endsWith(TEST_METADATA[args[1].title].end)).to.equal(true)
|
||||
cypressEventsHandled += 1
|
||||
}
|
||||
|
||||
const cypressEvents = [
|
||||
['test:before:run', testBeforeRun],
|
||||
['test:before:run:async', testBeforeRunAsync],
|
||||
['test:before:after:run:async', testBeforeAfterRunAsync],
|
||||
['test:after:run', testAfterRun],
|
||||
['test:after:run:async', testAfterRunAsync],
|
||||
]
|
||||
|
||||
cypressEvents.forEach(([event, handler]) => {
|
||||
Cypress.prependListener(event, (...args) => {
|
||||
handler(Cypress, ...args)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.on('test:after:run:async', async (test) => {
|
||||
if (test.title === 'passes 1') {
|
||||
expect(cypressEventsHandled).to.equal(5)
|
||||
} else if (test.title === 'passes 2') {
|
||||
expect(cypressEventsHandled).to.equal(10)
|
||||
} else if (test.title === 'passes 3') {
|
||||
expect(cypressEventsHandled).to.equal(15)
|
||||
} else if (test.title === 'passes 4') {
|
||||
expect(cypressEventsHandled).to.equal(20)
|
||||
} else if (test.title === 'passes 5') {
|
||||
expect(cypressEventsHandled).to.equal(25)
|
||||
} else if (test.title === 'passes 6') {
|
||||
expect(cypressEventsHandled).to.equal(!shouldAlwaysResetPage(Cypress.config) ? 29 : 30)
|
||||
}
|
||||
})
|
||||
|
||||
describe('test isolation', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('cypress/e2e/dom-content.html')
|
||||
})
|
||||
|
||||
describe('suite 1', { testIsolation: true }, () => {
|
||||
it('passes 1', () => {
|
||||
expect(true).to.equal(true)
|
||||
})
|
||||
|
||||
it('passes 2', () => {
|
||||
expect(true).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('suite 2', { testIsolation: false }, () => {
|
||||
it('passes 3', () => {
|
||||
expect(true).to.equal(true)
|
||||
})
|
||||
|
||||
it('passes 4', () => {
|
||||
expect(true).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('suite 3', { testIsolation: true }, () => {
|
||||
it('passes 5', () => {
|
||||
expect(true).to.equal(true)
|
||||
})
|
||||
|
||||
it('passes 6', () => {
|
||||
expect(true).to.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -12,6 +12,14 @@ describe('Test Isolation', () => {
|
||||
browser: 'chrome',
|
||||
})
|
||||
|
||||
systemTests.it('fires events in the right order with the right arguments when overridden within the spec - run mode', {
|
||||
project: 'cypress-in-cypress',
|
||||
spec: 'test-isolation-describe-config.spec.js',
|
||||
expectedExitCode: 0,
|
||||
timeout: 20000,
|
||||
browser: 'chrome',
|
||||
})
|
||||
|
||||
systemTests.it('fires events in the right order with the right arguments - headed: true - noExit: true', {
|
||||
config: {
|
||||
env: {
|
||||
|
||||
Reference in New Issue
Block a user