React 测试库 fireEvent 未触发/找到答案

时间:2021-07-04 19:23:54

标签: reactjs typescript react-testing-library

我在使用 React 测试库及其 fireEvent 函数时遇到问题。 我想在悬停后测试我的组件及其样式。 这是我用 tsx 编写的组件:

Component

这是我的测试:

import React from 'react'
import { makeStyles } from '@material-ui/core'
import Paper, { PaperProps } from '@material-ui/core/Paper'
import Box from '@material-ui/core/Box'
import posed from 'react-pose'
import grey from '@material-ui/core/colors/grey'
import green from '@material-ui/core/colors/green'
import lightBlue from '@material-ui/core/colors/lightBlue'
import teal from '@material-ui/core/colors/teal'

function styleProducer(variant: BigTileProps['variant'] = 'default', color: BigTileProps['color'] = 'default'): Function {
    type colrMapType = {
        [k: string]: { tile: { [pr: string]: string } }
    }
    const colorMap: colrMapType = {
        default: { tile: {} },
        grey: {
            tile: { background: grey[700], color: 'white' }
        },
        green: {
            tile: { background: green[300] }
        },
        teal: {
            tile: { background: teal[400], color: 'white' }
        },
        blue: {
            tile: { background: lightBlue[200] }
        },
    }
    interface variantsKeys {
        small: (theme: any) => object
        default: (theme: any) => object
        big: (theme: any) => object
        large: (theme: any) => object
    }
    type variantsType = {
        [k in keyof variantsKeys]: variantsKeys[k]
    }
    const variants: variantsType = {
        small: (theme: any) => ({
            tile: Object.assign({
                minWidth: theme.spacing(10),
                height: theme.spacing(10),
                background: grey[500],
                position: 'relative',
                '&:hover': {
                    cursor: 'pointer'
                }
            }, colorMap[color].tile),
            content: {
                fontSize: '2rem',
                fontWeight: 'bold'
            },
            title: {
                textTransform: 'uppercase'
            },
            icon: {
                position: 'absolute',
                top: 0,
                left: 0
            }
        }),
        default: (theme: any) => ({
            tile: Object.assign({
                minWidth: theme.spacing(15),
                height: theme.spacing(15),
                position: 'relative',
                '&:hover': {
                    cursor: 'pointer'
                }
            }, colorMap[color].tile),
            content: {
                fontSize: '2rem',
                fontWeight: 'bold'
            },
            title: {
                textTransform: 'uppercase'
            },
            icon: {
                position: 'absolute',
                top: 0,
                left: 0
            }
        }),
        big: (theme: any) => ({
            tile: Object.assign({
                minWidth: theme.spacing(20),
                height: theme.spacing(20),
                position: 'relative',
                '&:hover': {
                    cursor: 'pointer'
                }
            }, colorMap[color].tile),
            content: {
                fontSize: '2rem',
                fontWeight: 'bold'
            },
            title: {
                textTransform: 'uppercase'
            },
            icon: {
                position: 'absolute',
                top: 0,
                left: 0
            }
        }),
        large: (theme: any) => ({
            tile: Object.assign({
                minWidth: theme.spacing(25),
                height: theme.spacing(25),
                position: 'relative',
                '&:hover': {
                    cursor: 'pointer'
                }
            }, colorMap[color].tile),
            content: {
                fontSize: '2rem',
                fontWeight: 'bold'
            },
            title: {
                textTransform: 'uppercase'
            },
            icon: {
                position: 'absolute',
                top: 0,
                left: 0
            }
        })
    }

    return makeStyles(variants[variant])
}

type BigTileProps = {
    color?: 'default' | 'grey' | 'green' | 'blue' | 'teal',
    variant?: 'small' | 'default' | 'big' | 'large',
    width?: string, // 15px , 10rem etc
    height?: string, // 15px , 10rem etc
    title?: string,
    content?: string
    icon?: React.FC | React.ReactElement
}

const PosedPaper = posed(Paper)({
    onHover: {
        scale: 1.05
    },
    none: {
        scale: 1
    }
})

const BigTile: React.FC<BigTileProps> = ({
    variant = 'default',
    color = 'default',
    width,
    height,
    children,
    title,
    content,
    icon,
    ...props
}) => {
    const [hover, setHover] = React.useState(false)
    const useStyles = styleProducer(variant, color)
    const classes = useStyles()
    const onHoverHandle = (bool: boolean) => () => {
        setHover(bool)
    }
    const style = {height, width}
    if (!height) delete style['height']
    if (!width) delete style['width']

    return (

        <PosedPaper className={classes.tile} style={{ height, width }} pose={hover ? 'onHover' : 'none'} onMouseEnter={onHoverHandle(true)} onMouseLeave={onHoverHandle(false)}>
            <Box className={classes.icon} p={1}>
                {icon}
            </Box>
            <Box height="100%" width="100%" display="flex" justifyContent="center" alignItems="center" flexDirection="column">
                <Box mb={1} className={classes.content}>{children ? children : content}</Box>
                <div className={classes.title}>{title}</div>
            </Box>
        </PosedPaper>
    )
}
export default BigTile

在这里我看不到鼠标悬停事件后改变的样式。控制台日志只显示我转换:无 当它应该是像转换:比例(1.05)。 请帮助我正确触发此事件,如果您对代码本身有一些建议,那么采纳一些建议会很棒。

1 个答案:

答案 0 :(得分:0)

//答案

每次我开始测试时都会触发事件。 为了检查它,我只是在 onHoverHandle 里面放了一些 console.log(..) ,它在 moseenter/leave 之后触发。

当然我不需要在fireEvent之后再次找到元素,因为我之前有这个元素。主要想法是我需要在检查样式更改之前等待事件结束。所以 waitFor 对此有好处。 我在某处阅读了比使用来自 '@testing-library/user-event' 的 userEvent 比 fireEvent 更好的地方,所以我做到了。

最终解决方案:

    it('BigTile hover check.', async ()=>{
        const { container } = render(<BigTile />)
        const elem = container.firstChild as HTMLElement
        if (!elem) fail("Element is null.")
        userEvent.hover(elem);
        await waitFor(() => {
            expect(elem.style.transform).toEqual("scale(1.05) translateZ(0)")
        })
    })