Myk*_*rat 10 unit-testing reactjs jestjs enzyme formik
TL; 博士
如何使用 Jest 和 Enzyme 为带有“useField”钩子的组件编写单元测试?在浅渲染时,我收到此错误
Warning: Formik context is undefined, please verify you are calling
useFormikContext() as child of a <Formik> component
TypeError: Cannot read property 'getFieldProps' of undefined
Run Code Online (Sandbox Code Playgroud)
细节
该项目构建与
这是一个学习项目,所以我正在尝试不同的方法。这就是为什么我将所有组件放在不同的文件中,认为这可能没有必要。
结构:
Formik.tsx
|
| AddContactForm.tsx
|
| TextInput.tsx
| TextInput.test.tsx
Run Code Online (Sandbox Code Playgroud)
细节:
Formik.tsx 只是一个包装器,我们拥有表单的所有属性
<Formik
initialValues={initialValues}
validationSchema={...}
onSubmit={...};
component={AddContactForm}
/>
Run Code Online (Sandbox Code Playgroud)
AddContactForm.tsx 在这里,我将字段元和道具传递给输入。这似乎不是最好的解决方案,我想在组件本身内部使用 useField() 钩子
<Form>
<TextInput
label="First Name"
name={"firstName"}
placeholder="Jane"
field={getFieldProps("firstName")}
meta={getFieldMeta("firstName")}
/>
<button type="submit">Submit</button>
</Form>
Run Code Online (Sandbox Code Playgroud)
TextInput.tsx 这是当前的解决方案 - 我可以为它编写单元测试 - 例如快照测试。
const TextInput: React.FC<MyInput> = React.memo(
({ label, field, meta}: MyInput) => {
return (
<>
<TextField
label={label}
type="text"
{...field}
error={meta?.touched && meta?.error ? true : undefined}
helperText={meta?.touched ? meta?.error : undefined}
/>
</>
);
}
);
Run Code Online (Sandbox Code Playgroud)
TextInput.test.tsx 这里我必须写一个很大的 mockProps 对象来模拟所有的东西:(
describe("<TextInput/>", () => {
it("Match Snapshot", () => {
const mockProps: MyInput = {
label: "label",
name: "name",
placeholder: "placeholder",
meta: {
touched: false,
error: "",
initialError: "",
initialTouched: false,
initialValue: "",
value: "",
},
field: {
value: "",
checked: false,
onChange: jest.fn(),
onBlur: jest.fn(),
multiple: undefined,
name: "firstName",
},
};
expect(
shallow(
<TextInput
label="label"
name="name"
placeholder="placeholder"
{...mockProps.meta}
{...mockProps.field}
/>
)
).toMatchSnapshot();
});
});
Run Code Online (Sandbox Code Playgroud)
相反,我想要的是不是通过道具而是通过 useField() 钩子来获取字段和元数据。
文本字段.tsx
const TextInput: React.FC<MyInput> = React.memo(
({ label, ...props }: MyInput) => {
const [field, meta] = useField(props);
return (
<>
<TextField
label={label}
type="text"
{...field}
{...props}
error={meta?.touched && meta?.error ? true : undefined}
helperText={meta?.touched ? meta?.error : undefined}
/>
</>
);
}
);
Run Code Online (Sandbox Code Playgroud)
但是后来我不知道如何为它编写测试。似乎它希望在测试中包含 Formik 上下文,但不可能在测试文件中使用 useFormikContext() 钩子,因为它违反了钩子使用规则。
要了解有关 Jest 中的 Mocking 的更多信息,您应该阅读以下官方文档:
您还可以查看Enzyme 的ShallowWrapperAPI 文档
// TextInput.test.tsx
import React from 'react';
import { useField } from 'formik'; // package will be auto mocked
import TextInput from '...';
jest.mock('formik'); // formik package is auto mocked
describe("<TextInput/>", () => {
it("Match Snapshot", () => {
const mockMeta = {
touched: false,
error: "",
initialError: "",
initialTouched: false,
initialValue: "",
value: "",
}
const mockField = {
value: "",
checked: false,
onChange: jest.fn(),
onBlur: jest.fn(),
multiple: undefined,
name: "firstName",
};
useField.mockReturnValue([mockField, mockMeta]);
const mockProps = {...};
expect(
shallow(<TextInput {...mockProps} />).debug()
).toMatchSnapshot();
});
});
Run Code Online (Sandbox Code Playgroud)
// TextInput.tsx
import React from 'react';
import { useField } from 'formik';
import ...
const TextInput: React.FC<MyInput> = React.memo(
({ label, ...props }: MyInput) => {
const [field, meta] = useField(props);
return (
<>
<TextField
label={label}
type="text"
{...field}
{...props}
error={meta?.touched && meta?.error ? true : undefined}
helperText={meta?.touched ? meta?.error : undefined}
/>
</>
);
}
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3275 次 |
| 最近记录: |