0

I am using a formik form to sign up and testing it with react testing library. The submit button is disabled if the email or password fields are invalid. I am testing if my btn is enabled or disabled when i type certain input. I am performing 2 tests the first one with invalid inputs and the second with valid inputs but the first one is always passing even if it shouldn't. The 2nd test is behaving as it should

const MockedSignUpFormView=()=>{
    return(
        <BrowserRouter>
            <SignUpFormView/>
        </BrowserRouter>
    )
}


it('btn is disabled if sign up with wrong credentials ',async () => {
        render(<MockedSignUpFormView />);
        const emailInput = screen.getByRole('textbox', {  name: /email address/i});
        const passInput = screen.getByPlaceholderText(/password/i);
        const confirmPassInput = screen.getByLabelText(/confirm password/i);
        const signUpBtn = screen.getByRole('button', {  name: /sign up/i})
      
        userEvent.type(emailInput,'mnbmbm@gmail.com')
    
        userEvent.type(passInput,'sadasdas')
     
        userEvent.type(confirmPassInput,'czxcxzcxz')
        
        await waitFor(async ()=>{ 
            expect(signUpBtn).not.toHaveAttribute('disabled')})
        
        screen.debug()
    });

    it('btn is enabled if sign up with right credentials ',async () => {
        render(<MockedSignUpFormView />);
        const emailInput = screen.getByRole('textbox', {  name: /email address/i});
        const passInput = screen.getByPlaceholderText(/password/i);
        const confirmPassInput = screen.getByLabelText(/confirm password/i);
        const signUpBtn = screen.getByRole('button', {  name: /sign up/i})
      
        userEvent.type(emailInput,'mnbmbm@gmail.com')
    
        userEvent.type(passInput,'czxcxzcxz')
     
        userEvent.type(confirmPassInput,'czxcxzcxz')
        
        await waitFor(async ()=>{ 
            expect(signUpBtn).toBeEnabled()})
        
        screen.debug()
    });

I am using screen.debug and i am getting disabled on the first btn but still test keeps passing for this expect(signUpBtn).not.toHaveAttribute('disabled')}) and this expect(signUpBtn).not.toBeDisabled()

Sreen.debug() for first btn <button class="login__btn" disabled="" type="submit"> Sreen.debug() for 2nd btn <button class="login__btn" type="submit">

SignUpFormView component

const SignUpFormView=(props:any)=>{
    const [error,setError]=useState(false);
    const navigate=useNavigate ();
 
    return(
        <React.Fragment>
            <Formik
            initialValues={{
                email: "",
                password:"",
                confirmPassword:""
            }}
            validationSchema={Yup.object({   
            password: Yup.string()
                .min(6, "Must be 6 characters or more")
                .required("Required"),
            confirmPassword: Yup.string()
                .min(6, "Must be 6 characters or more")
                .required("Required")
                .oneOf([Yup.ref('password'), null], 'Passwords must match'),
            email: Yup.string()
                .email("Invalid email address`")
                .required("Required"),
            })}
            onSubmit={(values, { setSubmitting }) => {
                    props.onSubmitHandler(values.email,values.password).then((userCredential:any) => {
                        setSubmitting(false);
                    
                        navigate('/home');
                      
                    }).catch((err:any)=>{
                        setError(err.message);
                    })
                }}>
                {formik => {
                    return (
                        <nav className={classes["nav"]}>
                            <h2 className={classes['nav__detail']}>Sign Up</h2>
                            <Form className={classes['form__login']}>
                                <Input 
                                    label="Email Address"
                                    name="email"
                                    type="email"
                                
                                />
                                <Input
                                    label="Password"
                                    name="password"
                                    type="password"
                                    placeholder='Password' 
                                  
                                />
                                <Input
                                    label="Confirm Password"
                                    name="confirmPassword"
                                    type="password"  
                                    
                                />
                                {(formik.isSubmitting || error) /*&& renderResponseItem(formik.isSubmitting,error)*/}
                                {!formik.isSubmitting && <button type="submit" disabled={!formik.isValid || formik.isSubmitting ? true :false} className={classes['login__btn']}>Sign Up</button>}
                            </Form>
                            <Link to='/'>Have an account? Login</Link>
                        </nav>
                    )
                }
            }
        </Formik>
    </React.Fragment>
    )
}

Input component

import  React  from 'react';
import { useField } from "formik";
import classes from './InputView.module.css';

interface Props{
  name:string,
  id?:string,
  placeholder?:string,
  label:string,
  type:string
}

const Input:React.FC<Props>=(props)=>{
    const [field, meta] = useField(props);

    const inputClasses=meta.touched && meta.error ? `${classes.input} ${classes.error}`:`${classes.input}`;
    return (
      <React.Fragment>
        <label className={classes.label} htmlFor={props.id || props.name}>{props.label}</label>
        <input className={inputClasses} {...field} {...props}  id={props.name} placeholder={props?.placeholder}/>
      </React.Fragment>
    );
}
H.b
  • 239
  • 2
  • 13
  • If I understood your description correctly, the first test has invalid data and the button should be disabled, right? If that is right why are you expecting it to be enabled? – Dzianis Roi May 25 '22 at 12:02
  • 1
    Can you add the code of `MockedSignUpFormView` component? – Luis Paulo Pinto May 25 '22 at 12:05
  • Just as @DenisRoy says, remove the `not.`, or change the whole assertion to `expect(signUpBtn).toBeDisabled()`, both ways should work – Benji May 25 '22 at 12:06
  • @DenisRoy no the test passes if i remove the .not() or add it. It just keeps passing even if it shouldn't – H.b May 25 '22 at 12:35
  • @Benji no the test passes if i remove the .not() or add it. It just keeps passing even if it shouldn't – H.b May 25 '22 at 12:36
  • 1
    Yes, tks. Just saw it and it wont help. What you need to add is the `form`code with the validation, in this case i believe its the `SignUpFormView`, – Luis Paulo Pinto May 25 '22 at 12:58
  • @LuisPauloPinto added SignUpFormView – H.b May 25 '22 at 13:35
  • 1
    The problem now its related to `Input` componnet - Its a custom component or you are using some 3rd library? Can you also show the code if its a custom component? – Luis Paulo Pinto May 25 '22 at 15:00
  • @LuisPauloPinto added. sorry for the trouble – H.b May 25 '22 at 15:07
  • 1
    I've created an code sample and everything worked as expected (Throw an error on first test). Strange, maybe I'm missing something... Take a look [here](https://codesandbox.io/s/stack-disabled-button-test-itev93?file=/src/SignUpFormView.spec.js) - it might help you. – Luis Paulo Pinto May 25 '22 at 15:31
  • @LuisPauloPinto So there isn't any problem in the logic right? Thanks a lot. – H.b May 25 '22 at 16:31
  • 1
    Right, no problem at all. Cheers! – Luis Paulo Pinto May 25 '22 at 17:09
  • @H.b did you find the problem? I also cannot make assertions around Formik to get working... – Tomek Oct 27 '22 at 19:50
  • @Tomek I don't think I got this solved. Sorry – H.b Oct 27 '22 at 20:37

0 Answers0