Skip to main content
Cypress应用

React 示例

info
你将学到
  • 如何挂载React组件
  • 如何向React组件传递数据
  • 如何测试事件处理器
  • 如何为React Router和Redux定制cy.mount()

挂载组件

挂载组件

测试组件的第一步是挂载它。这会将组件渲染到测试环境中,并允许使用Cypress API来选择元素、与之交互以及运行断言。

要挂载React组件,请将组件导入到你的测试文件中,并将组件传递给cy.mount命令:

import { Stepper } from './stepper'

it('mounts', () => {
cy.mount(<Stepper />)
//Stepper的初始计数应为0(默认值)
cy.get('[data-cy=counter]').should('have.text', '0')
})

向组件传递数据

你可以通过在传递给cy.mount()的JSX上设置props来向组件传递数据:

it('mounts', () => {
cy.mount(<Stepper initial={100} />)
//Stepper的初始计数应为100
cy.get('[data-cy=counter]').should('have.text', '100')
})

测试事件处理器

将Cypress的spy传递给事件prop,并验证它是否被调用:

it('clicking + fires a change event with the incremented value', () => {
const onChangeSpy = cy.spy().as('onChangeSpy')
cy.mount(<Stepper onChange={onChangeSpy} />)
cy.get('[data-cy=increment]').click()
cy.get('@onChangeSpy').should('have.been.calledWith', 1)
})

自定义挂载命令

定制cy.mount()

默认情况下,cy.mount()mount()的简单传递,但你可以根据需要定制cy.mount()。例如,如果你在React应用中使用提供者或其他全局应用级设置,可以在这里配置它们。

以下是几个演示如何使用自定义挂载命令的示例。这些示例可以调整为支持大多数其他你需要的提供者。

React Router

如果你的组件使用了React Router的钩子或组件,确保组件可以访问React Router提供者。下面是一个使用MemoryRouter包装组件的挂载命令示例。

import { mount } from 'cypress/react'
import { MemoryRouter } from 'react-router-dom'

Cypress.Commands.add('mount', (component, options = {}) => {
const { routerProps = { initialEntries: ['/'] }, ...mountOptions } = options

const wrapped = <MemoryRouter {...routerProps}>{component}</MemoryRouter>

return mount(wrapped, mountOptions)
})

为了设置特定场景,可以在选项中传递将传递给MemoryRouter的props。以下是一个测试示例,确保活动链接应用了正确的类,通过将路由器初始化为指向特定路由的initialEntries

import { Navigation } from './Navigation'

it('home link should be active when url is "/"', () => {
// 无需传递自定义initialEntries,因为默认url是'/'
cy.mount(<Navigation />)

cy.get('a').contains('Home').should('have.class', 'active')
})

it('login link should be active when url is "/login"', () => {
cy.mount(<Navigation />, {
routerProps: {
initialEntries: ['/login'],
},
})

cy.get('a').contains('Login').should('have.class', 'active')
})

Redux

要使用一个消费Redux存储状态或动作的组件,创建一个将你的组件包装在Redux提供者中的mount命令:

import { mount } from 'cypress/react'
import { Provider } from 'react-redux'
import { getStore } from '../../src/store'

Cypress.Commands.add('mount', (component, options = {}) => {
// 如果没有提供store,则使用默认store
const { reduxStore = getStore(), ...mountOptions } = options

const wrapped = <Provider store={reduxStore}>{component}</Provider>

return mount(wrapped, mountOptions)
})

options参数可以包含一个已经初始化数据的store:

import { getStore } from '../redux/store'
import { setUser } from '../redux/userSlice'
import { UserProfile } from './UserProfile'

it('User profile should display user name', () => {
const user = { name: 'test person' }

// getStore是一个创建新store的工厂方法
const store = getStore()

// setUser是从user slice导出的一个动作
store.dispatch(setUser(user))

cy.mount(<UserProfile />, { reduxStore: store })

cy.get('div.name').should('have.text', user.name)
})
info

getStore方法是一个初始化新Redux存储的工厂方法。重要的是每个新测试都要初始化存储,以确保存储的更改不会影响其他测试。