1

I have a Formik from which is like this:

<Formik
   initialValues={initialValue}
   validationSchema={schema} // Here I set to the schema below. 
   onSubmit={handleBasicSubmit}
>

<FormControl isRequired isInvalid={"username" in errors}> // here if the error from schema it will shown 
     <FormControl.Label>Username</FormControl.Label>
       <Input
         p={2}
         onChangeText={handleChange("username")}
         placeholder="Preferred username"
         value={values.username}
      />
      <FormControl.ErrorMessage>
         {errors.username}
       </FormControl.ErrorMessage>
    </FormControl>

</Formik>

When enter username into the field, then the schema will check with server see whether the username is already taken by calling checkUserHandleExist function inside the .test() function.

Yup Schema:

const schema = yup.object().shape({
   username: Yup.string()
        .required('Required')
        .min(3, 'Too short')
        .max(15, 'Long')
        .matches(/^[A-Za-z0-9_-]*$/, 'No symbol')
        .test(
          'unique-username', 
          'Already used', 
           async (value: string | undefined) =>  {
             if(value){
              try {
               const res = await checkUserHandleExist(value);

               const data = res.data;

               if (data.error) {
                 // @ts-expect-error
                 return this.createError("Have problem verify username");
               } else {
                 if (data.is_user_handle_exists) {
                   // @ts-expect-error
                   return this.createError("Already used"); // the phase should be on screen 
                 }
                 else {
                   return true;
                 }
               }
             } catch (error) { }
            }
        }
        )

})

In order to test it with React-Native-testing-library, here is my test:

it('Username enter is existed after check from server, display error', async () => {
      // here mock the API method for checkUsernameExisted 
      rest.get(API_URL + "/invite", (req, res, ctx) => {
        return res(
          ctx.status(200),
          ctx.json({
            is_user_handle_exists: true  // Here mock the result is true 
          })
        )
      })
      
      const { getByText, getByPlaceholderText, queryByText } = render( 
            <UserBasicDetails />
      );
    
      const usernameField = getByPlaceholderText('Preferred username, macam Twitter or Ig')

      fireEvent.changeText(usernameField, 'kenchoong')
      const button = getByText('Continue')
      
      
      const errorMsg = queryByText(/Already used/i) // here Already used should be existed 
      expect(errorMsg).not.toBeNull()  
     
    })

As you can see here, I mocked the API method to return true as result(in Yup test function) .

Then the errorMsg should be existed according my code.

Problem now

When I queryByText for the Already used phrase, it always get this message Error: expect(received).not.toBeNull().

What I have tried:

  1. I thought I should be wait for the error message to show, so I tried this:
await waitFor(() => {
        const errorMsg = queryByText(/Already used/i) // here Already used should be existed 
        expect(errorMsg).not.toBeNull()  
      })

Having the same error.

  1. I also tried using getByText, findByText as well. Also having this error Error: expect(received).not.toBeNull().

  2. I even try without waitFor:

const errorMsg = await findByText(/Already used/i) // here Already used should be existed 
expect(errorMsg).not.toBeNull()

I not sure why is this happened. Since I already waitFor it should wait until the errorMsg appear. But it didnt. All my other test case for max, min and matches inside the Yup schema is passed, just test is not passed. Dont know why.

Please give some help. Thanks in advance.

ken
  • 2,426
  • 5
  • 43
  • 98

0 Answers0