How to write test case using Jest for Yup.isValid function?

Viewed 10238

I am trying to add a unit test to validate the Yup.isValid function, but the after running test case showing error as: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. Even if I am changing the minimum timeout of jasmine same error showing. My function to validate the Yup schema is:

export const validateSchema= (
  validationSchema,
  data
) => {
  return new Promise(async (resolve, reject) => {
    await validationSchema
      isValid(data)
      .then(isFormValid => {
        //passing response to method
      })
      .catch(error => reject(error));
  });
};

My test case is:

test("validate Schema",async () => {
    let catchFn = jest.fn();
    let data= someSampleData;
    //data is valid as per the schema
   await validationSchema(
        validationSchema,
        data
      )
      .then(res => {
       //My expected condition
      })
      .catch(catchFn);
  });

Above test case is not going to then where I can put my condition. Same error is coming as I mentioned. How can I fix this issue?

3 Answers

For large schemas it might be nice to use yup's validateAt api to pass in a path to validate for, so fixture data can be more concise.

Jest specs could look something like:

await expect(schema.validateAt(path, fixture)).rejects.toBeTruthy()
  it("requires person's name", async () => {
    await expect(schema.validateAt('person.name', {})).rejects.toBeFalsy()
    await expect(schema.validateAt('person.name', {person: {name: "something"}})).resolves.toBeTruthy()

  }

Unit testing yup is interesting, in that a lot of it is configuration, testing that libraries work the way they say they do can be extraneous. However, this does seem to helpful for testing more complex custom schema validation behaviors.

validateSchema uses promise construction antipattern and shows one of the reasons why it's considered an antipattern, new Promise is unneeded construction that is prone to human errors.

The use of async as Promise executor is a mistake that contributes to the antipattern. Promise executor ignores a promise that is returned from async function. resolve is never called, while .catch(error => reject(error)) is no-op. validateSchema returns either rejected or pending promise. If pending promise is returned from a test, this results in a timeout.

It should be:

export const validateSchema= async (
  validationSchema,
  data
) => {
    await validationSchema;
    const isFormValid = isValid(data);
    await updateFormValidFlag(isFormValid, theFormName); // does it return a promise?
  });
};

Mixing await and raw promises is rarely ever needed. Using dummy function in catch in test will result in supressing errors, which is rarely a desirable behaviour.

The test can be:

test("validate Schema",async () => {
   let data= someSampleData;
   await validateSchema(...);
   //My expected condition
});

Just another example, I am mainly check for true values

it( 'should handle validating object', async () => {
  const result = await schema.isValid(myObject)
  expect( result ).toEqual( true )
} )
Related