Skip to content

Commit

Permalink
Add test coverage to FormDataProvider to subscribe to updated form value
Browse files Browse the repository at this point in the history
  • Loading branch information
sebelga committed Aug 26, 2020
1 parent c529e80 commit 44b5572
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import React, { useState } from 'react';
import { act } from 'react-dom/test-utils';

import { registerTestBed, TestBed } from '../shared_imports';
Expand All @@ -36,13 +36,14 @@ describe('<FormDataProvider />', () => {
return (
<Form form={form}>
<UseField path="name" defaultValue="Initial value" data-test-subj="nameField" />
<UseField path="lastName" defaultValue="Initial value" data-test-subj="lastNameField" />
<FormDataProvider>
{(formData) => {
onFormData(formData);
return null;
}}
</FormDataProvider>
{/* Putting one field below to make sure the order in the DOM does not affect behaviour */}
<UseField path="lastName" defaultValue="Initial value" data-test-subj="lastNameField" />
</Form>
);
};
Expand Down Expand Up @@ -95,6 +96,63 @@ describe('<FormDataProvider />', () => {
});
});

test('should subscribe to the latest updated form data when mounting late', async () => {
const onFormData = jest.fn();

const TestComp = () => {
const { form } = useForm();
const [isOn, setIsOn] = useState(false);

return (
<Form form={form}>
<UseField path="name" defaultValue="Initial value" data-test-subj="nameField" />
<button onClick={() => setIsOn(true)} data-test-subj="btn">
Toggle On
</button>
{isOn && (
<FormDataProvider>
{(formData) => {
onFormData(formData);
return null;
}}
</FormDataProvider>
)}
</Form>
);
};

const setup = registerTestBed(TestComp, {
memoryRouter: { wrapComponent: false },
});

const {
form: { setInputValue },
find,
} = setup() as TestBed;

expect(onFormData.mock.calls.length).toBe(0); // Not present in the DOM yet

// Make some changes to the form fields
await act(async () => {
setInputValue('nameField', 'updated value');
});

// Update state to trigger the mounting of the FormDataProvider
await act(async () => {
find('btn').simulate('click').update();
});

expect(onFormData.mock.calls.length).toBe(1);

const [formDataUpdated] = onFormData.mock.calls[onFormData.mock.calls.length - 1] as Parameters<
OnUpdateHandler
>;

expect(formDataUpdated).toEqual({
name: 'updated value',
});
});

test('props.pathsToWatch (string): should not re-render the children when the field that changed is not the one provided', async () => {
const onFormData = jest.fn();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const FormDataProvider = React.memo(({ children, pathsToWatch }: Props) =
const form = useFormContext();
const { subscribe } = form;
const previousRawData = useRef<FormData>(form.__getFormData$().value);
const isMounted = useRef(false);
const [formData, setFormData] = useState<FormData>(previousRawData.current);

const onFormData = useCallback(
Expand Down Expand Up @@ -59,7 +60,14 @@ export const FormDataProvider = React.memo(({ children, pathsToWatch }: Props) =
return subscription.unsubscribe;
}, [subscribe, onFormData]);

if (Object.keys(formData).length === 0) {
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);

if (!isMounted.current && Object.keys(formData).length === 0) {
// No field has mounted yet, don't render anything
return null;
}
Expand Down

0 comments on commit 44b5572

Please sign in to comment.