title: How to unit test Yup .test() method using React Native Testing Library?
body: <p>I have a Formik from which is like this:</p>
  <pre><code>&lt;Formik
     initialValues={initialValue}
     validationSchema={schema} // Here I set to the schema below. 
     onSubmit={handleBasicSubmit}
  &gt;
  
  &lt;FormControl isRequired isInvalid={&quot;username&quot; in errors}&gt; // here if the error from schema it will shown 
       &lt;FormControl.Label&gt;Username&lt;/FormControl.Label&gt;
         &lt;Input
           p={2}
           onChangeText={handleChange(&quot;username&quot;)}
           placeholder=&quot;Preferred username&quot;
           value={values.username}
        /&gt;
        &lt;FormControl.ErrorMessage&gt;
           {errors.username}
         &lt;/FormControl.ErrorMessage&gt;
      &lt;/FormControl&gt;
  
  &lt;/Formik&gt;
  </code></pre>
  <p>When enter username into the field, then the schema will check with server see whether the <code>username</code> is already taken by calling <code>checkUserHandleExist</code> function inside the <code>.test()</code> function.</p>
  <p>Yup Schema:</p>
  <pre><code>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) =&gt;  {
               if(value){
                try {
                 const res = await checkUserHandleExist(value);
  
                 const data = res.data;
  
                 if (data.error) {
                   // @ts-expect-error
                   return this.createError(&quot;Have problem verify username&quot;);
                 } else {
                   if (data.is_user_handle_exists) {
                     // @ts-expect-error
                     return this.createError(&quot;Already used&quot;); // the phase should be on screen 
                   }
                   else {
                     return true;
                   }
                 }
               } catch (error) { }
              }
          }
          )
  
  })
  </code></pre>
  <p>In order to test it with React-Native-testing-library, here is my test:</p>
  <pre><code>it('Username enter is existed after check from server, display error', async () =&gt; {
        // here mock the API method for checkUsernameExisted 
        rest.get(API_URL + &quot;/invite&quot;, (req, res, ctx) =&gt; {
          return res(
            ctx.status(200),
            ctx.json({
              is_user_handle_exists: true  // Here mock the result is true 
            })
          )
        })
        
        const { getByText, getByPlaceholderText, queryByText } = render( 
              &lt;UserBasicDetails /&gt;
        );
      
        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()  
       
      })
  
  </code></pre>
  <p>As you can see here, I mocked the API method to return <code>true</code> as result(in Yup test function) .</p>
  <p>Then the <code>errorMsg</code> should be existed according my code.</p>
  <p><strong>Problem now</strong></p>
  <p>When I <code>queryByText</code> for the <code>Already used</code> phrase, it always get this message <code>Error: expect(received).not.toBeNull()</code>.</p>
  <p><strong>What I have tried:</strong></p>
  <ol>
  <li>I thought I should be <code>wait</code> for the error message to show, so I tried this:</li>
  </ol>
  <pre><code>await waitFor(() =&gt; {
          const errorMsg = queryByText(/Already used/i) // here Already used should be existed 
          expect(errorMsg).not.toBeNull()  
        })
  
  </code></pre>
  <p>Having the same error.</p>
  <ol start="2">
  <li><p>I also tried using <code>getByText</code>, <code>findByText</code> as well. Also having this error  <code>Error: expect(received).not.toBeNull()</code>.</p>
  </li>
  <li><p>I even try without <code>waitFor</code>:</p>
  </li>
  </ol>
  <pre><code>const errorMsg = await findByText(/Already used/i) // here Already used should be existed 
  expect(errorMsg).not.toBeNull()
  </code></pre>
  <p>I not sure why is this happened. Since I already <code>waitFor</code> it should wait until the <code>errorMsg</code> appear. But it didnt. All my other test case for <code>max</code>, <code>min</code> and <code>matches</code> inside the Yup schema is passed, just <code>test</code> is not passed. Dont know why.</p>
  <p>Please give some help. Thanks in advance.</p>