Skip to content
Merged
2 changes: 1 addition & 1 deletion src/validation/ValidationExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class ValidationExecutor {
);
const groupedMetadatas = this.metadataStorage.groupByPropertyName(targetMetadatas);

if (this.validatorOptions && forbidUnknownValues && !targetMetadatas.length) {
if (forbidUnknownValues && !targetMetadatas.length) {
const validationError = new ValidationError();

if (
Expand Down
5 changes: 3 additions & 2 deletions src/validation/ValidatorOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ export interface ValidatorOptions {
};

/**
* Fails validation for objects unknown to class-validator. Defaults to false.
* Fails validation for objects unknown to class-validator. Defaults to true.
*
* For instance, since a plain empty object has no annotations used for validation:
* - `validate({})` // passes
* - `validate({})` // fails.
* - `validate({}, { forbidUnknownValues: true })` // fails.
* - `validate({}, { forbidUnknownValues: false })` // passes.
* - `validate(new SomeAnnotatedEmptyClass(), { forbidUnknownValues: true })` // passes.
*/
forbidUnknownValues?: boolean;
Expand Down
47 changes: 35 additions & 12 deletions test/functional/validator-options.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,20 @@ describe('validator options', () => {
class MyClass {
@IsNotEmpty()
title: string = '';
isActive: boolean;
}

const model = new MyClass();
model.title = '';
return validator
.validate(model, { skipMissingProperties: true, validationError: { target: false } })
.then(errors => {
expect(errors.length).toEqual(1);
expect(errors[0].target).toBeUndefined();
expect(errors[0].property).toEqual('title');
expect(errors[0].constraints).toEqual({ isNotEmpty: 'title should not be empty' });
expect(errors[0].value).toEqual('');
});
return validator.validate(model, { validationError: { target: false } }).then(errors => {
expect(errors.length).toEqual(1);
expect(errors[0].target).toBeUndefined();
expect(errors[0].property).toEqual('title');
expect(errors[0].constraints).toEqual({ isNotEmpty: 'title should not be empty' });
expect(errors[0].value).toEqual('');
});
});

it('should returns error on unknown objects if forbidUnknownValues is true', function () {
it('should return error on unknown objects if forbidUnknownValues is true', () => {
const anonymousObject = { badKey: 'This should not pass.' };

return validator.validate(anonymousObject, { forbidUnknownValues: true }).then(errors => {
Expand All @@ -37,11 +34,37 @@ describe('validator options', () => {
});
});

it('should return no error on unknown objects if forbidUnknownValues is false', function () {
it('should return no error on unknown objects if forbidUnknownValues is false', () => {
const anonymousObject = { badKey: 'This should not pass.' };

return validator.validate(anonymousObject, { forbidUnknownValues: false }).then(errors => {
expect(errors.length).toEqual(0);
});
});

it(`should return error on unknown objects if no options object argument is passed`, () => {
const anonymousObject = { badKey: 'This should not pass.' };

return validator.validate(anonymousObject, undefined).then(errors => {
expect(errors.length).toEqual(1);
expect(errors[0].target).toEqual(anonymousObject);
expect(errors[0].property).toEqual(undefined);
expect(errors[0].value).toEqual(undefined);
expect(errors[0].children).toBeInstanceOf(Array);
expect(errors[0].constraints).toEqual({ unknownValue: 'an unknown value was passed to the validate function' });
});
});

it(`should return error on unknown objects if options object argument passed with forbidUnknownValues undefined`, () => {
const anonymousObject = { badKey: 'This should not pass.' };

return validator.validate(anonymousObject, { forbidUnknownValues: undefined }).then(errors => {
expect(errors.length).toEqual(1);
expect(errors[0].target).toEqual(anonymousObject);
expect(errors[0].property).toEqual(undefined);
expect(errors[0].value).toEqual(undefined);
expect(errors[0].children).toBeInstanceOf(Array);
expect(errors[0].constraints).toEqual({ unknownValue: 'an unknown value was passed to the validate function' });
});
});
});