Skip to content

Document CT changes for v11 #4828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 7, 2022
Merged
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
263 changes: 262 additions & 1 deletion content/guides/references/migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,275 @@
title: Migration Guide
---

<DocsVideo src="https://youtube.com/embed/mIqKNhLlPcU"></DocsVideo>
## Migrating to Cypress version 11.0

This guide details the changes and how to change your code to migrate to Cypress
version 11.0.
[See the full changelog for version 11.0](/guides/references/changelog#11-0-0).

### Component Testing Updates

As of Cypress 11, Component Testing is now generally available. There are some
minor breaking changes. Most projects should be able to migrate without any code
modifications.

#### Changes to Mounting Options

Each major libary we support has a `mount` function with two arguments:

1. The component
2. Mounting Options

Mounting options previously had several properties that are now removed:

- cssFile, cssFiles
- style, styles
- stylesheet, stylesheets

Read more about the rationale
[here](https://www.cypress.io/blog/2022/11/04/upcoming-changes-to-component-testing/).
We recommend writing test-specific styles in a separate `css` file you import in
your test, or in your `supportFile`.

#### Before (Cypress 10)

```jsx
import { mount } from ‘cypress/react’
import { Card } from ‘./Card’

it(‘renders some content’, () => {
cy.mount(<Card title=”title” />, {
styles: `
.card { width: 100px; }
`,
stylesheets: ['https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css']
})
})
```

#### After (Cypress 11)

```js
/** style.css */
@import "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css";
.card { width: 100px }

/** Card.cy.jsx */
import { mount } from ‘cypress/react’
import { Card } from ‘./Card’
import ‘./styles.css’ // contains CDN link and custom styling.

it('renders some content', () => {
cy.mount(<Card title=”title” />)
})
```

### React - `mountHook` Removed

`mountHook` from `cypress/react` has been removed. Read more about the rationale
[here](https://www.cypress.io/blog/2022/11/04/upcoming-changes-to-component-testing/).

We recommend simply replacing it with `mount` and a component.

Consider the following `useCounter` hook:

```js
import { useState, useCallback } from 'react'

function useCounter() {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount((x) => x + 1), [])

return { count, increment }
}
```

#### Before - Cypress 10 and `mountHook`

```js
import { mountHook } from 'cypress/react'
import { useCounter } from ‘./useCounter’

it('increments the count', () => {
mountHook(() => useCounter()).then((result) => {
expect(result.current.count).to.equal(0)
result.current.increment()
expect(result.current.count).to.equal(1)
result.current.increment()
expect(result.current.count).to.equal(2)
})
})
```

#### After - Cypress 11 and `mount`

```js
import { useCounter } from ‘./useCounter’

it('increments the count', () => {
function Counter () {
const { count, increment } = useCounter()
return (
<>
<h1 name="count">Count is {{ count }}</h1>
<button onClick={increment}>Increment</button>
</>
)
}

cy.mount(<Counter />).then(() => {
cy.get('[name="count"]').should('contain', 0)
.get('button').click()
.get('[name="count"]').should('contain', 1)
})
})
```

### React - `unmount` Removed

`unmount` from `cypress/react` has been removed. Read more about the rationale
[here](https://www.cypress.io/blog/2022/11/04/upcoming-changes-to-component-testing/).
We recommend using the API React provides for unmounting components,
[unmountComponentAtNode](https://reactjs.org/docs/react-dom.html#unmountcomponentatnode).

#### Before - Cypress 10 and `unmount`

```js
import { unmount } from ‘cypress/react’

it('calls the prop', () => {
cy.mount(<Comp onUnmount={cy.stub().as('onUnmount')} />)
cy.contains('My component')

unmount()

// the component is gone from the DOM
cy.contains('My component').should('not.exist')
cy.get('@onUnmount').should('have.been.calledOnce')
})
```

#### After - Cypress 11 and `unmountComponentAtNode`

```js
import { getContainerEl } from 'cypress/react'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is getContainerEl new? It doesn't appear to be in v10. Why wouldn't they just use the component that the mount returns?

Copy link
Contributor Author

@lmiller1990 lmiller1990 Nov 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It actually is in v10, it's from cypress/mount-utils. https://github.com/cypress-io/cypress/blob/develop/npm/mount-utils/src/index.ts#L42. It isn't documented but it how we write and ensure all our mount adapters target the same element.

You can't unmount a component, you need to pass the exact same HTML element you mounted on (this is how React works). It's the argument called container here: https://reactjs.org/docs/react-dom.html#unmountcomponentatnode.

I personally think just keeping umount would have been far more ergonomic, but this shouldn't be too disruptive - unmount isn't that commonly used, from what I can see.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should add some tsdocs around getContainerEl since its a part of our api now

import ReactDom from 'react-dom'

it('calls the prop', () => {
cy.mount(<Comp onUnmount={cy.stub().as('onUnmount')} />)
cy.contains('My component')

cy.then(() => ReactDom.unmountComponentAtNode(getContainerEl()))

// the component is gone from the DOM
cy.contains('My component').should('not.exist')
cy.get('@onUnmount').should('have.been.calledOnce')
})
```

### Vue - `mountCallback` Removed

`mountCallback` from `cypress/vue` has been removed. Read more about the
rationale
[here](https://www.cypress.io/blog/2022/11/04/upcoming-changes-to-component-testing/).
We recommend using `mount`.

#### Before - Cypress 10 and `mountCallback`

```js
import { mountCallback } from ‘cypress/vue’

beforeEach(mountCallback(MessageList))

it('shows no messages', () => {
getItems().should('not.exist')
})
```

#### After - Cypress 11 and `mount`

```js
beforeEach(() => cy.mount(MessageList))

it('shows no messages', () => {
getItems().should('not.exist')
})
```

### Angular - Providers Mounting Options Change

There is one breaking change for Angular users in regards to providers. In
Cypress 10, we took any providers passed as part of the Mounting Options and
overrode the component providers via the `TestBed.overrideComponent` API.

In Cypress 11, providers passed as part of the Mounting Options will be assigned
at the module level using the `TestBed.configureTestingModule` API.

This means that module-level providers (resolved from imports or
`@Injectable({ providedIn: 'root' })` can be overridden, but providers specified
in `@Component({ providers: [...] })` will not be overridden when using
`cy.mount(MyComponent, { providers: [...] })`.

To override component-level providers, use the `TestBed.overrideComponent` API.

See a concrete example
[here](https://www.cypress.io/blog/2022/11/04/upcoming-changes-to-component-testing/#angularproviders-priority).

### Vite Dev Server (`cypress/vite-dev-server`)

When providing an inline `viteConfig` inside of `cypress.config`, any
`vite.config.js` file is not automatically merged.

#### Before - Cypress 10 and `viteConfig`

```js
import { defineConfig } from 'cypress'

export default defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'vite',
viteConfig: {
// ... custom vite config ...
// result merged with `vite.config` file if present
},
},
},
})
```

#### After - Cypress 11 and `viteConfig`

```js
import { defineConfig } from 'cypress'
import viteConfig from './vite.config'

export default defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'vite',
viteConfig: {
...viteConfig,
// ... other overrides ...
},
},
},
})
```

Vite 3+ users could make use of the
[`mergeConfig`](https://vitejs.dev/guide/api-javascript.html#mergeconfig) API.

## Migrating to Cypress version 10.0

This guide details the changes and how to change your code to migrate to Cypress
version 10.0.
[See the full changelog for version 10.0](/guides/references/changelog#10-0-0).

<DocsVideo src="https://youtube.com/embed/mIqKNhLlPcU"></DocsVideo>

### Cypress Changes

- The “Run all specs” and “Run filtered specs” functionality have been removed.
Expand Down