At the moment, the generateValidationErrorMessage function produces messages that are specific to the Create User operations. This means that although the code is separated, the logic is still highly coupled to the Create User endpoint. This coupling defeats the purpose of modules; it is a code smell that should be eliminated.
Instead, we should program the generateValidationErrorMessage function to be able to generate error messages for all validation errors. Doing so also provides local consistency, because all validators will now have a consistent structure/format for their error messages.
So, let's make the change by replacing our generateValidationErrorMessage function with the following:
function generateValidationErrorMessage(errors) {
const error = errors[0];
if (error.keyword === 'required') {
return `The '${error.dataPath}.${error.params.missingProperty}' field is missing`;
}
if (error.keyword === 'type') {
return `The '${error.dataPath}' field must be of type ${error.params.type}`;
}
if (error.keyword === 'format') {
return `The '${error.dataPath}' field must be a valid ${error.params.format}`;
}
if (error.keyword === 'additionalProperties') {
return `The '${error.dataPath}' object does not support the field '${error.params.additionalProperty}'`;
}
return 'The object is not valid';
}
Because this change will break our current implementation and tests, we must obtain approval from the product manager. If they approve, we must then update the E2E tests to reflect this change:
Scenario Outline: Bad Request Payload
...
And contains a message property which says "<message>"
Examples:
| missingFields | message |
| email | The '.email' field is missing |
| password | The '.password' field is missing |
Scenario Outline: Request Payload with Properties of Unsupported Type
...
And contains a message property which says "The '.<field>' field must be of type <type>"
...
Scenario Outline: Request Payload with invalid email format
...
And contains a message property which says "The '.email' field must be a valid email"
...
Scenario Outline: Invalid Profile
...
And contains a message property which says "<message>"
Examples:
| payload | message |
| ... | The '.profile' object does not support the field 'foo' |
| ... | The '.profile.name' object does not support the field 'a' |
| ... | The '.profile.summary' field must be of type string |
| ... | The '.profile.bio' field must be of type string |
Next, import the generateValidationErrorMessage function into our src/validators/users/create.js file and update the validateRequest function so that we can use it to return an object containing an error message if validation fails:
import generateValidationErrorMessage from '../errors/messages';
function validate(req) {
...
const valid = ajvValidate(req.body);
if (!valid) {
return new ValidationError(generateValidationErrorMessage(ajvValidate.errors));
}
return true;
}