【问题标题】:Unit testing a formik component with jest/enzyme使用 jest/enzyme 对 formik 组件进行单元测试
【发布时间】:2021-02-04 09:39:22
【问题描述】:

我已经整理了一个非常基本的联系表格,效果很好。但是我现在需要开始编写我的单元测试并且我遇到了很多问题(就像我到目前为止只设法让快照测试通过)。

所以首先我尝试测试如果您没有填写所有必需的部分,当您单击提交按钮时表单应该呈现我的验证消息。

我想我可以通过调用handleSubmit() 函数来实现这一点,例如: componentRender.find('Formik').instance().props.handleSubmit(badFormValues, { resetForm });

但是,当我运行 componentRender.debug() 时,我的验证消息没有被呈现。好像没有调用validationSchema函数?

有什么特别的事情需要做吗?我觉得mapPropsToValues() 函数正在工作,从查看它正在填充我传递表单的值的状态对象。我只是不明白为什么似乎跳过了验证?

我已经在这里工作了 2 天,通过谷歌找不到任何好的例子(可能是我的错),所以任何帮助都将不胜感激。

目前为止的测试文件供参考:

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');
        });
    });
});

这是我的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);

【问题讨论】:

  • 你终于让它工作了吗?

标签: javascript reactjs jestjs enzyme formik


【解决方案1】:

如果您尝试通过单击带有type="submit" 的按钮来提交表单,它可能不起作用

我发现让它提交(并因此运行验证)的唯一方法是直接模拟它:

const form = wrapper.find('form');
form.simulate('submit', { preventDefault: () => {} });

...另外,在 formik 的异步验证和状态更改之后,您可能需要使用类似以下内容来更新包装器:

setTimeout(() => {
  wrapper.update();
}, 0);

不要忘记使用 done() 或 async await,这样测试就不会提前终止。

【讨论】:

  • 能否请您解释一下,为什么我们需要使用 done 或 async?它是特定于 formik 库还是我们必须将它用于每种类型的表单?
  • React 测试库似乎也是这种情况:单击提交按钮不起作用;您必须获取表单并提交。
  • 您能解释一下为什么按钮上的 onSubmit 不起作用吗?
  • 我收到警告:测试中 Formik 的更新未包含在 act(...) 中。
【解决方案2】:

你可以直接使用prop(key)触发道具

wrapper.find(Formik).prop('onSubmit')(args)
wrapper.find(Component).prop('onSubmit')(args)

您也可以使用simulate(event)模拟onclick

const mockHandleSubmit = jest.fn()
const wrapper = shallow(<Form onSubmit={mockHandleSubmit} />)
wrapper.find(SubmitButton).simulate('click')
expect(mockHandleSubmit).toHaveBeenCalled();

【讨论】:

    猜你喜欢
    • 2019-12-08
    • 2021-06-24
    • 2019-10-26
    • 2019-07-28
    • 2018-12-16
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    相关资源
    最近更新 更多