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:
- 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.
I also tried using
getByText
,findByText
as well. Also having this errorError: expect(received).not.toBeNull()
.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.