1
votes

I am trying to write a custom test for the yup validation library for use in a node/express app that tests whether two fields are the same - use case e.g. testing whether password and confirm password fields match. The logic is working, however the message provided from the method is not.

Custom validator code modified from: https://github.com/jquense/yup/issues/97#issuecomment-306547261

Custom validator

yup.addMethod(yup.string, 'isMatch', function (ref, msg) {
  return this.test({
    name: 'isMatch',
    message: msg || `${this.path} must be equal to ${this.reference}`,
    params: {
      reference: ref.path
    },
    test: function (value) {
      return value === this.resolve(ref);
    }
  });
});

Example use

const schema = yup.object().shape({
  password: yup.string().min(8),
  passwordConfirm: yup.string().isMatch(yup.ref('password'))
})

const payload = {
  password: 'correctPassword',
  passwordConfirm: 'incorrectPassword'
}

schema.validate(payload)

The above method works as expected from a logic perspective. However, in the error message returned, the value of this.path and this.reference are both undefined (i.e. undefined must be equal to undefined). It should read passwordConfirm must be equal to password.

I had to add this. in front of path and reference, otherwise node crashes with a ReferenceError that path/reference is not defined.

1

1 Answers

2
votes

You do not need to write a custom validation function to check if two fields match, you can use the built in validator.oneOf

Whitelist a set of values. Values added are automatically removed from any blacklist if they are in it. The ${values} interpolation can be used in the message argument.

Note that undefined does not fail this validator, even when undefined is not included in arrayOfValues. If you don't want undefined to be a valid value, you can use mixed.required.

See here ref: oneOf(arrayOfValues: Array, message?: string | function): Schema Alias: equals

So you could re-write your schema as follows (I've added required also to the password fields):

const schema = yup.object().shape({
  password: yup.string().min(8).required('Required!'),
  passwordConfirm: yup.string().oneOf([Yup.ref('password')], 'Password must be the same!').required('Required!')
})