使用笑话和酶进行测试时,Formik 不会更新错误

发布于 2025-01-17 09:58:26 字数 3642 浏览 3 评论 0原文

我有一个 Formik 注册表单,已通过 yup 验证。当验证架构未满足时,我想显示错误组件。一切都在浏览器中运行,但是当我进行测试时,即使应该已经存在错误,并且酶的行为就像没有错误一样。有人可以告诉我我做错了什么吗?这很奇怪,因为当我将 console.log(errors.email) 放入 Formik 的返回函数中时,我看到“它似乎不是有效的电子邮件地址”。我的测试控制台中出现错误。另一方面,当我将 erros.email 放入 Formik 的返回函数中时,在测试中它看起来不存在。

// SignUp.tsx
const SignUp: React.FC = () => {
  const { register, errorMessage } = React.useContext(AuthContext);

  const initialValues = {
    email: '',
    password: '',
    passwordRepeat: '',
  };

  const hasErrors = (errors: FormikErrors<typeof initialValues>) => {
    return Object.keys(errors).length !== 0 || errorMessage;
  };

  const allFieldsWereTouched = (touched: FormikTouched<typeof initialValues>) => {
    return Array.from(Object.values(touched)).filter((wasTouched) => wasTouched).length === Object.keys(initialValues).length;
  };

  const signUpValidationSchema = Yup.object().shape({
    email: Yup.string().email('It does not seem to be a valid email address.'),
    password: Yup.string().min(5, 'Password must have at least 5 characters.').max(15, 'Password must not have more than 15 characters.'),
    passwordRepeat: Yup.string().oneOf([Yup.ref('password')], 'Both passwords must be equal.'),
  });

  const submitForm = (values: typeof initialValues) => {
    register(values.email, values.password);
  };

  return (
    <AuthWrapper>
      <h3 className={classes.authModalTitle} data-test='signup-modal-title'>
        Sign Up
      </h3>
      <Formik initialValues={initialValues} onSubmit={submitForm} validationSchema={signUpValidationSchema}>
        {({ errors, touched }) => {
          return (
            <Form>
              <FormikTextInput type='email' name='email' description='E-mail address' as={Input} />
              <FormikTextInput type='password' name='password' description='Password' as={Input} />
              <FormikTextInput type='password' name='passwordRepeat' description='Password repeat' as={Input} />
              {errors.email && <Error message={errors.email || errors.password || errors.passwordRepeat || errorMessage} />}
              <Button className={classes.buttonAdditional} type='submit' dataTest='signup-button'>
                Open account
              </Button>
            </Form>
          );
        }}
      </Formik>
      <FormInfo question='Already have an account?' answer='Sign in' path='SignIn' />
    </AuthWrapper>
  );
};

export default SignUp;

// SignUp.test.tsx

const setup = () => {
  return mount(
    <MemoryRouter>
      <AuthContextProvider>
        <SignUp />
      </AuthContextProvider>
    </MemoryRouter>
  );
};

describe('<SignUp />', () => {
  let wrapper: ReactWrapper;

  beforeEach(() => {
    wrapper = setup();
  });

  afterEach(() => {
    wrapper.unmount();
  });

  describe('showing errors', () => {
    const simulateTyping = async (name: string, value: string | number) => {
      const formField = formikFindByInputName(wrapper, name);
      formField.simulate('change', { target: { name, value } });
      formField.simulate('blur');
    };

    const checkErrorExistance = (wrapper: ReactWrapper, condition: boolean) => {
      const error = findByTestAttr(wrapper, 'error');
      expect(error.exists()).toBe(condition);
    };

    it('does not show error when email input value is wrong but not all inputs were touched', () => {
      simulateTyping('email', 'test');
      checkErrorExistance(wrapper, true);
    });
    
    
  });
});

