import { mount } from 'enzyme'; import type { Formik, FormikProps } from 'formik'; import React from 'react'; import { SpinFormik } from '../SpinFormik'; import { FormikFormField } from '../fields'; import { SelectInput } from '../inputs'; import { useSaveRestoreMutuallyExclusiveFields } from './useSaveRestoreMutuallyExclusiveFields.hook'; function PizzaComponent() { return ( <> } /> } /> } /> } /> ); } function SandwichComponent() { return ( <> } /> } /> } /> ); } function OrderComponent({ formik }: { formik: FormikProps }) { useSaveRestoreMutuallyExclusiveFields(formik, formik.values.pizzaOrSandwich, { pizza: ['topping', 'crust', 'sauce', 'cheese'], sandwich: ['bread', 'meat', 'cheese'], }); // Note: none of the FormikFormField components are necessary for these unit tests to work. // However, they provide clarity to the reader regarding what the hook intends to do. return ( <> } /> {formik.values.pizzaOrSandwich === 'pizza' && } {formik.values.pizzaOrSandwich === 'sandwich' && } ); } const initialValues = { pizzaOrSandwich: 'pizza', topping: 'pepperoni', crust: 'thin', sauce: 'red', cheese: 'cheddar', }; const setupTest = (formikRef: React.MutableRefObject) => { return mount( } />, ); }; describe('useSaveRestoreMutuallyExclusiveFields hook', () => { it(`clears out previously entered 'pizza' fields when the user chooses 'sandwich'`, () => { const formikRef = React.createRef(); const wrapper = setupTest(formikRef); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); // cleared out the pizza field from the formik values expect(formikRef.current.getFormikBag().values).toEqual({ pizzaOrSandwich: 'sandwich' }); }); it(`clears out 'touched' status for 'pizza' fields when the user chooses 'sandwich'`, () => { const formikRef = React.createRef(); const wrapper = setupTest(formikRef); formikRef.current.setFieldTouched('topping', true); formikRef.current.setFieldTouched('crust', true); expect(formikRef.current.getFormikBag().touched.topping).toBe(true); expect(formikRef.current.getFormikBag().touched.crust).toBe(true); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); expect(formikRef.current.getFormikBag().touched.topping).toBe(null); expect(formikRef.current.getFormikBag().touched.crust).toBe(null); }); it(`restores previously saved 'pizza' fields when toggling back to 'pizza'`, () => { const formikRef = React.createRef(); const wrapper = setupTest(formikRef); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); formikRef.current.setFieldValue('pizzaOrSandwich', 'pizza'); wrapper.setProps({}); // restored the pizza fields expect(formikRef.current.getFormikBag().values).toEqual({ pizzaOrSandwich: 'pizza', topping: 'pepperoni', crust: 'thin', sauce: 'red', cheese: 'cheddar', }); }); it(`restores previously saved touched statuses for 'pizza' fields when toggling back to 'pizza'`, () => { const formikRef = React.createRef(); const wrapper = setupTest(formikRef); formikRef.current.setFieldTouched('topping', true); formikRef.current.setFieldTouched('crust', true); expect(formikRef.current.getFormikBag().touched.topping).toBe(true); expect(formikRef.current.getFormikBag().touched.crust).toBe(true); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); formikRef.current.setFieldValue('pizzaOrSandwich', 'pizza'); wrapper.setProps({}); expect(formikRef.current.getFormikBag().touched.topping).toBe(true); expect(formikRef.current.getFormikBag().touched.crust).toBe(true); }); it(`restores previously saved 'pizza' and 'sandwich' fields when toggling back and forth`, () => { const formikRef = React.createRef(); const wrapper = setupTest(formikRef); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); formikRef.current.setFieldValue('bread', 'wheat'); formikRef.current.setFieldValue('meat', 'ham'); formikRef.current.setFieldValue('cheese', 'cheddar'); wrapper.setProps({}); formikRef.current.setFieldValue('pizzaOrSandwich', 'pizza'); wrapper.setProps({}); // restored the pizza fields expect(formikRef.current.getFormikBag().values).toEqual({ pizzaOrSandwich: 'pizza', topping: 'pepperoni', crust: 'thin', sauce: 'red', cheese: 'cheddar', }); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); // restored the sandwich fields expect(formikRef.current.getFormikBag().values).toEqual({ pizzaOrSandwich: 'sandwich', bread: 'wheat', meat: 'ham', cheese: 'cheddar', }); }); it(`saves and restores different values for keys that exist in multiple field sets`, () => { const formikRef = React.createRef(); const wrapper = setupTest(formikRef); formikRef.current.setFieldValue('cheese', 'mozzarella'); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); formikRef.current.setFieldValue('bread', 'wheat'); formikRef.current.setFieldValue('meat', 'ham'); formikRef.current.setFieldValue('cheese', 'cheddar'); formikRef.current.setFieldValue('pizzaOrSandwich', 'pizza'); wrapper.setProps({}); // restored the pizza fields expect(formikRef.current.getFormikBag().values.cheese).toEqual('mozzarella'); formikRef.current.setFieldValue('pizzaOrSandwich', 'sandwich'); wrapper.setProps({}); // restored the sandwich fields expect(formikRef.current.getFormikBag().values.cheese).toEqual('cheddar'); }); });