gpt4 book ai didi

reactjs - 使用 React-testing 库提交 Formik 表单

转载 作者:行者123 更新时间:2023-12-03 14:25:34 25 4
gpt4 key购买 nike

我正在寻找触发登录表单的提交处理程序。然而,由于某种原因,组件的实际处理程序被触发(调用外部 api),而不是调用我的模拟函数。如何确保我的模拟处理程序被调用?

感兴趣的三个组件如下(演示、容器和测试套件)

登录表单.js

import { Formik, Form, Field } from 'formik';
import { CustomInput } from '..';

const LoginForm = ({ initialValues, handleSubmit, validate }) => {
return (
<Formik
initialValues={initialValues}
validate={validate}
onSubmit={handleSubmit}
>
{({ isSubmitting, handleSubmit }) => {
return (
<Form onSubmit={handleSubmit}>
<div className="d-flex flex-column justify-content-center align-items-center">
<Field
data-testid="usernameOrEmail"
type="text"
name="identifier"
placeholder="Username/Email"
component={CustomInput}
inputClass="mb-4 mt-2 text-monospace"
/>
<Field
data-testid="login-password"
type="password"
name="password"
placeholder="Password"
component={CustomInput}
inputClass="mb-4 mt-4 text-monospace"
/>
<button
data-testid="login-button"
className="btn btn-primary btn-lg mt-3 text-monospace"
type="submit"
disabled={isSubmitting}
style={{ textTransform: 'uppercase', minWidth: '12rem' }}
>
Submit
</button>
</div>
</Form>
)}}
</Formik>
);
};

export default LoginForm;

登录页面.js

import React, { useContext } from 'react';
import { loginUser } from '../../services';
import { userContext } from '../../contexts';
import { loginValidator } from '../../helpers';
import { setAuthorizationToken, renderAlert } from '../../utils';
import LoginForm from './login-form';

const INITIAL_VALUES = { identifier: '', password: '' };

const LoginPage = props => {
const { handleUserData, handleAuthStatus } = useContext(userContext);

const handleSubmit = async (values, { setSubmitting }) => {
try {
const result = await loginUser(values);
handleAuthStatus(true);
handleUserData(result.data);
setAuthorizationToken(result.data.token);
props.history.push('/habits');
renderAlert('success', 'Login Successful');
} catch (err) {
renderAlert('error', err.message);
}
setSubmitting(false);
};

return (
<LoginForm
initialValues={INITIAL_VALUES}
validate={values => loginValidator(values)}
handleSubmit={handleSubmit}
/>
);
};

export default LoginPage;

LoginPage.spec.js

import React from 'react';
import { cleanup, getByTestId, fireEvent, wait } from 'react-testing-library';
import { renderWithRouter } from '../../../helpers';
import LoginPage from '../login-page';

afterEach(cleanup);
const handleSubmit = jest.fn();

test('<LoginPage /> renders with blank fields', () => {
const { container } = renderWithRouter(<LoginPage />);

const usernameOrEmailNode = getByTestId(container, 'usernameOrEmail');
const passwordNode = getByTestId(container, 'login-password');
const submitButtonNode = getByTestId(container, 'login-button');

expect(usernameOrEmailNode.tagName).toBe('INPUT');
expect(passwordNode.tagName).toBe('INPUT');
expect(submitButtonNode.tagName).toBe('BUTTON');
expect(usernameOrEmailNode.getAttribute('value')).toBe('');
expect(passwordNode.getAttribute('value')).toBe('');
});

test('Clicking the submit button after entering values', async () => {
const { container } = renderWithRouter(<LoginPage handleSubmit={handleSubmit} />);

const usernameOrEmailNode = getByTestId(container, 'usernameOrEmail');
const passwordNode = getByTestId(container, 'login-password');
const submitButtonNode = getByTestId(container, 'login-button');

fireEvent.change(usernameOrEmailNode, { target: { value: fakeUser.username }});
fireEvent.change(passwordNode, { target: { value: fakeUser.password }});
fireEvent.click(submitButtonNode);

await wait(() => {
expect(handleSubmit).toHaveBeenCalledTimes(1);
});


expect(usernameOrEmailNode.tagName).toBe('INPUT');
expect(passwordNode.tagName).toBe('INPUT');
expect(submitButtonNode.tagName).toBe('BUTTON');
expect(usernameOrEmailNode.getAttribute('value')).toBe('');
expect(passwordNode.getAttribute('value')).toBe('');
});```

最佳答案

要回答您的问题,您需要首先在 LoginPage.js 外部访问 handleSubmit 常量,以便可以对其进行模拟然后进行测试。例如,

LoginPage.js

export const handleSubmit = async (values, { setSubmitting }) => {
... code to handle submission
})

在您的测试中 - LoginPage.spec.js

jest.unmock('./login-page');
import LoginPage, otherFunctions from '../login-page'
otherFunctions.handleSubmit = jest.fn();

...
test('Clicking the submit button after entering values', () => {
...
fireEvent.click(submitButtonNode);
expect(handleSubmit).toHaveBeenCalledTimes(1);
})

希望以上内容能解决您的问题。

But, going by the philosophy of unit testing, the above components must not be tested the way you are doing it. Instead your test setup should be like this -

  1. Add a new test file called LoginForm.spec.js that tests your LoginForm component. You would test the following in this -
    1. Check if all input fields have been rendered.
    2. Check if the correct handler is called on submit and with the correct parameters.
  2. The existing test file called LoginPage.spec.js would then only test if the particular form was rendered and then you could also test what the handleSubmit method does individually.

I believe the above would make your tests more clearer and readable too, because of the separation of concerns and would also allow you to test more edge cases.

关于reactjs - 使用 React-testing 库提交 Formik 表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54842033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com