From 664124b86096676f2f4d84a552ed26fa826cb198 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Thu, 24 Jul 2025 14:42:18 -0400 Subject: [PATCH 1/4] breaking: Move getSelector, getSelectorPriority, and reset to private methods on ElementSelector API BREAKING: Move getSelector, getSelectorPriority, and reset to private methods on ElementSelector API --- cli/types/cypress.d.ts | 1 - packages/app/src/runner/aut-iframe.ts | 2 +- packages/app/src/store/studio-store.ts | 2 +- .../cypress/e2e/cypress/element_selector.cy.ts | 18 +++++++++++------- .../driver/src/cypress/element_selector.ts | 17 ++++++++++------- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 833f2a24d00..3837ebe3206 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -702,7 +702,6 @@ declare namespace Cypress { */ ElementSelector: { defaults(options: Partial): void - getSelector($el: JQuery): JQuery.Selector } /** diff --git a/packages/app/src/runner/aut-iframe.ts b/packages/app/src/runner/aut-iframe.ts index 9bb7a916d47..af8f24b3d9a 100644 --- a/packages/app/src/runner/aut-iframe.ts +++ b/packages/app/src/runner/aut-iframe.ts @@ -385,7 +385,7 @@ export class AutIframe { const Cypress = this.eventManager.getCypress() - const selector = Cypress.ElementSelector.getSelector($el) + const selector = Cypress.ElementSelector._getSelector($el) const selectorPlaygroundStore = useSelectorPlaygroundStore() this._addOrUpdateSelectorPlaygroundHighlight({ diff --git a/packages/app/src/store/studio-store.ts b/packages/app/src/store/studio-store.ts index d6c2b48078e..03213808f1a 100644 --- a/packages/app/src/store/studio-store.ts +++ b/packages/app/src/store/studio-store.ts @@ -520,7 +520,7 @@ export const useStudioStore = defineStore('studioRecorder', { if (!this._matchPreviousMouseEvent(target)) { this._previousMouseEvent = { element: target, - selector: getCypress().ElementSelector.getSelector(window.UnifiedRunner.CypressJQuery(target)), + selector: getCypress().ElementSelector._getSelector(window.UnifiedRunner.CypressJQuery(target)), } } }, diff --git a/packages/driver/cypress/e2e/cypress/element_selector.cy.ts b/packages/driver/cypress/e2e/cypress/element_selector.cy.ts index b0bf92b0741..09ffc2f9df1 100644 --- a/packages/driver/cypress/e2e/cypress/element_selector.cy.ts +++ b/packages/driver/cypress/e2e/cypress/element_selector.cy.ts @@ -2,23 +2,27 @@ import type { ElementSelectorAPI } from '../../../src/cypress/element_selector' import { DEFAULT_SELECTOR_PRIORITIES } from '../../../src/cypress/element_selector' const { $: $cypress } = Cypress.$Cypress -const ElementSelector = Cypress.ElementSelector as ElementSelectorAPI +const ElementSelector = Cypress.ElementSelector as ElementSelectorAPI & { + _reset(): void + _getSelectorPriority(): Cypress.SelectorPriority[] + _getSelector($el: any): string +} const SELECTOR_DEFAULTS: Cypress.SelectorPriority[] = [...DEFAULT_SELECTOR_PRIORITIES] describe('src/cypress/element_selector', () => { beforeEach(() => { - ElementSelector.reset() + ElementSelector._reset() }) it('has defaults', () => { - expect(ElementSelector.getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) + expect(ElementSelector._getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) }) context('.defaults', () => { it('is noop if not called with selectorPriority', () => { ElementSelector.defaults({}) - expect(ElementSelector.getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) + expect(ElementSelector._getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) }) it('sets element:selector:priority if selectorPriority specified', () => { @@ -39,7 +43,7 @@ describe('src/cypress/element_selector', () => { selectorPriority, }) - expect(ElementSelector.getSelectorPriority()).to.eql(selectorPriority) + expect(ElementSelector._getSelectorPriority()).to.eql(selectorPriority) }) it('throws if not passed an object', () => { @@ -108,13 +112,13 @@ describe('src/cypress/element_selector', () => { Cypress.$('body').append($div) - expect(ElementSelector.getSelector($div)).to.eq('[data-cy="main button 123"]') + expect(ElementSelector._getSelector($div)).to.eq('[data-cy="main button 123"]') ElementSelector.defaults({ selectorPriority: ['data-foo'], }) - expect(ElementSelector.getSelector($div)).to.eq('[data-foo="bar"]') + expect(ElementSelector._getSelector($div)).to.eq('[data-foo="bar"]') }) }) diff --git a/packages/driver/src/cypress/element_selector.ts b/packages/driver/src/cypress/element_selector.ts index 7e63da231b5..f4e66b2cdbc 100644 --- a/packages/driver/src/cypress/element_selector.ts +++ b/packages/driver/src/cypress/element_selector.ts @@ -29,12 +29,15 @@ export type ElementSelectorDefaultsOptions = { } export interface ElementSelectorAPI { - reset(): void - getSelectorPriority(): Cypress.SelectorPriority[] - getSelector($el: any): string defaults(options: ElementSelectorDefaultsOptions): void } +interface ElementSelectorPrivate { + _reset(): void + _getSelectorPriority(): Cypress.SelectorPriority[] + _getSelector($el: any): string +} + const reset = (): Defaults => { return { selectorPriority: [...DEFAULT_SELECTOR_PRIORITIES], @@ -43,16 +46,16 @@ const reset = (): Defaults => { let defaults = reset() -const ElementSelector: ElementSelectorAPI = { - reset () { +const ElementSelector: ElementSelectorAPI & ElementSelectorPrivate = { + _reset () { defaults = reset() }, - getSelectorPriority () { + _getSelectorPriority () { return defaults.selectorPriority }, - getSelector ($el: any) { + _getSelector ($el: any) { return uniqueSelector($el.get(0), { selectorTypes: defaults.selectorPriority, }) From 1fd58ce8c6788d04e5397baeb11766cbda9ea7d5 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Mon, 28 Jul 2025 12:59:32 -0400 Subject: [PATCH 2/4] Update getSelectorPriority back to public method --- .../driver/cypress/e2e/cypress/element_selector.cy.ts | 8 ++++---- packages/driver/src/cypress/element_selector.ts | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/driver/cypress/e2e/cypress/element_selector.cy.ts b/packages/driver/cypress/e2e/cypress/element_selector.cy.ts index 09ffc2f9df1..df3791b712d 100644 --- a/packages/driver/cypress/e2e/cypress/element_selector.cy.ts +++ b/packages/driver/cypress/e2e/cypress/element_selector.cy.ts @@ -4,7 +4,7 @@ import { DEFAULT_SELECTOR_PRIORITIES } from '../../../src/cypress/element_select const { $: $cypress } = Cypress.$Cypress const ElementSelector = Cypress.ElementSelector as ElementSelectorAPI & { _reset(): void - _getSelectorPriority(): Cypress.SelectorPriority[] + getSelectorPriority(): Cypress.SelectorPriority[] _getSelector($el: any): string } @@ -16,13 +16,13 @@ describe('src/cypress/element_selector', () => { }) it('has defaults', () => { - expect(ElementSelector._getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) + expect(ElementSelector.getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) }) context('.defaults', () => { it('is noop if not called with selectorPriority', () => { ElementSelector.defaults({}) - expect(ElementSelector._getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) + expect(ElementSelector.getSelectorPriority()).to.deep.eq(SELECTOR_DEFAULTS) }) it('sets element:selector:priority if selectorPriority specified', () => { @@ -43,7 +43,7 @@ describe('src/cypress/element_selector', () => { selectorPriority, }) - expect(ElementSelector._getSelectorPriority()).to.eql(selectorPriority) + expect(ElementSelector.getSelectorPriority()).to.eql(selectorPriority) }) it('throws if not passed an object', () => { diff --git a/packages/driver/src/cypress/element_selector.ts b/packages/driver/src/cypress/element_selector.ts index f4e66b2cdbc..d289d0137db 100644 --- a/packages/driver/src/cypress/element_selector.ts +++ b/packages/driver/src/cypress/element_selector.ts @@ -30,11 +30,11 @@ export type ElementSelectorDefaultsOptions = { export interface ElementSelectorAPI { defaults(options: ElementSelectorDefaultsOptions): void + getSelectorPriority(): Cypress.SelectorPriority[] } interface ElementSelectorPrivate { _reset(): void - _getSelectorPriority(): Cypress.SelectorPriority[] _getSelector($el: any): string } @@ -51,16 +51,16 @@ const ElementSelector: ElementSelectorAPI & ElementSelectorPrivate = { defaults = reset() }, - _getSelectorPriority () { - return defaults.selectorPriority - }, - _getSelector ($el: any) { return uniqueSelector($el.get(0), { selectorTypes: defaults.selectorPriority, }) }, + getSelectorPriority () { + return defaults.selectorPriority + }, + defaults (props: ElementSelectorDefaultsOptions) { if (!_.isPlainObject(props)) { $errUtils.throwErrByPath('element_selector.defaults_invalid_arg', { From 00aaf48aee08e9a7cb503449669c8945c62952d6 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Tue, 29 Jul 2025 13:37:10 -0400 Subject: [PATCH 3/4] Update error message + changelog for removed method --- cli/CHANGELOG.md | 2 +- packages/driver/cypress/e2e/cypress/element_selector.cy.ts | 6 +----- packages/driver/src/cypress.ts | 2 +- packages/driver/src/cypress/error_messages.ts | 6 ++++++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index b7910389689..0b109537f7c 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -12,7 +12,7 @@ _Released 07/29/2025 (PENDING)_ - `@cypress/webpack-dev-server` no longer supports `webpack-dev-server` version 4. Addresses [#31605](https://github.com/cypress-io/cypress/issues/31605). If you still need to use `webpack-dev-server` version 4, please see our [migration guide](https://docs.cypress.io/app/references/migration-guide#Migrating-to-Cypress-150). - In order to better align with best practices, `@cypress/webpack-batteries-included-preprocessor` no longer includes certain browser built-ins that were automatically provided by Webpack 4. The removed built-ins are `assert`, `constants`, `crypto`, `domain`, `events`, `http`, `https`, `punycode`, `querystring`, `string_decoder`, `sys`, `timers`, `tty`, `url`, `util`, `vm`, and `zlib`. However, we know that certain built-ins are popular, given that many users have files that are shared between their Cypress tests and node context. Because of this, `@cypress/webpack-batteries-included-preprocessor` will ship with built-in support for `buffer`, `path`, `process`, `os`, and `stream`. If there is a built-in that isn't supported by default and you need to add support, please refer to the Webpack [resolve.fallback](https://webpack.js.org/configuration/resolve/#resolvefallback) documentation and the [`@cypress/webpack-batteries-included-preprocessor` README](../npm/webpack-batteries-included-preprocessor/README.md). Addresses [#31039](https://github.com/cypress-io/cypress/issues/31039). - The application under test's `pagehide` event in Chromium browsers will no longer trigger Cypress's `window:unload` event. Addressed in [#31853](https://github.com/cypress-io/cypress/pull/31853). -- The `Cypress.SelectorPlayground` API has been renamed to `Cypress.ElementSelector`. This API was renamed to accommodate its use for defining `selectorPriority` in Cypress Studio and our future [`cy.prompt` release](https://on.cypress.io/cy-prompt-early-access?utm_source=docs&utm_medium=app-changelog&utm_content=cy-prompt-release). Addresses [#31801](https://github.com/cypress-io/cypress/issues/31801). Addressed in [#31889](https://github.com/cypress-io/cypress/pull/31889). +- The `Cypress.SelectorPlayground` API has been renamed to `Cypress.ElementSelector`. This API was renamed to accommodate its use for defining `selectorPriority` in Cypress Studio and our future [`cy.prompt` release](https://on.cypress.io/cy-prompt-early-access?utm_source=docs&utm_medium=app-changelog&utm_content=cy-prompt-release). Additionally, the `getSelector` method and the `onElement` option of `defaults` were removed from this API. Addresses [#31801](https://github.com/cypress-io/cypress/issues/31801). Addressed in [#31889](https://github.com/cypress-io/cypress/pull/31889). - **Component Testing breaking changes:** - Removed support for Angular 17. The minimum supported version is now `18.0.0`. Addresses [#31303](https://github.com/cypress-io/cypress/issues/31303). - `@cypress/angular` now requires a minimum of `zone.js` `0.14.0`. Addresses [#31582](https://github.com/cypress-io/cypress/issues/31582). diff --git a/packages/driver/cypress/e2e/cypress/element_selector.cy.ts b/packages/driver/cypress/e2e/cypress/element_selector.cy.ts index df3791b712d..d1db09639bc 100644 --- a/packages/driver/cypress/e2e/cypress/element_selector.cy.ts +++ b/packages/driver/cypress/e2e/cypress/element_selector.cy.ts @@ -144,11 +144,7 @@ describe('src/cypress/element_selector', () => { expect(fn).to.throw() .with.property('message') - .and.include('`Cypress.SelectorPlayground.getSelector()` has been renamed to `Cypress.ElementSelector.getSelector()`') - - expect(fn).to.throw() - .with.property('message') - .and.include('Please update your code to use `Cypress.ElementSelector` instead') + .and.include('`Cypress.SelectorPlayground.getSelector()` has been removed') }) }) }) diff --git a/packages/driver/src/cypress.ts b/packages/driver/src/cypress.ts index e8086ad1ffc..9d42f26bf6c 100644 --- a/packages/driver/src/cypress.ts +++ b/packages/driver/src/cypress.ts @@ -159,7 +159,7 @@ class $Cypress { }) }, getSelector ($el: any) { - $errUtils.throwErrByPath('selector_playground.renamed', { + $errUtils.throwErrByPath('selector_playground.removed', { args: { method: 'getSelector' }, }) }, diff --git a/packages/driver/src/cypress/error_messages.ts b/packages/driver/src/cypress/error_messages.ts index f8a86d3e885..b65b62eff60 100644 --- a/packages/driver/src/cypress/error_messages.ts +++ b/packages/driver/src/cypress/error_messages.ts @@ -1740,6 +1740,12 @@ export default { docsUrl: 'https://on.cypress.io/element-selector-api', } }, + removed: ({ method }: { method: string }) => { + return { + message: `\`Cypress.SelectorPlayground.${method}()\` has been removed.`, + docsUrl: 'https://on.cypress.io/element-selector-api', + } + }, }, server: { From 14553e15767c18a8c5208659c1f688783c254ff0 Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Tue, 29 Jul 2025 13:38:10 -0400 Subject: [PATCH 4/4] mention this PR in changelog --- cli/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 0b109537f7c..6dee6d593ab 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -12,7 +12,7 @@ _Released 07/29/2025 (PENDING)_ - `@cypress/webpack-dev-server` no longer supports `webpack-dev-server` version 4. Addresses [#31605](https://github.com/cypress-io/cypress/issues/31605). If you still need to use `webpack-dev-server` version 4, please see our [migration guide](https://docs.cypress.io/app/references/migration-guide#Migrating-to-Cypress-150). - In order to better align with best practices, `@cypress/webpack-batteries-included-preprocessor` no longer includes certain browser built-ins that were automatically provided by Webpack 4. The removed built-ins are `assert`, `constants`, `crypto`, `domain`, `events`, `http`, `https`, `punycode`, `querystring`, `string_decoder`, `sys`, `timers`, `tty`, `url`, `util`, `vm`, and `zlib`. However, we know that certain built-ins are popular, given that many users have files that are shared between their Cypress tests and node context. Because of this, `@cypress/webpack-batteries-included-preprocessor` will ship with built-in support for `buffer`, `path`, `process`, `os`, and `stream`. If there is a built-in that isn't supported by default and you need to add support, please refer to the Webpack [resolve.fallback](https://webpack.js.org/configuration/resolve/#resolvefallback) documentation and the [`@cypress/webpack-batteries-included-preprocessor` README](../npm/webpack-batteries-included-preprocessor/README.md). Addresses [#31039](https://github.com/cypress-io/cypress/issues/31039). - The application under test's `pagehide` event in Chromium browsers will no longer trigger Cypress's `window:unload` event. Addressed in [#31853](https://github.com/cypress-io/cypress/pull/31853). -- The `Cypress.SelectorPlayground` API has been renamed to `Cypress.ElementSelector`. This API was renamed to accommodate its use for defining `selectorPriority` in Cypress Studio and our future [`cy.prompt` release](https://on.cypress.io/cy-prompt-early-access?utm_source=docs&utm_medium=app-changelog&utm_content=cy-prompt-release). Additionally, the `getSelector` method and the `onElement` option of `defaults` were removed from this API. Addresses [#31801](https://github.com/cypress-io/cypress/issues/31801). Addressed in [#31889](https://github.com/cypress-io/cypress/pull/31889). +- The `Cypress.SelectorPlayground` API has been renamed to `Cypress.ElementSelector`. This API was renamed to accommodate its use for defining `selectorPriority` in Cypress Studio and our future [`cy.prompt` release](https://on.cypress.io/cy-prompt-early-access?utm_source=docs&utm_medium=app-changelog&utm_content=cy-prompt-release). Additionally, the `getSelector` method and the `onElement` option of `defaults` were removed from this API. Addresses [#31801](https://github.com/cypress-io/cypress/issues/31801). Addressed in [#31889](https://github.com/cypress-io/cypress/pull/31889) and [#32098](https://github.com/cypress-io/cypress/pull/32098). - **Component Testing breaking changes:** - Removed support for Angular 17. The minimum supported version is now `18.0.0`. Addresses [#31303](https://github.com/cypress-io/cypress/issues/31303). - `@cypress/angular` now requires a minimum of `zone.js` `0.14.0`. Addresses [#31582](https://github.com/cypress-io/cypress/issues/31582).