0
votes

I'm new to using Joi validations and I need your help. I'm trying to achieve the following:

  1. Get error message for all empty fields in Postman which are required in Joi

  2. Requesting a user to enter all or one of the valid values when they hit PATCH request.

I have tried this:

  1. Returning an error message when one field is empty by when all fields are empty in postman (when I send no request) I still get an error for the first field yet I want a list of error messages for all empty fields.

Joi User signup validation

import Joi from "joi";

export const validateSignup = user => {
  const schema = Joi.object().keys({
    first_name: Joi.string()
      .min(3)
      .max(20)
      .required()
      .error(() => "first_name must be a string"),
    last_name: Joi.string()
      .min(3)
      .max(20)
      .required()
      .error(() => "last_name must be a string"),
    email: Joi.string()
      .email({ minDomainAtoms: 2 })
      .trim()
      .required()
      .error(() => "email must be a valid email"),
    password: Joi.string()
      .regex(
        /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
      )
      .required()
      .error(
        () =>
          "password must be at least 8 characters long containing 1 capital letter, 1 small letter, 1 digit and 1 of these special characters(@, $, !, %, *, ?, &)"
      )
  });

  const options = { abortEarly: false };
  return Joi.validate(user, schema, options);
};

Sign up controllers

import { validateSignup } from "../helpers/userValidator";

class User {
  static async SignUp(req, res) {
    const { error } = validateSignup(req.body);
    if (error) {
      return res
        .status(400)
         .json(new ResponseHandler(400, (error.details || []).map(er => er.message), null).result());
    }
  }
}

ResponseHandler Class

class ResponseHandler{
    constructor(status, message, data, error){
        this.status = status; 
        this.message = message; 
        this.data = data, 
        this.error = error;
    } 

    result(){
        const finalRes = {};
        finalRes.status = this.status;
        finalRes.message = this.message; 
        if(this.data  !== null){
            finalRes.data = this.data;
        }else if(this.error !== null){
            finalRes.error = this.error;
        }
        return finalRes;
    }
}


export default ResponseHandler; 

Postman response

Postman's response body

I would appreciate your help. Thanks

1

1 Answers

2
votes

You are just using sending the 0th element that's why you are getting only one error.

Instead of error.details[0].message use

(error.details || []).map(e=>e.message)

Explanation:
Joi has all the errors stored in error.details array. You just have to format it your way using the values you like.

For example for this object:

{
  first_name: null,
  last_name: null,
  email: null,
  password: null
}

Errors are:

[ { message: 'first_name must be a string',
    path: [ 'first_name' ],
    type: 'string.base',
    context: { value: null, key: 'first_name', label: 'first_name' } },
  { message: 'last_name must be a string',
    path: [ 'last_name' ],
    type: 'string.base',
    context: { value: null, key: 'last_name', label: 'last_name' } },
  { message: 'email must be a valid email',
    path: [ 'email' ],
    type: 'string.base',
    context: { value: null, key: 'email', label: 'email' } },
  { message:
     'password must be at least 8 characters long containing 1 capital letter, 1 small letter, 1 digit and 1 of these special characters(@, $, !, %, *, ?, &)',
    path: [ 'password' ],
    type: 'string.base',
    context: { value: null, key: 'password', label: 'password' } } ]