Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions docs/app/component-testing/angular/api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
```
Expand Down Expand Up @@ -142,18 +147,22 @@ providers, declarations, imports and even component @Inputs()
<td>Description</td>
</thead>
<tr>
<td>autoSpyOutputs</td>
<td>autoSpyOutputs (deprecated)</td>
<td>boolean (optional)</td>
<td>
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
</td>
</tr>
<tr>
<td>autoDetectChanges</td>
<td>autoDetectChanges (deprecated)</td>
<td>boolean (optional)</td>
<td>
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
</td>
</tr>
<tr>
Expand Down
46 changes: 34 additions & 12 deletions docs/app/component-testing/angular/examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ in the options:
cy.mount(StepperComponent, {
componentProperties: {
count: 100,
change: new EventEmitter(),
},
})
```
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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:

Expand Down
5 changes: 3 additions & 2 deletions docs/app/component-testing/angular/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
2 changes: 1 addition & 1 deletion docs/app/component-testing/get-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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) <Badge type="info">Alpha</Badge> | Svelte 5 | Vite 5-7 |
| [Svelte with Webpack](/app/component-testing/svelte/overview#Svelte-with-Webpack) <Badge type="info">Alpha</Badge> | Svelte 5 | Webpack 5 |

Expand Down
152 changes: 113 additions & 39 deletions docs/app/core-concepts/interacting-with-elements.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<strong>Opacity</strong>

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:
Expand Down Expand Up @@ -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

<strong>Opacity</strong>

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
Expand Down
8 changes: 8 additions & 0 deletions docs/app/references/assertions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions docs/app/references/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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_
Expand Down
Loading