Skip to content

Commit dbab07a

Browse files
authored
feat: add showConstraintMessages option to ValidationError.toString() (#1612)
1 parent f6f1bdf commit dbab07a

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

src/validation/ValidationError.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,20 @@ export class ValidationError {
4545
* @param shouldDecorate decorate the message with ANSI formatter escape codes for better readability
4646
* @param hasParent true when the error is a child of an another one
4747
* @param parentPath path as string to the parent of this property
48+
* @param showConstraintMessages show constraint messages instead of constraint names
4849
*/
49-
toString(shouldDecorate: boolean = false, hasParent: boolean = false, parentPath: string = ``): string {
50+
toString(
51+
shouldDecorate: boolean = false,
52+
hasParent: boolean = false,
53+
parentPath: string = ``,
54+
showConstraintMessages: boolean = false
55+
): string {
5056
const boldStart = shouldDecorate ? `\x1b[1m` : ``;
5157
const boldEnd = shouldDecorate ? `\x1b[22m` : ``;
58+
const constraintsToString = () =>
59+
(showConstraintMessages ? Object.values : Object.keys)(this.constraints ?? {}).join(`, `);
5260
const propConstraintFailed = (propertyName: string): string =>
53-
` - property ${boldStart}${parentPath}${propertyName}${boldEnd} has failed the following constraints: ${boldStart}${Object.keys(
54-
this.constraints
55-
).join(`, `)}${boldEnd} \n`;
61+
` - property ${boldStart}${parentPath}${propertyName}${boldEnd} has failed the following constraints: ${boldStart}${constraintsToString()}${boldEnd} \n`;
5662

5763
if (!hasParent) {
5864
return (
@@ -61,7 +67,9 @@ export class ValidationError {
6167
}${boldEnd} has failed the validation:\n` +
6268
(this.constraints ? propConstraintFailed(this.property) : ``) +
6369
(this.children
64-
? this.children.map(childError => childError.toString(shouldDecorate, true, this.property)).join(``)
70+
? this.children
71+
.map(childError => childError.toString(shouldDecorate, true, this.property, showConstraintMessages))
72+
.join(``)
6573
: ``)
6674
);
6775
} else {
@@ -75,7 +83,9 @@ export class ValidationError {
7583
} else {
7684
return this.children
7785
? this.children
78-
.map(childError => childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`))
86+
.map(childError =>
87+
childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`, showConstraintMessages)
88+
)
7989
.join(``)
8090
: ``;
8191
}

src/validation/ValidationExecutor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ export class ValidationExecutor {
4545
*/
4646
if (!this.metadataStorage.hasValidationMetaData && this.validatorOptions?.enableDebugMessages === true) {
4747
console.warn(
48-
`No validation metadata found. No validation will be performed. There are multiple possible reasons:\n` +
49-
` - There may be multiple class-validator versions installed. You will need to flatten your dependencies to fix the issue.\n` +
50-
` - This validation runs before any file with validation decorator was parsed by NodeJS.`
48+
`No validation metadata found. No validation will be performed. There are multiple possible reasons:\n` +
49+
` - There may be multiple class-validator versions installed. You will need to flatten your dependencies to fix the issue.\n` +
50+
` - This validation runs before any file with validation decorator was parsed by NodeJS.`
5151
);
5252
}
5353

test/functional/validation-error.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe('ValidationError', () => {
4949
}
5050

5151
const validationErrors = await validator.validate(new RootClass());
52+
expect(validationErrors).toHaveLength(3);
5253
expect(validationErrors[0].toString()).toEqual(
5354
'An instance of RootClass has failed the validation:\n' +
5455
' - property title has failed the following constraints: minLength, isString \n'
@@ -67,5 +68,23 @@ describe('ValidationError', () => {
6768
' - property nestedArr[1].name has failed the following constraints: isString \n' +
6869
' - property nestedArr[1].url has failed the following constraints: isUrl \n'
6970
);
71+
expect(validationErrors[0].toString(undefined, undefined, undefined, true)).toEqual(
72+
'An instance of RootClass has failed the validation:\n' +
73+
' - property title has failed the following constraints: title must be longer than or equal to 15 characters, title must be a string \n'
74+
);
75+
expect(validationErrors[1].toString(undefined, undefined, undefined, true)).toEqual(
76+
'An instance of RootClass has failed the validation:\n' +
77+
' - property nestedObj.name has failed the following constraints: name must be a string \n' +
78+
' - property nestedObj.url has failed the following constraints: url must be a URL address \n' +
79+
' - property nestedObj.insideNested.name has failed the following constraints: name must be a string \n' +
80+
' - property nestedObj.insideNested.url has failed the following constraints: url must be a URL address \n'
81+
);
82+
expect(validationErrors[2].toString(undefined, undefined, undefined, true)).toEqual(
83+
'An instance of RootClass has failed the validation:\n' +
84+
' - property nestedArr[0].name has failed the following constraints: name must be a string \n' +
85+
' - property nestedArr[0].url has failed the following constraints: url must be a URL address \n' +
86+
' - property nestedArr[1].name has failed the following constraints: name must be a string \n' +
87+
' - property nestedArr[1].url has failed the following constraints: url must be a URL address \n'
88+
);
7089
});
7190
});

0 commit comments

Comments
 (0)