【问题标题】:React testing library fireEvent not firing / found answerReact 测试库 fireEvent 未触发/找到答案
【发布时间】:2021-07-04 19:23:54
【问题描述】:

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

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

这是我的测试:

    it('BigTile hover check', ()=>{
        const { container } = render(<BigTile />)
        const elem = container.querySelector<HTMLElement>('.MuiPaper-root')
        if (!elem) fail("Element is null.")
        fireEvent.mouseOver(elem);
        const elemAfterHover = container.querySelector<HTMLElement>('.MuiPaper-root')
        if (!elemAfterHover) fail("Element after hover is null.")
        console.log(elemAfterHover.style)
    })

在鼠标悬停事件后我看不到更改的样式。控制台日志只显示了 transform:none 什么时候应该像变换:比例(1.05)。 请帮助我正确触发此事件,如果您对代码本身有一些建议,请采纳一些建议。

【问题讨论】:

    标签: reactjs typescript react-testing-library


    【解决方案1】:

    //回答

    每次我开始测试时都会触发该事件。 为了检查它,我只是在 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)")
            })
        })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-16
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 2021-10-19
      • 2021-09-27
      • 2021-01-08
      • 1970-01-01
      相关资源
      最近更新 更多