diff --git a/.node-version b/.node-version index d9617ea1b408..d7cb9ec3a764 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -16.5.0 \ No newline at end of file +16.13.2 \ No newline at end of file diff --git a/circle.yml b/circle.yml index 6d25a7b770bf..790087551e3c 100644 --- a/circle.yml +++ b/circle.yml @@ -39,6 +39,7 @@ macWorkflowFilters: &mac-workflow-filters or: - equal: [ develop, << pipeline.git.branch >> ] - equal: [ check-results-for-env, << pipeline.git.branch >> ] + - equal: [ tbiethman/chore/electron-18-update, << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -49,6 +50,7 @@ windowsWorkflowFilters: &windows-workflow-filters - equal: [ master, << pipeline.git.branch >> ] - equal: [ develop, << pipeline.git.branch >> ] - equal: [ check-results-for-env, << pipeline.git.branch >> ] + - equal: [ tbiethman/chore/electron-18-update, << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -60,7 +62,7 @@ executors: # the Docker image with Cypress dependencies and Chrome browser cy-doc: docker: - - image: cypress/browsers:node16.5.0-chrome94-ff93 + - image: cypress/browsers:node16.13.2-chrome100-ff98 # by default, we use "small" to save on CI costs. bump on a per-job basis if needed. resource_class: small environment: @@ -69,7 +71,7 @@ executors: # Docker image with non-root "node" user non-root-docker-user: docker: - - image: cypress/browsers:node16.5.0-chrome94-ff93 + - image: cypress/browsers:node16.13.2-chrome100-ff98 user: node environment: PLATFORM: linux @@ -371,8 +373,10 @@ commands: npm install yarn -g # ensure yarn is installed with the correct node engine yarn check-node-version - run: - name: Check Node - command: yarn check-node-version + name: Check Node + command: | + [ -s "${HOME}/.nvm/nvm.sh" ] && \. "${HOME}/.nvm/nvm.sh" + yarn check-node-version install-chrome: description: Install Google Chrome @@ -589,7 +593,11 @@ commands: ## by default, assert that at least 1 test ran default: 0 steps: - - run: yarn verify:mocha:results <> + - run: + name: 'Verify Mocha Results' + command: | + [ -s "${HOME}/.nvm/nvm.sh" ] && \. "${HOME}/.nvm/nvm.sh" + yarn verify:mocha:results <> clone-repo-and-checkout-release-branch: description: | @@ -896,7 +904,9 @@ commands: yarn binary-build --platform $PLATFORM --version $(node ./scripts/get-next-version.js) - run: name: Zip the binary - command: yarn binary-zip --platform $PLATFORM + command: | + apt-get update && apt-get install -y zip + yarn binary-zip --platform $PLATFORM - store-npm-logs - persist_to_workspace: root: ~/ @@ -1247,7 +1257,7 @@ jobs: runner-integration-tests-firefox: <<: *defaults - resource_class: medium + resource_class: medium+ parallelism: 2 steps: - run-runner-integration-tests: diff --git a/cli/test/lib/util_spec.js b/cli/test/lib/util_spec.js index 8412933170f6..0e44c4f0f4d4 100644 --- a/cli/test/lib/util_spec.js +++ b/cli/test/lib/util_spec.js @@ -267,7 +267,7 @@ describe('util', () => { }) it('copy NODE_OPTIONS to ORIGINAL_NODE_OPTIONS', () => { - sandbox.stub(process.versions, 'node').value('v16.5.0') + sandbox.stub(process.versions, 'node').value('v16.13.2') sandbox.stub(process.versions, 'openssl').value('1.0.0') restoreEnv = mockedEnv({ @@ -322,7 +322,7 @@ describe('util', () => { // https://github.com/cypress-io/cypress/issues/18914 it('does not include --openssl-legacy-provider in Node <=16', () => { - sandbox.stub(process.versions, 'node').value('v16.5.0') + sandbox.stub(process.versions, 'node').value('v16.13.2') sandbox.stub(process.versions, 'openssl').value('1.0.0') restoreEnv = mockedEnv({}) diff --git a/package.json b/package.json index 5c7ef86a5684..addde78c9bf6 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "yarn-deduplicate": "3.1.0" }, "engines": { - "node": ">=16.5.0", + "node": ">=16.13.2", "yarn": ">=1.17.3" }, "productName": "Cypress", diff --git a/packages/driver/cypress/fixtures/dom.html b/packages/driver/cypress/fixtures/dom.html index 819fc05167a9..433a337aacaa 100644 --- a/packages/driver/cypress/fixtures/dom.html +++ b/packages/driver/cypress/fixtures/dom.html @@ -114,6 +114,10 @@ width: 60px; } + /* normalizing li height across supported browsers */ + li { + height: 18px; + } DOM Fixture diff --git a/packages/driver/cypress/integration/commands/actions/trigger_spec.js b/packages/driver/cypress/integration/commands/actions/trigger_spec.js index b1423d7545d9..a984c663fbb1 100644 --- a/packages/driver/cypress/integration/commands/actions/trigger_spec.js +++ b/packages/driver/cypress/integration/commands/actions/trigger_spec.js @@ -589,13 +589,10 @@ describe('src/cy/commands/actions/trigger', () => { }) it('passes options.animationDistanceThreshold to cy.ensureElementIsNotAnimating', () => { - const $btn = cy.$$('button:first') - - const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($btn) - cy.spy(cy, 'ensureElementIsNotAnimating') - cy.get('button:first').trigger('tap', { animationDistanceThreshold: 1000 }).then(() => { + cy.get('button:first').trigger('tap', { animationDistanceThreshold: 1000 }).then(($btn) => { + const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($btn) const { args } = cy.ensureElementIsNotAnimating.firstCall expect(args[1]).to.deep.eq([fromElWindow, fromElWindow]) @@ -606,13 +603,10 @@ describe('src/cy/commands/actions/trigger', () => { it('passes config.animationDistanceThreshold to cy.ensureElementIsNotAnimating', () => { const animationDistanceThreshold = Cypress.config('animationDistanceThreshold') - const $btn = cy.$$('button:first') - - const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($btn) - cy.spy(cy, 'ensureElementIsNotAnimating') - cy.get('button:first').trigger('mouseover').then(() => { + cy.get('button:first').trigger('mouseover').then(($btn) => { + const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($btn) const { args } = cy.ensureElementIsNotAnimating.firstCall expect(args[1]).to.deep.eq([fromElWindow, fromElWindow]) diff --git a/packages/driver/cypress/integration/commands/actions/type_spec.js b/packages/driver/cypress/integration/commands/actions/type_spec.js index 20874e019a3b..2813da07ed32 100644 --- a/packages/driver/cypress/integration/commands/actions/type_spec.js +++ b/packages/driver/cypress/integration/commands/actions/type_spec.js @@ -351,13 +351,10 @@ describe('src/cy/commands/actions/type - #type', () => { }) it('passes options.animationDistanceThreshold to cy.ensureElementIsNotAnimating', () => { - const $txt = cy.$$(':text:first') - - const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($txt) - cy.spy(cy, 'ensureElementIsNotAnimating') - cy.get(':text:first').type('foo', { animationDistanceThreshold: 1000 }).then(() => { + cy.get(':text:first').type('foo', { animationDistanceThreshold: 1000 }).then(($txt) => { + const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($txt) const { args } = cy.ensureElementIsNotAnimating.firstCall expect(args[1]).to.deep.eq([fromElWindow, fromElWindow]) @@ -369,13 +366,10 @@ describe('src/cy/commands/actions/type - #type', () => { it('passes config.animationDistanceThreshold to cy.ensureElementIsNotAnimating', () => { const animationDistanceThreshold = Cypress.config('animationDistanceThreshold') - const $txt = cy.$$(':text:first') - - const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($txt) - cy.spy(cy, 'ensureElementIsNotAnimating') - cy.get(':text:first').type('foo').then(() => { + cy.get(':text:first').type('foo').then(($txt) => { + const { fromElWindow } = Cypress.dom.getElementCoordinatesByPosition($txt) const { args } = cy.ensureElementIsNotAnimating.firstCall expect(args[1]).to.deep.eq([fromElWindow, fromElWindow]) diff --git a/packages/driver/cypress/integration/e2e/origin/commands/navigation.spec.ts b/packages/driver/cypress/integration/e2e/origin/commands/navigation.spec.ts index 7faee1d43d8b..267a5b93f664 100644 --- a/packages/driver/cypress/integration/e2e/origin/commands/navigation.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/commands/navigation.spec.ts @@ -22,9 +22,18 @@ context('cy.origin navigation', () => { cy.get('a[data-cy="dom-link"]').click() cy.origin('http://foobar.com:3500', () => { - cy.get(':checkbox[name="colors"][value="blue"]').check().should('be.checked') + cy.window().then((localWindow) => { + // Define a custom property on window that we can assert the presence of. + // After reloading, this property should not exist. + // @ts-ignore + localWindow.cy_testCustomValue = true + }) + + cy.window().should('have.prop', 'cy_testCustomValue', true) + cy.reload() - cy.get(':checkbox[name="colors"][value="blue"]').should('not.be.checked') + + cy.window().should('not.have.prop', 'cy_testCustomValue', true) }) }) diff --git a/packages/driver/cypress/integration/e2e/origin/commands/spies_stubs_clocks.spec.ts b/packages/driver/cypress/integration/e2e/origin/commands/spies_stubs_clocks.spec.ts index ad06cd0f2f05..8719ca789749 100644 --- a/packages/driver/cypress/integration/e2e/origin/commands/spies_stubs_clocks.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/commands/spies_stubs_clocks.spec.ts @@ -6,6 +6,16 @@ context('cy.origin spies, stubs, and clock', () => { cy.get('a[data-cy="cross-origin-secondary-link"]').click() }) + afterEach(() => { + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We enqueue another cy command after each test to ensure stability + // is reached for the next test. This additional command can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + cy.then(() => { /* ensuring stability */ }) + }) + it('spy()', () => { cy.origin('http://foobar.com:3500', () => { const foo = { bar () { } } diff --git a/packages/driver/cypress/integration/e2e/origin/commands/unsupported_commands.spec.ts b/packages/driver/cypress/integration/e2e/origin/commands/unsupported_commands.spec.ts index facd558ef6e0..9afcca4672da 100644 --- a/packages/driver/cypress/integration/e2e/origin/commands/unsupported_commands.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/commands/unsupported_commands.spec.ts @@ -4,6 +4,16 @@ context('cy.origin unsupported commands', () => { cy.get('a[data-cy="cross-origin-secondary-link"]').click() }) + afterEach(() => { + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We enqueue another cy command after each test to ensure stability + // is reached for the next test. This additional command can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + cy.then(() => { /* ensuring stability */ }) + }) + it('cy.route() method is deprecated', (done) => { cy.on('fail', (err) => { expect(err.message).to.equal('`cy.route()` has been deprecated and its use is not supported in the `cy.origin()` callback. Consider using `cy.intercept()` (outside of the callback) instead.') diff --git a/packages/driver/cypress/integration/e2e/origin/config_env.spec.ts b/packages/driver/cypress/integration/e2e/origin/config_env.spec.ts index b0c767511650..07cf55373869 100644 --- a/packages/driver/cypress/integration/e2e/origin/config_env.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/config_env.spec.ts @@ -10,11 +10,6 @@ error: 'cy-origin-error', } - beforeEach(() => { - cy.visit('/fixtures/primary-origin.html') - cy.get('a[data-cy="cross-origin-secondary-link"]').click() - }) - afterEach(() => { // @ts-ignore window.top.__cySkipValidateConfig = true diff --git a/packages/driver/cypress/integration/e2e/origin/cypress_api.spec.ts b/packages/driver/cypress/integration/e2e/origin/cypress_api.spec.ts index ef8466b486d7..a31fd8afec21 100644 --- a/packages/driver/cypress/integration/e2e/origin/cypress_api.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/cypress_api.spec.ts @@ -6,6 +6,16 @@ describe('cy.origin Cypress API', () => { cy.get('a[data-cy="cross-origin-secondary-link"]').click() }) + afterEach(() => { + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We enqueue another cy command after each test to ensure stability + // is reached for the next test. This additional command can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + cy.then(() => { /* ensuring stability */ }) + }) + context('Commands', () => { it('adds a custom command', () => { cy.origin('http://foobar.com:3500', () => { diff --git a/packages/driver/cypress/integration/e2e/origin/logging.spec.ts b/packages/driver/cypress/integration/e2e/origin/logging.spec.ts index b6b57c3a0c2d..3121df5ef22a 100644 --- a/packages/driver/cypress/integration/e2e/origin/logging.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/logging.spec.ts @@ -42,7 +42,13 @@ describe('cy.origin logging', () => { expect(originLog.groupStart).to.be.true - done() + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We execute done after a brief timeout to ensure stability + // is reached for the next test. This timeout can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + setTimeout(done, 0) }) cy.visit('/fixtures/primary-origin.html') @@ -64,7 +70,13 @@ describe('cy.origin logging', () => { expect(originLog.groupStart).to.be.true - done() + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We execute done after a brief timeout to ensure stability + // is reached for the next test. This timeout can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + setTimeout(done, 0) }) cy.visit('/fixtures/primary-origin.html') diff --git a/packages/driver/cypress/integration/e2e/origin/origin.spec.ts b/packages/driver/cypress/integration/e2e/origin/origin.spec.ts index 4703b3531682..74b15a8647c6 100644 --- a/packages/driver/cypress/integration/e2e/origin/origin.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/origin.spec.ts @@ -1,4 +1,14 @@ describe('cy.origin', () => { + afterEach(() => { + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We enqueue another cy command after each test to ensure stability + // is reached for the next test. This additional command can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + cy.then(() => { /* ensuring stability */ }) + }) + it('passes viewportWidth/Height state to the secondary origin', () => { const expectedViewport = [320, 480] @@ -237,12 +247,13 @@ describe('cy.origin', () => { expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) expect(err.codeFrame).to.exist expect(err.codeFrame!.frame).to.include('cy.origin') + done() }) const variable = () => {} - cy.origin('http://idp.com:3500', { args: variable }, (variable) => { + cy.origin('http://foobar.com:3500', { args: variable }, (variable) => { variable() }) }) diff --git a/packages/driver/cypress/integration/e2e/origin/uncaught_errors.spec.ts b/packages/driver/cypress/integration/e2e/origin/uncaught_errors.spec.ts index 9c5d14a2a79a..946fee2c8af3 100644 --- a/packages/driver/cypress/integration/e2e/origin/uncaught_errors.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/uncaught_errors.spec.ts @@ -4,6 +4,16 @@ describe('cy.origin - uncaught errors', () => { cy.get('a[data-cy="errors-link"]').click() }) + afterEach(() => { + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We enqueue another cy command after each test to ensure stability + // is reached for the next test. This additional command can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + cy.then(() => { /* ensuring stability */ }) + }) + describe('sync errors', () => { it('appropriately reports negative assertions', (done) => { cy.on('fail', (err) => { diff --git a/packages/driver/cypress/integration/e2e/origin/yield.spec.ts b/packages/driver/cypress/integration/e2e/origin/yield.spec.ts index be04412b54d8..6a9af945fde2 100644 --- a/packages/driver/cypress/integration/e2e/origin/yield.spec.ts +++ b/packages/driver/cypress/integration/e2e/origin/yield.spec.ts @@ -14,6 +14,16 @@ describe('cy.origin yields', () => { cy.get('a[data-cy="cross-origin-secondary-link"]').click() }) + afterEach(() => { + // FIXME: Tests that end with a cy.origin command and enqueue no further cy + // commands may have origin's unload event bleed into subsequent tests + // and prevent stability from being reached, causing those tests to hang. + // We enqueue another cy command after each test to ensure stability + // is reached for the next test. This additional command can be removed with the + // completion of: https://github.com/cypress-io/cypress/issues/21300 + cy.then(() => { /* ensuring stability */ }) + }) + it('yields a value', () => { cy.origin('http://foobar.com:3500', () => { cy diff --git a/packages/driver/src/cy/commands/actions/type.ts b/packages/driver/src/cy/commands/actions/type.ts index 7d4753e79794..9b083b55fdf8 100644 --- a/packages/driver/src/cy/commands/actions/type.ts +++ b/packages/driver/src/cy/commands/actions/type.ts @@ -360,9 +360,10 @@ export default function (Commands, Cypress, cy, state, config) { // We don't want to send it twice. !Cypress.isBrowser('firefox') || // After Firefox 98, - // it sends a click event automatically if the element is a