reactjs - React/Jest:模拟用户篡改 HTML
问题描述
在 React vanilla 表单中,我需要解决用户手动编辑选项值以使表单提交错误值的问题。
为了重现,用户检查元素,并手动将value
an更改option
为无效值(按域)。
修复很简单,但我想在修复之前以 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')
})
解决方案
我以前也有过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()
})
推荐阅读
- python - 文字标签不显示
- imagej - 如何在运行时查找、读取、写入 Jython 注册表
- eclipse - java.lang.NullPointerException:条目中的空值:lastScrollData=null
- sql - 在 SQL 中聚合具有条件的行
- angular - @agm/core 模块在 '@angular/core' 中找不到 angular 7 'ɵɵdefineInjectable' 错误
- c++ - 使用函数指针作为 UI-Button 回调的缺点
- python - 使用 numpy 快速查找子矩阵
- mysql - Node.js:每次用户刷新时 MySQL 都会获取新数据做一些奇怪的事情
- sql - 如何在从另一列获取其他值的同时使用 Max?
- python - 如何在 Kivy (Python3) 中动态创建多个函数?