[英]Unit testing a formik component with jest/enzyme
I've put together a pretty basic contact form that works just fine.我已经整理了一个非常基本的联系表格,效果很好。 However I now need to start writing my unit tests and I've run into a load of problems (like I literally have only managed to get a snapshot test to pass so far).然而,我现在需要开始编写我的单元测试,但我遇到了很多问题(就像我目前只能设法通过快照测试)。
So to start with I'm trying to test that the form should render my validation messages when you click the submit button if you have not filled out all the required sections.因此,首先,如果您没有填写所有必需的部分,我会尝试测试当您单击提交按钮时表单是否应该呈现我的验证消息。
I thought I could achieve this by calling the handleSubmit()
function eg: componentRender.find('Formik').instance().props.handleSubmit(badFormValues, { resetForm });
我以为我可以通过调用handleSubmit()
函数来实现这一点,例如: componentRender.find('Formik').instance().props.handleSubmit(badFormValues, { resetForm });
However when I run componentRender.debug()
, my validation messages aren't being rendered.但是,当我运行componentRender.debug()
,没有呈现我的验证消息。 It's like the validationSchema function isn't being called?就像没有调用validationSchema函数一样?
Is there something special that needs to be done?有什么特别需要做的吗? I feel like the mapPropsToValues()
function is working, from looking at the state object it's being populated with the values I'm passing the form.我觉得mapPropsToValues()
函数正在工作,从查看它正在填充我传递表单的值的状态对象。 I just can't see why validation is seemingly being skipped?我就是不明白为什么验证似乎被跳过了?
I've been at this for 2 days now and can't find any good examples through google (probably my fault) so any help would be massively appreciated.我已经在这里呆了 2 天了,无法通过谷歌找到任何好的例子(可能是我的错)所以任何帮助都将不胜感激。
For reference here is the test file so far:参考这里是迄今为止的测试文件:
import React from 'react'; import { shallow, mount } from 'enzyme'; import { BrowserRouter as Router } from 'react-router-dom'; import PartnerRegistrationForm from 'Components/partner-registration-form/PartnerRegistrationForm'; describe('PartnerRegistrationForm component', () => { const formValues = { companyName: 'some company', countryCode: 'GB +44', telNumber: 12345678, selectCountry: 'United Kingdom', postcode: 'ABC1 234', addressSelect: '123 street', siteName: 'blah', siteURL: 'https://www.blah.com', contactName: 'Me', email: 'me@me.com', }; const componentShallow = shallow(<PartnerRegistrationForm {...formValues} />); describe('Component Snapshot', () => { it('should match stored snapshot', () => { expect(componentShallow).toMatchSnapshot(); }); }); describe('Component functionality', () => { it('should not submit if required fields are empty', () => { const badFormValues = { companyName: 'some company', countryCode: 'GB +44', telNumber: 12345678, }; const resetForm = jest.fn(); const componentRender = mount( <Router> <PartnerRegistrationForm {...badFormValues} /> </Router>, ); componentRender.find('Formik').instance().props.handleSubmit(badFormValues, { resetForm }); // console.log(componentRender.update().find('.validation-error')); // console.log(componentRender.find('Formik').instance()); // expect(componentRender.find('.validation-error').text()).toEqual('Company Name is required'); }); }); });
And here is my withFormik()
function:这是我的withFormik()
函数:
const WrappedFormWithFormik = withFormik({ mapPropsToValues({ companyName, countryCode, telNumber, selectCountry, postcode, addressSelect, siteName, siteURL, contactName, email, }) { return { companyName: companyName || '', countryCode: countryCode || '', telNumber: telNumber || '', selectCountry: selectCountry || '', postcode: postcode || '', addressSelect: addressSelect || '', siteName: siteName || '', siteURL: siteURL || '', contactName: contactName || '', email: email || '', }; }, validationSchema, // This is a standard Yup.object(), just importing it from a separate file handleSubmit: (values, { resetForm }) => { console.log('submitting'); const { companyName, countryCode, telNumber, selectCountry, postcode, addressSelect, siteName, siteURL, contactName, email, } = values; const emailBody = `Name: ${contactName},` + `Email: ${email},` + `Company Name: ${companyName},` + `Country Code: ${countryCode},` + `Telephone Number: ${telNumber},` + `Country: ${selectCountry},` + `Postcode: ${postcode},` + `Address: ${addressSelect},` + `Website Name: ${siteName},` + `Website URL: ${siteURL}`; // TODO set up actual contact submit logic window.location.href = `mailto:test@test.com?subject=New partner request&body=${emailBody}`; resetForm(); }, })(PartnerRegistrationForm);
It might not work if you are trying to submit the form by clicking on a button with type="submit"
如果您尝试通过单击type="submit"
的按钮来提交表单,则它可能不起作用
I've found the only way to get it to submit (and thus run validations) was by simulating it directly:我发现让它提交(并因此运行验证)的唯一方法是直接模拟它:
const form = wrapper.find('form');
form.simulate('submit', { preventDefault: () => {} });
...and additionally you might need to use something like the following to update the wrapper after formik's async validation and state changes: ...此外,在 formik 的异步验证和状态更改后,您可能需要使用类似以下内容来更新包装器:
setTimeout(() => {
wrapper.update();
}, 0);
Don't forget to use done()
or async await so the test doesn't terminate early.不要忘记使用done()
或 async await 这样测试不会提前终止。
You can trigger props directly using prop(key)
可以直接使用prop(key)
触发 props
wrapper.find(Formik).prop('onSubmit')(args)
wrapper.find(Component).prop('onSubmit')(args)
You can also simulate onclick
using simulate(event)
您还可以使用simulate(event)
模拟onclick
const mockHandleSubmit = jest.fn()
const wrapper = shallow(<Form onSubmit={mockHandleSubmit} />)
wrapper.find(SubmitButton).simulate('click')
expect(mockHandleSubmit).toHaveBeenCalled();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.