我有一个Switch
组件,该组件基于一个以Routes
作为参数并返回字符串的switch语句来呈现useRouteMatch().path
。
在单元测试中,我想动态模拟这一点,但是似乎每个文件只能设置一个jest.mock
。
SectionComponent.tsx:
import React from 'react'
import { useRouteMatch } from 'react-router-dom'
import * as strings from '../../../strings'
import Header from '../../shared/header/Header'
const SectionComponent: React.FC = ({ children }) => {
const { path } = useRouteMatch()
const sectionTitle = () => {
switch (path) {
case '/header':
return strings.demo.header.title
case '/navbars':
return strings.demo.navbar.title
case '/button':
// ...etc
default:
return ''
}
}
return (
<div>
<Header
title={sectionTitle()}
titleColor={strings.theme.orange}
titleSize="S"
bgColor={strings.theme.white}
size="S"
/>
{children}
</div>
)
}
export default SectionComponent
SectionComponent.spec.tsx:
import React from 'react'
import { render } from '@testing-library/react'
import SectionComponent from './SectionComponent'
import * as strings from '../../../strings'
// list I want to dynamically generate useRouteMatch().path and expected result from
const options = [
{ name: 'header', to: '/header' },
{ name: 'navbars', to: '/navbars' },
{ name: 'button', to: '/button' },
{ name: 'typography', to: '/typography' },
{ name: 'form', to: '/form' },
{ name: 'navs', to: '/navs' },
{ name: 'indicators', to: '/indicators' },
{ name: 'list-group', to: '/list-group' },
{ name: 'cards', to: '/cards' },
]
// Can only do this once per file
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
useRouteMatch: () => ({ path: '/header' }), // return value can't access outside variables eg option.to ('/header')
}))
describe('SectionComponent', () => {
// ideally want to map thorugh options and test here:
it('should render with each Title', () => {
const { getByText } = render(<SectionComponent />)
expect(getByText(strings.demo.header.title)).toBeInTheDocument()
})
})
有人有什么建议吗?如有必要,我很乐意提供更多信息
答案 0 :(得分:0)
使用jest.fn().mockReturnValueOnce()
多次找出解决方法
import React from 'react'
import { render } from '@testing-library/react'
import SectionComponent from './SectionComponent'
const options = [
{ name: 'Headers' },
{ name: 'Navbars' },
{ name: 'Button' },
{ name: 'Typography' },
{ name: 'Forms' },
{ name: 'Navs' },
{ name: 'Indicators' },
{ name: 'List Group' },
{ name: 'Cards' },
]
jest.mock('react-router', () => ({
useRouteMatch: jest
.fn()
.mockReturnValueOnce({ path: '/header' })
.mockReturnValueOnce({ path: '/navbars' })
.mockReturnValueOnce({ path: '/button' })
.mockReturnValueOnce({ path: '/typography' })
.mockReturnValueOnce({ path: '/form' })
.mockReturnValueOnce({ path: '/navs' })
.mockReturnValueOnce({ path: '/indicators' })
.mockReturnValueOnce({ path: '/list-group' })
.mockReturnValueOnce({ path: '/cards' }),
}))
options.forEach(option => {
describe('SectionComponent', () => {
it('should render with each Title', () => {
const { getByText } = render(<SectionComponent />)
expect(getByText(option.name)).toBeInTheDocument()
})
})
})
Maybe not the most efficient but it works