【问题标题】:React/Jest: Simulate users tampering with the HTMLReact/Jest:模拟用户篡改 HTML
【发布时间】:2021-11-04 16:30:30
【问题描述】:

在 React vanilla 表单中,我需要解决用户手动编辑选项值以使表单提交错误值的问题。

为了重现,用户检查元素,并手动将 optionvalue 更改为无效值(按域)。

修复很简单,但我想在修复之前创建一个失败的单元测试,以 TDD 方式,并且不知道如何在测试中对此建模。我使用 jest 和 react-testing-library。

表格代码如下:

export const CreateTripForm = ({ countries, onSubmit }) => {
    const [countryId, setCountryId] = useState()

    const submit = async (e) => {
        e.preventDefault()
        if (countryId === undefined) return 

        await onSubmit(countryId)
    }

    return (
        <form onSubmit={submit}>
            <legend>Choose a country</legend>
            
            <label htmlFor="countryId">Country</label>
            <select name="countryId" required value={countryId} onChange={(e) => setCountryId(e.target.value)}>
                <option value=""></option>
                {countries.map((country) =>
                    <option key={country.id} value={country.id}>{country.label}</option>
                )}
            </select>

            <input type="submit" value="Create a trip" />
        </form>
    )
}

这是我尝试做的,但测试通过而不是失败:

it('keeps previous countryId if the selected one has been tampered with', () => {
    const onSubmit = jest.fn(() => Promise.resolve())

    const countries = [
        { id: 'fr', label: 'France' },
        { id: 'en', label: 'England' },
    ]

    const { container } = render(
        <CreateTripForm countries={countries} onSubmit={onSubmit} />
    )

    const select = container.querySelector('select[name=countryId]')
    const submitButton = container.querySelector('input[type=select]')

    // Select the 'fr' option, it works.
    fireEvent.change(select, { target: { value: 'fr' } })

    submitButton.click()
    expect(onSubmit).toHaveBeenCalledWith('fr')

    // Edit an option to have an incorrect value, it should keep the previous value.
    elements.unitSelect.options[2].value = 'asgard'
    fireEvent.change(select, { target: { value: 'asgard' } })

    submitButton.click()
    expect(onSubmit).toHaveBeenCalledWith('fr')
})

【问题讨论】:

    标签: reactjs unit-testing jestjs react-testing-library


    【解决方案1】:

    我以前在expect() 上遇到过一些像这样的糟糕经历。
    您是否尝试过将测试分开?一个代表成功,一个代表失败?
    据我所知,第一个 expect() 并没有重置他已经被称为的内容,所以我想这就是为什么你的测试通过了第二个 expect()
    试试这样:

    it('keeps previous countryId if the selected one has been tampered with', () => {
        const onSubmit = jest.fn(() => Promise.resolve())
    
        const countries = [
            { id: 'fr', label: 'France' },
            { id: 'en', label: 'England' },
        ]
    
        const { container } = render(
            <CreateTripForm countries={countries} onSubmit={onSubmit} />
        )
    
        const select = container.querySelector('select[name=countryId]')
        const submitButton = container.querySelector('input[type=select]')
    
        // Select the 'fr' option, it works.
        fireEvent.change(select, { target: { value: 'fr' } })
    
        submitButton.click()
        expect(onSubmit).toHaveBeenCalledWith('fr')
    })
    
    it('should prevent sending with tampered select', () => {
        const onSubmit = jest.fn(() => Promise.resolve())
        const countries = [
            { id: 'fr', label: 'France' },
            { id: 'en', label: 'England' },
        ]
        const { container } = render(
            <CreateTripForm countries={countries} onSubmit={onSubmit} />
        )
        const select = container.querySelector('select[name=countryId]')
        const submitButton = container.querySelector('input[type=select]')
        elements.unitSelect.options[2].value = 'asgard'
        fireEvent.change(select, { target: { value: 'asgard' } })
    
        submitButton.click()
        expect(onSubmit).not.toHaveBeenCalled()
    })
    

    【讨论】:

    • 感谢您的回答!我明白了,但我想要的不是在被篡改时阻止提交,而是保持以前的值,这就是为什么我在同一个测试中同时拥有两个 expects。
    • 但是你没有保留之前的值。一旦触发选择更改为“asgard”,就会调用 onChange 回调并将 countryId 设置为“asgard”。我对你想要测试的内容有点困惑,你能再澄清一下吗?
    猜你喜欢
    • 2019-04-24
    • 2017-02-23
    • 2019-08-15
    • 2020-12-04
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 2018-05-05
    相关资源
    最近更新 更多