diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 2bd995b34e34..1660ab1782cd 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -10,8 +10,9 @@ _Released 03/28/2023 (PENDING)_ **Bugfixes:** - Fixed a compatibility issue so that component test projects can use [Vite](https://vitejs.dev/) version 4.2.0 and greater. Fixes [#26138](https://github.com/cypress-io/cypress/issues/26138). - - Changed the way that Git hashes are loaded so that non-relevant runs are excluded from the Debug page. Fixes [#26058](https://github.com/cypress-io/cypress/issues/26058). - Fixed an issue where [`cy.intercept()`](https://docs.cypress.io/api/commands/intercept) added an additional `content-length` header to spied requests that did not set a `content-length` header on the original request. Fixes [#24407](https://github.com/cypress-io/cypress/issues/24407). + - Changed the way that Git hashes are loaded so that non-relevant runs are excluded from the Debug page. Fixes [#26058](https://github.com/cypress-io/cypress/issues/26058). + - Corrected the [`.type()`](https://docs.cypress.io/api/commands/type) command to account for shadow root elements when determining whether or not focus needs to be simulated before typing. Fixes [#26198](https://github.com/cypress-io/cypress/issues/26198). - Fixed an issue where an incorrect working directory could be used for Git operations on Windows. Fixes [#23317](https://github.com/cypress-io/cypress/issues/23317). **Misc:** diff --git a/packages/driver/cypress/e2e/commands/actions/type.cy.js b/packages/driver/cypress/e2e/commands/actions/type.cy.js index 3c4171479c85..b91081568170 100644 --- a/packages/driver/cypress/e2e/commands/actions/type.cy.js +++ b/packages/driver/cypress/e2e/commands/actions/type.cy.js @@ -3092,5 +3092,17 @@ describe('src/cy/commands/actions/type - #type', () => { cy.get('#result').should('have.text', 'typed') }) + + // https://github.com/cypress-io/cypress/issues/26198 + it('type calls on elements in shadow dom do not fire click if the element already has focus', () => { + cy.visit('fixtures/shadow-dom-type.html') + + cy.get('test-element').shadow().find('input').as('input') + + cy.get('@input').invoke('on', 'click', cy.spy().as('clickSpy')) + cy.get('@input').focus().type('asdf') + + cy.get('@clickSpy').should('not.have.been.called') + }) }) }) diff --git a/packages/driver/cypress/e2e/dom/elements.cy.ts b/packages/driver/cypress/e2e/dom/elements.cy.ts index a7a08d2c0388..960617789c04 100644 --- a/packages/driver/cypress/e2e/dom/elements.cy.ts +++ b/packages/driver/cypress/e2e/dom/elements.cy.ts @@ -1,5 +1,5 @@ import $elements from '../../../src/dom/elements' -const { getActiveElByDocument, isFocused, elementFromPoint } = $elements +const { getActiveElByDocument, isFocused, elementFromPoint, isFocusedOrInFocused } = $elements const $ = window.Cypress.$ describe('src/dom/elements', () => { @@ -321,4 +321,14 @@ describe('src/dom/elements', () => { expect(elementFromPoint(doc, 1, 2)).to.equal(shadowHostNode) }) }) + + context('.isFocusedOrInFocused', () => { + it('should traverse shadow roots when determining if an element has focus', () => { + cy.visit('/fixtures/shadow-dom-type.html') + + cy.get('test-element').shadow().find('input').focus().then(($input) => { + expect(isFocusedOrInFocused($input[0])).to.be.true + }) + }) + }) }) diff --git a/packages/driver/src/dom/elements/complexElements.ts b/packages/driver/src/dom/elements/complexElements.ts index 51b735485a3f..10cfa37d4461 100644 --- a/packages/driver/src/dom/elements/complexElements.ts +++ b/packages/driver/src/dom/elements/complexElements.ts @@ -139,14 +139,21 @@ export const isFocusable = ($el: JQuery) => { export const isFocusedOrInFocused = (el: HTMLElement) => { debug('isFocusedOrInFocus', el) - const doc = $document.getDocumentFromElement(el) if (!doc.hasFocus()) { return false } - const { activeElement } = doc + let root: Document | ShadowRoot + + if (isWithinShadowRoot(el)) { + root = el.getRootNode() as ShadowRoot + } else { + root = doc + } + + let { activeElement } = root let elToCheckCurrentlyFocused