diff --git a/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-after-or-equal.decorator.ts b/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-after-or-equal.decorator.ts index 484e98d..fb6e734 100644 --- a/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-after-or-equal.decorator.ts +++ b/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-after-or-equal.decorator.ts @@ -2,6 +2,7 @@ import { registerDecorator, ValidationOptions, ValidationArguments, + isISO8601, } from 'class-validator'; export function IsAfterOrEqual( @@ -19,11 +20,22 @@ export function IsAfterOrEqual( validate(value: any, args: ValidationArguments) { const [relatedPropertyName] = args.constraints; const relatedValue = (args.object as any)[relatedPropertyName]; - return ( - typeof value === 'string' && - typeof relatedValue === 'string' && - value >= relatedValue - ); // you can return a Promise here as well, if you want to make async validation + if ( + !( + typeof value === 'string' && + typeof relatedValue === 'string' && + isISO8601(value, { + strict: true, + strictSeparator: true, + }) && + isISO8601(relatedValue, { + strict: true, + strictSeparator: true, + }) + ) + ) + return false; + return new Date(value) >= new Date(relatedValue); }, }, }); diff --git a/src/modules/ad/tests/unit/interface/has-day.decorator.spec.ts b/src/modules/ad/tests/unit/interface/has-day.decorator.spec.ts new file mode 100644 index 0000000..ef27a62 --- /dev/null +++ b/src/modules/ad/tests/unit/interface/has-day.decorator.spec.ts @@ -0,0 +1,60 @@ +import { Frequency } from '@modules/ad/core/domain/ad.types'; +import { ScheduleItemDto } from '@modules/ad/interface/grpc-controllers/dtos/schedule-item.dto'; +import { HasDay } from '@modules/ad/interface/grpc-controllers/dtos/validators/decorators/has-day.decorator'; +import { Validator } from 'class-validator'; + +describe('Has day decorator', () => { + class MyClass { + @HasDay('schedule', { + message: 'At least a day is required for a recurrent ad', + }) + frequency: Frequency; + + schedule: ScheduleItemDto[]; + } + + it('should return a property decorator has a function', () => { + const hasDay = HasDay('someProperty'); + expect(typeof hasDay).toBe('function'); + }); + + it('should validate a punctual frequency associated with a valid schedule', async () => { + const myClassInstance = new MyClass(); + myClassInstance.frequency = Frequency.PUNCTUAL; + myClassInstance.schedule = [ + { + time: '07:15', + }, + ]; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(0); + }); + + it('should validate a recurrent frequency associated with a valid schedule', async () => { + const myClassInstance = new MyClass(); + myClassInstance.frequency = Frequency.RECURRENT; + myClassInstance.schedule = [ + { + time: '07:15', + day: 1, + }, + ]; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(0); + }); + + it('should not validate a recurrent frequency associated with an invalid schedule', async () => { + const myClassInstance = new MyClass(); + myClassInstance.frequency = Frequency.RECURRENT; + myClassInstance.schedule = [ + { + time: '07:15', + }, + ]; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(1); + }); +}); diff --git a/src/modules/ad/tests/unit/interface/is-after-or-equal.decorator.spec.ts b/src/modules/ad/tests/unit/interface/is-after-or-equal.decorator.spec.ts new file mode 100644 index 0000000..71ab685 --- /dev/null +++ b/src/modules/ad/tests/unit/interface/is-after-or-equal.decorator.spec.ts @@ -0,0 +1,45 @@ +import { IsAfterOrEqual } from '@modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-after-or-equal.decorator'; +import { Validator } from 'class-validator'; + +describe('Is after or equal decorator', () => { + class MyClass { + firstDate: string; + + @IsAfterOrEqual('firstDate', { + message: 'secondDate must be after or equal to firstDate', + }) + secondDate: string; + } + + it('should return a property decorator has a function', () => { + const isAfterOrEqual = IsAfterOrEqual('someProperty'); + expect(typeof isAfterOrEqual).toBe('function'); + }); + + it('should validate a secondDate posterior to firstDate', async () => { + const myClassInstance = new MyClass(); + myClassInstance.firstDate = '2023-07-20'; + myClassInstance.secondDate = '2023-07-30'; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(0); + }); + + it('should not validate a secondDate prior to firstDate', async () => { + const myClassInstance = new MyClass(); + myClassInstance.firstDate = '2023-07-20'; + myClassInstance.secondDate = '2023-07-19'; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(1); + }); + + it('should not validate if dates are invalid', async () => { + const myClassInstance = new MyClass(); + myClassInstance.firstDate = '2023-07-40'; + myClassInstance.secondDate = '2023-07-19'; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(1); + }); +});