I have a Formik signup form that is validated with yup. When validation schema isn't fulfilled i want to show error component. Everything works in browser, but when i do my tests, even though there should be errors already jest and enzyme behaves like there was no error. Can someone tell me what am I doing wrong? It's strange because when I put console.log(errors.email) in Formik's return function i see that there is 'It does not seem to be a valid email address.' error in my test console. From the other hand when i put erros.email in Formik's return function, in test it looks like it doesn't exist.

// SignUp.tsx
const SignUp: React.FC = () => {
  const { register, errorMessage } = React.useContext(AuthContext);

  const initialValues = {
    email: '',
    password: '',
    passwordRepeat: '',
  };

  const hasErrors = (errors: FormikErrors<typeof initialValues>) => {
    return Object.keys(errors).length !== 0 || errorMessage;
  };

  const allFieldsWereTouched = (touched: FormikTouched<typeof initialValues>) => {
    return Array.from(Object.values(touched)).filter((wasTouched) => wasTouched).length === Object.keys(initialValues).length;
  };

  const signUpValidationSchema = Yup.object().shape({
    email: Yup.string().email('It does not seem to be a valid email address.'),
    password: Yup.string().min(5, 'Password must have at least 5 characters.').max(15, 'Password must not have more than 15 characters.'),
    passwordRepeat: Yup.string().oneOf([Yup.ref('password')], 'Both passwords must be equal.'),
  });

  const submitForm = (values: typeof initialValues) => {
    register(values.email, values.password);
  };

  return (
    <AuthWrapper>
      <h3 className={classes.authModalTitle} data-test='signup-modal-title'>
        Sign Up
      </h3>
      <Formik initialValues={initialValues} onSubmit={submitForm} validationSchema={signUpValidationSchema}>
        {({ errors, touched }) => {
          return (
            <Form>
              <FormikTextInput type='email' name='email' description='E-mail address' as={Input} />
              <FormikTextInput type='password' name='password' description='Password' as={Input} />
              <FormikTextInput type='password' name='passwordRepeat' description='Password repeat' as={Input} />
              {errors.email && <Error message={errors.email || errors.password || errors.passwordRepeat || errorMessage} />}
              <Button className={classes.buttonAdditional} type='submit' dataTest='signup-button'>
                Open account
              </Button>
            </Form>
          );
        }}
      </Formik>
      <FormInfo question='Already have an account?' answer='Sign in' path='SignIn' />
    </AuthWrapper>
  );
};

export default SignUp;

// SignUp.test.tsx

const setup = () => {
  return mount(
    <MemoryRouter>
      <AuthContextProvider>
        <SignUp />
      </AuthContextProvider>
    </MemoryRouter>
  );
};

describe('<SignUp />', () => {
  let wrapper: ReactWrapper;

  beforeEach(() => {
    wrapper = setup();
  });

  afterEach(() => {
    wrapper.unmount();
  });

  describe('showing errors', () => {
    const simulateTyping = async (name: string, value: string | number) => {
      const formField = formikFindByInputName(wrapper, name);
      formField.simulate('change', { target: { name, value } });
      formField.simulate('blur');
    };

    const checkErrorExistance = (wrapper: ReactWrapper, condition: boolean) => {
      const error = findByTestAttr(wrapper, 'error');
      expect(error.exists()).toBe(condition);
    };

    it('does not show error when email input value is wrong but not all inputs were touched', () => {
      simulateTyping('email', 'test');
      checkErrorExistance(wrapper, true);
    });
    
    
  });
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜唯美灬不弃 2025-01-24 09:58:26

我遇到了同样的问题,必须自己运行 validateForm,所以类似:

<Formik>{({..., validateForm}) => 
  <Button onClick={async () => {const newErrors = await validateForm?.()}} />

然后检查 newErrors

I had the same issue and had to run validateForm myself, so something like:

<Formik>{({..., validateForm}) => 
  <Button onClick={async () => {const newErrors = await validateForm?.()}} />

Then check the newErrors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文