简体   繁体   English

使用 jest/enzyme 对 formik 组件进行单元测试

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM