用mock React Jest测试组件



这是我的组件,它包含一个Select子组件

import { hashHistory } from 'react-router'
import { useEffect } from 'react'
import Select from 'cm/components/common/select'
import { eventTracker, events } from 'cm/common/event-tracker'
import { eventMetricsMap } from './helpers'
import { compose } from 'cm/common/utils'
const SelectLanguage = ({ handlers, languages, selectedLanguage }) => {
useEffect(() => {
hashHistory.listen(({ pathname }) => {
if (pathname.indexOf('/library')) {
handlers.onSelect(null)
}
})
}, [])
const handleSelect = ({ value }) => {
handlers.onSelect(value)
return value.toLowerCase()
}
const trackSelectLanguage = language => {
eventTracker.track(
events.switchBuildingBlickLanguage,
{
from: eventMetricsMap[ 'buildingblocks' ][ 'from' ],
language
}
)
}
return (
<Select
className="search__form--lang dropdown-selection--fixed-width"
handlers={{
onSelect: compose(
trackSelectLanguage,
handleSelect
)
}}
items={languages}
selected={selectedLanguage}
type="medium-input"
/>
)
}

我想用Jest对这个组件进行单元测试。我想涵盖的4个测试用例:

  • 在文档
  • 中呈现<
  • 呈现项目/gh>
  • 轨道选择打开点击
  • <
  • 处理行动/gh>

不幸的是最后两个案例都失败了,找不到原因。

你知道怎么解决吗?

import expect from 'expect'
import { fireEvent, render } from '@testing-library/react'
import SelectLanguage from './select-language'
const dummyEvents = {
switchBuildingBlockLanguage: 'switch building blocks language'
}
jest.mock(
'cm/common/event-tracker',
() => ({
eventTracker: {
track: () => {}
},
events: {
dummyEvents
}
})
)
const languages = [
{
name: 'English',
value: 'EN',
},
{
name: 'Nederlands',
value: 'NL'
}
]
jest.mock(
'cm/components/common/select',
() => ({ items, handlers }) => {
console.log('items', items)
return (<div className="dropdown">
<div className="dropdown__menu">
{items.map(({ name }) => (
<div className="dropdown__item" onClick={handlers.onSelect}>{name}</div>
))}
</div>
</div>)
}
)
const containerPath = '.dropdown'
const itemPath = '.dropdown__item'
describe('SelectLanguage component', () => {
it('renders in the document', () => {
const { container } = render(
<SelectLanguage languages={languages}/>
)
const $container = container.querySelector(containerPath)
expect($container).toBeTruthy()
})
it('renders items', () => {
const { container } = render(
<SelectLanguage languages={languages}/>
)
const $dropdownItems = container.querySelectorAll(itemPath)
expect([ ...$dropdownItems ].length).toBe(2)
})
it('track select open click', () => {
const spyFn = jest.fn()
const { container } = render(
<SelectLanguage
selectedLanguage={{
value: 'EN'
}}
languages={languages}
handlers={{
onSelect: spyFn
}}
/>
)
const $dropdownItem = container.querySelector(itemPath)
fireEvent.click($dropdownItem)
expect(spyFn).toHaveBeenCalledWith(
dummyEvents.switchBuildingBlockLanguage,
{
from: 'building blocks',
language: 'en'
}
)
})
it('handles action', () => {
const spyFn = jest.fn()
const { container } = render(
<SelectLanguage
selectedLanguage={{
value: 'EN'
}}
languages={languages}
handlers={{
onSelect: spyFn
}}
/>
)
const $dropdownItem = container.querySelector(itemPath)
fireEvent.click($dropdownItem)
expect(spyFn).toHaveBeenCalledWith('EN')
})
})

使用事件时,需要等待事件完成后再运行断言。

test -library/react有waitFor函数:

import { fireEvent, render, waitFor } from '@testing-library/react'
// ...

it('handles action', async () => {
// ...
fireEvent.click($dropdownItem)
await waitFor(() => {
expect(spyFn).toHaveBeenCalledWith(
dummyEvents.switchBuildingBlockLanguage,
{
from: 'building blocks',
language: 'en'
}
)
});
// ...