web-dev-qa-db-fra.com

Unité de test d'un composant formik avec jest/enzyme

J'ai mis en place un formulaire de contact assez simple qui fonctionne parfaitement. Cependant, je dois maintenant commencer à écrire mes tests unitaires et j'ai rencontré beaucoup de problèmes (comme si je n'avais littéralement réussi qu'à obtenir un test de capture instantanée jusqu'à présent).

Donc, pour commencer, j'essaie de vérifier que le formulaire doit afficher mes messages de validation lorsque vous cliquez sur le bouton Envoyer si vous n'avez pas rempli toutes les sections requises.

Je pensais pouvoir y parvenir en appelant la fonction handleSubmit(), par exemple: componentRender.find('Formik').instance().props.handleSubmit(badFormValues, { resetForm });

Cependant, lorsque j'exécute componentRender.debug(), mes messages de validation ne sont pas rendus. C'est comme si la fonction validationSchema n'était pas appelée?

Y a-t-il quelque chose de spécial à faire? J'ai l'impression que la fonction mapPropsToValues() fonctionne, en regardant l'objet d'état dans lequel il est rempli avec les valeurs que je transmets au formulaire. Je ne vois tout simplement pas pourquoi la validation est apparemment ignorée?

Cela fait deux jours que je suis dans ce domaine et je ne trouve aucun bon exemple sur Google (probablement de ma faute), alors toute aide serait massivement appréciée.

Pour référence, voici le fichier de test jusqu'à présent:

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: '[email protected]',
    };

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

Et voici ma fonction 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:[email protected]?subject=New partner request&body=${emailBody}`;
        resetForm();
    },
})(PartnerRegistrationForm);

5
Fabio Felizzi

Cela pourrait ne pas fonctionner si vous essayez de soumettre le formulaire en cliquant sur un bouton avec type="submit"

J'ai trouvé le seul moyen de le soumettre (et donc d'effectuer des validations) en le simulant directement:

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

... et vous devrez peut-être utiliser les éléments suivants pour mettre à jour le wrapper après la validation async de Formik et les modifications d'état:

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

N'oubliez pas d'utiliser done() ou async attendez pour que le test ne se termine pas tôt.

2
spencer.sm