diff --git a/docs/app/component-testing/angular/api.mdx b/docs/app/component-testing/angular/api.mdx index b7bed7f604..6197fede27 100644 --- a/docs/app/component-testing/angular/api.mdx +++ b/docs/app/component-testing/angular/api.mdx @@ -13,6 +13,11 @@ sidebar_label: API ### mount +```js +// for Angular 20 and 21 using zoneless configuration +import { mount } from 'cypress/angular-zoneless' +``` + ```js import { mount } from 'cypress/angular' ``` @@ -142,18 +147,22 @@ providers, declarations, imports and even component @Inputs() Description - autoSpyOutputs + autoSpyOutputs (deprecated) boolean (optional) flag to automatically create a cy.spy() for every component @Output() - property + property. This is deprecated and not supported in + `cypress/angular-zoneless` and will be removed in a future version - autoDetectChanges + autoDetectChanges (deprecated) boolean (optional) - flag defaulted to true to automatically detect changes in your components + flag defaulted to true to automatically detect changes in your components. + This is deprecated and not supported in `cypress/angular-zoneless` and + will be removed in a future version as it is not needed with zoneless + configuration diff --git a/docs/app/component-testing/angular/examples.mdx b/docs/app/component-testing/angular/examples.mdx index 75eab39e05..1699246f35 100644 --- a/docs/app/component-testing/angular/examples.mdx +++ b/docs/app/component-testing/angular/examples.mdx @@ -46,7 +46,6 @@ in the options: cy.mount(StepperComponent, { componentProperties: { count: 100, - change: new EventEmitter(), }, }) ``` @@ -157,6 +156,26 @@ it('clicking + fires a change event with the incremented value', () => { }) ``` +### Working with Legacy @Input() Decorators + +With the release of Angular 18, [signals](https://angular.dev/guide/signals) became the preferred way to handle data binding. +However, legacy components that use `@Input()` and `@Output()` decorators are still supported. + +Interacting with legacy `@Input()` decorators is a bit different than working with signals. +In order to update the `@Input()` value, you need to use the `componentRef.setInput` method so Angular change detection runs properly. +Otherwise, you may see errors. + +```ts +cy.mount(StepperComponent, { componentProperties: { count: 100 } }) + .then(({ fixture }) => { + return cy.contains('span', '100').wrap(fixture) + }) + .then((fixture) => { + fixture.componentRef.setInput('count', 110) + return cy.contains('span', '110') + }) +``` + ### Using createOutputSpy() To make spying on event emitters easier, there is a utility function called @@ -179,7 +198,13 @@ it('clicking + fires a change event with the incremented value', () => { }) ``` -### Using autoSpyOutputs +### Using autoSpyOutputs (deprecated) + +:::caution + +The `autoSpyOutputs` flag is deprecated and not supported in `cypress/angular-zoneless` and will be removed in a future version. + +::: You might find yourself repeatedly creating a `cy.spy()` for each of your component outputs. Because of this, we created an easy mechanism to handle this @@ -208,17 +233,8 @@ function. It currently does not work with the template syntax. ::: -:::caution - -`autoSpyOutput` is an **experimental feature** and could be removed or changed -in the future - -::: - ### Signals -With the releases of Angular versions [17.1](https://github.com/angular/angular/blob/main/CHANGELOG.md#1710-2024-01-17) and [17.2](https://github.com/angular/angular/blob/main/CHANGELOG.md#1720-2024-02-14), [input](https://github.com/angular/angular/pull/53521) and [model](https://github.com/angular/angular/pull/54252) signals were introduced into the `@angular/core` API. Though basic signals were introduced in Angular `16`, using all signals requires Angular `17.2` and above. - :::info With Cypress 14, signal support is directly included in the `cypress/angular` testing harness. @@ -434,7 +450,13 @@ This custom mount command will allow you to skip manually passing in the `ButtonComponent` and `CardComponent` as declarations into each `cy.mount()` call. -### autoSpyOutputs +### autoSpyOutputs (deprecated) + +:::caution + +The `autoSpyOutputs` flag is deprecated and not supported in `cypress/angular-zoneless` and will be removed in a future version. + +::: Here is an example of defaulting `autoSpyOutputs` for every mounted component: diff --git a/docs/app/component-testing/angular/overview.mdx b/docs/app/component-testing/angular/overview.mdx index 235d813e2c..2850ba9e0e 100644 --- a/docs/app/component-testing/angular/overview.mdx +++ b/docs/app/component-testing/angular/overview.mdx @@ -20,11 +20,12 @@ sidebar_label: Overview ## Framework Support -Cypress Component Testing supports Angular `^18.0.0`, `^19.0.0`, and `^20.0.0`. +Cypress Component Testing supports Angular `^18.0.0`, `^19.0.0`, `^20.0.0`, and `^21.0.0`. :::info Our testing harness, `cypress/angular`, still requires `zone.js` and `@angular-devkit/build-angular` to be installed in your project, even if your project is zoneless or is built with `@angular/build`. +If you wish to use the zoneless configuration, which is the default in Angular 21, you can use `cypress/angular-zoneless` testing harness instead as of Cypress `15.8.0`. ::: ## Tutorial @@ -129,5 +130,5 @@ export default { #### Sample Angular Apps -- [Angular 18](https://github.com/cypress-io/cypress-component-testing-apps/tree/main/angular) - [Angular 20 Standalone](https://github.com/cypress-io/cypress-component-testing-apps/tree/main/angular-standalone) +- [Angular 21 Zoneless](https://github.com/cypress-io/cypress-component-testing-apps/tree/main/angular-zoneless) diff --git a/docs/app/component-testing/get-started.mdx b/docs/app/component-testing/get-started.mdx index cbf9b3f79b..8e417a8ae0 100644 --- a/docs/app/component-testing/get-started.mdx +++ b/docs/app/component-testing/get-started.mdx @@ -47,7 +47,7 @@ following development servers and frameworks: | [Next.js 14-16](/app/component-testing/react/overview#Nextjs) | React 18-19 | Webpack 5 | | [Vue with Vite](/app/component-testing/vue/overview#Vue-with-Vite) | Vue 3 | Vite 5-7 | | [Vue with Webpack](/app/component-testing/vue/overview#Vue-with-Webpack) | Vue 3 | Webpack 5 | -| [Angular](/app/component-testing/angular/overview#Framework-Configuration) | Angular 18-20 | Webpack 5 | +| [Angular](/app/component-testing/angular/overview#Framework-Configuration) | Angular 18-21 | Webpack 5 | | [Svelte with Vite](/app/component-testing/svelte/overview#Svelte-with-Vite) Alpha | Svelte 5 | Vite 5-7 | | [Svelte with Webpack](/app/component-testing/svelte/overview#Svelte-with-Webpack) Alpha | Svelte 5 | Webpack 5 | diff --git a/docs/app/core-concepts/interacting-with-elements.mdx b/docs/app/core-concepts/interacting-with-elements.mdx index c098f088ee..4f2d2dd3f8 100644 --- a/docs/app/core-concepts/interacting-with-elements.mdx +++ b/docs/app/core-concepts/interacting-with-elements.mdx @@ -26,6 +26,119 @@ inform your testing strategy, and ship high-quality code with confidence. ::: +## Visibility + +### Default Behavior + +Cypress checks a lot of things to determine an element's visibility. The +following calculations factor in CSS translations and transforms. + +#### An element is considered hidden if: + +- Its `width` or `height` is `0`. +- Its CSS property (or ancestors) is `visibility: hidden`. +- Its CSS property (or ancestors) is `display: none`. +- Its CSS property is `position: fixed` and it's offscreen or covered up. +- Any of its ancestors **hides overflow**\* + - AND that ancestor has a `width` or `height` of `0` + - AND an element between that ancestor and the element is `position: absolute` +- Any of its ancestors **hides overflow**\* + - AND that ancestor or an ancestor between it and that ancestor is its offset + parent + - AND it is positioned outside that ancestor's bounds +- Any of its ancestors **hides overflow**\* + - AND the element is `position: relative` + - AND it is positioned outside that ancestor's bounds + +\***hides overflow** means it has `overflow: hidden`, `overflow-x: hidden`, +`overflow-y: hidden`, `overflow: scroll`, or `overflow: auto` + +:::info + +Opacity + +Elements where the CSS property (or ancestors) is `opacity: 0` are considered +hidden when +[asserting on the element's visibility directly](/app/references/assertions#Visibility). + +However elements where the CSS property (or ancestors) is `opacity: 0` are +considered actionable and any commands used to interact with the hidden element +will perform the action. + +::: + +### Experimental Fast Visibility + +You can enable a faster visibility detection algorithm using [`experimentalFastVisibility`](/app/references/experiments#Experimental-Fast-Visibility). + +This algorithm is more accurate and less resource-intensive than the default behavior, but it has slightly different semantics. + +When `experimentalFastVisibility` is enabled, an element is considered hidden if: + +- Its `width` or `height` is `0` +- Its computed CSS properties prevent it from being clicked on or visible: + - `visibility: hidden` + - `opacity: 0` + - `display: none` + - `pointer-events: none` +- It is positioned fully outside of the browser viewport + - _this is a known compatibility issue with the legacy visibility algorithm_ when it comes to asserting visibility. It will be addressed during the course of this experiment. +- It is fully covered or clipped by another element + +Keep up-to-date with the the progress of this experiment in the [Cypress repository](https://github.com/cypress-io/cypress/issues/33043). + +#### Limitations + +Experimental fast visibility is an experimental feature that is still under development. It uses different semantics from the legacy visibility algorithm, and does not yet fully support all testing scenarios. + +- Shadow DOM is not yet supported. Tests that interact with Shadow DOM elements may fail or behave incorrectly. +- Elements outside of the browser's viewport are not yet correctly identified as visible. Scroll elements into view before testing. + +#### Common Compatibility Issues + +When enabling fast visibility, you may encounter differences in how elements are detected. The fast algorithm provides more geometrically accurate visibility detection, which may reveal that elements previously considered visible are actually hidden. + +**Elements Outside Viewport** + +Elements positioned outside the viewport are now correctly identified as hidden. Scroll elements into view before testing: + +```javascript +// Before +cy.get('.off-screen-element').should('be.visible') + +// After +cy.get('.off-screen-element').scrollIntoView().should('be.visible') +``` + +**Covered Elements** + +Elements covered by other elements are now correctly identified as hidden. Test the covering element or the user interaction that reveals the covered element: + +```javascript +// Test the user action that reveals the element +cy.get('.toggle-button').click() +cy.get('.covered-element').should('be.visible') +``` + +**Zero-Dimension Containers** + +Containers with zero dimensions are now correctly identified as hidden. Test the child element instead of the container: + +```javascript +// Test the child element that should be visible +cy.get('.zero-dimension-container .child-element').should('be.visible') +``` + +**Elements with `pointer-events: none`** + +Elements with `pointer-events: none` may be detected as hidden when they are visible. Do not assert visibility on elements with `pointer-events: none`, as they cannot be interacted with. + +:::caution + +**Important:** If tests fail after enabling fast visibility, the fast algorithm is likely correct and tests should be updated to match the actual behavior. + +::: + ## Actionability Some commands in Cypress are for interacting with the DOM such as: @@ -71,45 +184,6 @@ Whenever Cypress cannot interact with an element, it could fail at any of the above steps. You will usually get an error explaining why the element was not found to be actionable. -### Visibility - -Cypress checks a lot of things to determine an element's visibility. The -following calculations factor in CSS translations and transforms. - -#### An element is considered hidden if: - -- Its `width` or `height` is `0`. -- Its CSS property (or ancestors) is `visibility: hidden`. -- Its CSS property (or ancestors) is `display: none`. -- Its CSS property is `position: fixed` and it's offscreen or covered up. -- Any of its ancestors **hides overflow**\* - - AND that ancestor has a `width` or `height` of `0` - - AND an element between that ancestor and the element is `position: absolute` -- Any of its ancestors **hides overflow**\* - - AND that ancestor or an ancestor between it and that ancestor is its offset - parent - - AND it is positioned outside that ancestor's bounds -- Any of its ancestors **hides overflow**\* - - AND the element is `position: relative` - - AND it is positioned outside that ancestor's bounds - -\***hides overflow** means it has `overflow: hidden`, `overflow-x: hidden`, -`overflow-y: hidden`, `overflow: scroll`, or `overflow: auto` - -:::info - -Opacity - -Elements where the CSS property (or ancestors) is `opacity: 0` are considered -hidden when -[asserting on the element's visibility directly](/app/references/assertions#Visibility). - -However elements where the CSS property (or ancestors) is `opacity: 0` are -considered actionable and any commands used to interact with the hidden element -will perform the action. - -::: - ### Disability Cypress checks whether the `disabled` property is `true` on a diff --git a/docs/app/references/assertions.mdx b/docs/app/references/assertions.mdx index 1d9e463eea..13db1808b4 100644 --- a/docs/app/references/assertions.mdx +++ b/docs/app/references/assertions.mdx @@ -258,6 +258,14 @@ Watch the short video ["Multiple elements and should('be.visible') assertion"](https://www.youtube.com/watch?v=LxkrhUEE2Qk) that shows how to correctly check the visibility of elements. +:::info + +**Visibility Semantics** + +For detailed information about how Cypress determines element visibility, including the default behavior and the experimental fast visibility algorithm, see [Visibility](/app/core-concepts/interacting-with-elements#Visibility). + +::: + ### Existence ```javascript diff --git a/docs/app/references/changelog.mdx b/docs/app/references/changelog.mdx index 8a74150597..10cb02f9ab 100644 --- a/docs/app/references/changelog.mdx +++ b/docs/app/references/changelog.mdx @@ -8,6 +8,34 @@ sidebar_label: Changelog # Changelog +## 15.8.0 + +_Released 12/16/2025_ + +**Performance:** + +- Introduced a new `experimentalFastVisibility` experiment. Enabling this experiment changes how Cypress performs visibility checks and assertions. Read more about [experimental fast visibility](/app/references/experiments#Experimental-Fast-Visibility). Addresses [#33044](https://github.com/cypress-io/cypress/issues/33044). Addressed in [#32801](https://github.com/cypress-io/cypress/pull/32801). + +**Features:** + +- `Angular` version 21 is now supported within component testing. Addressed in [#33004](https://github.com/cypress-io/cypress/pull/33004). +- Adds zoneless support for `Angular` Component Testing through the `angular-zoneless` mount function. Addresses [#31504](https://github.com/cypress-io/cypress/issues/31504) and [#30070](https://github.com/cypress-io/cypress/issues/30070). +- After receiving feedback on its usefulness outside of Studio, the Selector Playground is now available for all users in open mode. When opened, the playground automatically enables interactive mode to help you build and test selectors directly in your application. Addresses [#32672](https://github.com/cypress-io/cypress/issues/32672). Addressed in [#33073](https://github.com/cypress-io/cypress/pull/33073). + +**Bugfixes:** + +- Fixed an issue where a EPIPE error shows up after CTRL+C is done in terminal. Fixes [#30659](https://github.com/cypress-io/cypress/issues/30659). Addressed in [#32873](https://github.com/cypress-io/cypress/pull/32873). +- Fixed an issue where the browser would freeze when Cypress intercepts a synchronous XHR request and a `routeHandler` is used. Fixes [#32874](https://github.com/cypress-io/cypress/issues/32874). Addressed in [#32925](https://github.com/cypress-io/cypress/pull/32925). +- Fixed an issue where `Next.js` Component Testing would not load correctly without a TypeScript-based Next config in versions 16.0.3 and up. Fixes [#32968](https://github.com/cypress-io/cypress/issues/32968). +- Fixed an issue where the error message for `not.have.length` was not correctly displaying the expected length in the Command Log. Addressed in [#18927](https://github.com/cypress-io/cypress/issues/18927). +- Fixed an issue where `removeAttribute()` would not work for attributes other than `target` on anchor or form elements after clicking links with `target="_top"` or `target="_parent"`. Fixes [#26206](https://github.com/cypress-io/cypress/issues/26206). Addressed in [#33051](https://github.com/cypress-io/cypress/pull/33051). + +**Dependency Updates:** + +- Removed extraneous dependencies that are no longer used. Addressed in [#33098](https://github.com/cypress-io/cypress/pull/33098). +- Upgraded `brace-expansion`. This removes the [CVE-2025-5889](https://security.snyk.io/vuln/SNYK-JS-BRACEEXPANSION-9789073) vulnerability being reported in security scans. Addressed in [#33112](https://github.com/cypress-io/cypress/pull/33112). +- Upgraded `form-data`. This removes the [CVE-2025-7783](https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150) vulnerability being reported in security scans. Addressed in [#33113](https://github.com/cypress-io/cypress/pull/33113). + ## 15.7.1 _Released 12/02/2025_ diff --git a/docs/app/references/error-messages.mdx b/docs/app/references/error-messages.mdx index e92d3b5380..b473987af4 100644 --- a/docs/app/references/error-messages.mdx +++ b/docs/app/references/error-messages.mdx @@ -238,7 +238,7 @@ are not. You may see a variation of this message for 4 different reasons: -1. The element is not visible +1. The element is not [visible](/app/core-concepts/interacting-with-elements#Visibility) 2. The element is being covered by another element 3. The element's center is hidden from view 4. The element is disabled @@ -801,10 +801,10 @@ read a unique identifier from your CI provider as described in our You may encounter this error if Cypress is detecting the exact same CI Build ID matching a previous CI Build ID in a run that was completed over 24 hours ago. -You cannot run tests on a run that has been complete for that long. ​ ​You can +You cannot run tests on a run that has been complete for that long. You can see the CI Build ID that is detected for each completed run by looking at the details section at the top of your run in -[Cypress Cloud](https://on.cypress.io/cloud). ​ ​You can generate and pass in +[Cypress Cloud](https://on.cypress.io/cloud). You can generate and pass in your own unique CI Build ID per run as described [here](/app/references/command-line#cypress-run-ci-build-id-lt-id-gt). @@ -946,6 +946,32 @@ there. It's possible to enable debugging these scripts by adding the `crossorigin` attribute and setting a `CORS` header. +### Synchronous XHR requests + +:::caution + +Note + +Synchronous XHR requests often cause hangs on the web, especially with poor network conditions or when the remote server is slow to respond. Synchronous XHR is now deprecated and should be avoided in favor of asynchronous requests. + +::: + +When using synchronous XHR requests, you may see the following warnings: + +> **Warning: Synchronous XHR request was not intercepted: http://example.com.** + +Cypress is unable to intercept a synchronous XHR request if the [`cy.intercept()`](/api/commands/intercept) is using a [`routeHandler`](/api/commands/intercept#routeHandler-Function). +Thus, the [`routeHandler`](/api/commands/intercept#routeHandler-Function) won't be executed and the request will be sent to the origin server without any modifications. +An intercept with a [`StaticResponse`](/api/commands/intercept#staticResponse-StaticResponse) does not have this limitation and will still be executed. + +> **Warning: Cookies may not have been applied to synchronous XHR request: http://example.com.** + +Cypress is unable to apply cookies to a synchronous XHR request if the request is cross-origin to the `top` origin. + +> **Warning: Cookies may not have been set for synchronous XHR response: http://example.com.** + +Cypress is unable to set cookies for a synchronous XHR response if the request is cross-origin to the `top` origin. + ## Browser Errors {/* keep old hash */} diff --git a/docs/app/references/experiments.mdx b/docs/app/references/experiments.mdx index 1116d7ed14..b270bc2545 100644 --- a/docs/app/references/experiments.mdx +++ b/docs/app/references/experiments.mdx @@ -38,6 +38,7 @@ configuration to Cypress. | `experimentalModifyObstructiveThirdPartyCode` | `false` | Whether Cypress will search for and replace obstructive code in third party `.js` or `.html` files. NOTE: Setting this flag removes [Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). | | `experimentalSourceRewriting` | `false` | Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm. See [#5273](https://github.com/cypress-io/cypress/issues/5273) for details. | | `experimentalWebKitSupport` | `false` | Enable experimental support for running tests in WebKit. When set, installs of `playwright-webkit` will be detected and available in Cypress. See [Launching Browsers](/app/references/launching-browsers#WebKit-Experimental) for more information. | +| `experimentalFastVisibility` | `false` | Enables a faster visibility detection algorithm using point sampling. This can significantly improve performance when interacting with complex DOM structures. See [Experimental Fast Visibility](/app/references/experiments#Experimental-Fast-Visibility) for more details. | | `retries.experimentalStrategy` | N/A | Applies a strategy for test retries according to your "flake tolerance"; options are detect-flake-but-always-fail or detect-flake-and-pass-on-threshold. See [Experimental Retries](/app/references/experiments#Experimental-Flake-Detection-Features) for more details. | | `retries.experimentalOptions` | N/A | Sets retries strategy-specific options like maxRetries, passesRequired, and stopIfAnyPassed. See [Experimental Retries](/app/references/experiments#Experimental-Flake-Detection-Features) for more details. | @@ -124,6 +125,90 @@ modified HTML or JS value. ::: +## Experimental Fast Visibility + +The `experimentalFastVisibility` option enables a faster visibility detection algorithm that uses point sampling instead of the legacy algorithm. This can significantly improve performance when interacting with complex DOM structures. + +### Benefits + +The fast visibility algorithm provides several advantages over the legacy algorithm: + +- **Better performance**: Constant-time in the best case, and bounded exponential in the worst case (when point sampling on a fully hidden element) +- **Memory efficiency**: Reduces memory usage and prevents browser crashes during visibility checks +- **Reduced layout thrashing**: Avoids repeated access of CSS properties that require layout recalculation +- **Better coverage detection**: Can detect when an element is fully covered by positioned elements outside its ancestor tree + +### How It Works + +The fast visibility algorithm: + +1. Assumes `body` and `html` are always visible (consistent with current visibility behavior) +2. Uses the built-in `checkVisibility` method as a first pass, with all options enabled +3. For `` elements, defers to the visibility of the parent `