diff --git a/src/modules/ad/interface/grpc-controllers/dtos/coordinates.dto.ts b/src/modules/ad/interface/grpc-controllers/dtos/coordinates.dto.ts index 54b4654..99f5783 100644 --- a/src/modules/ad/interface/grpc-controllers/dtos/coordinates.dto.ts +++ b/src/modules/ad/interface/grpc-controllers/dtos/coordinates.dto.ts @@ -1,7 +1,7 @@ import { AutoMap } from '@automapper/classes'; import { Transform } from 'class-transformer'; import { IsLatitude, IsLongitude } from 'class-validator'; -import { toPrecision } from './validators/to-precision'; +import { toPrecision } from './transformers/to-precision'; export class CoordinatesDto { @Transform(({ value }) => toPrecision(value, 6), { diff --git a/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts b/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts index 4bd2559..f7f31b5 100644 --- a/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts +++ b/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts @@ -14,9 +14,9 @@ import { Transform, Type } from 'class-transformer'; import { ScheduleDto } from './schedule.dto'; import { MarginDurationsDto } from './margin-durations.dto'; import { WaypointDto } from './waypoint.dto'; -import { intToFrequency } from './validators/frequency.mapping'; -import { IsSchedule } from './validators/decorators/is-schedule.validator'; -import { HasValidPositionIndexes } from './validators/decorators/valid-position-indexes.validator'; +import { intToFrequency } from './transformers/int-to-frequency'; +import { IsSchedule } from './validators/decorators/is-schedule.decorator'; +import { HasValidPositionIndexes } from './validators/decorators/has-valid-position-indexes.decorator'; import { Frequency } from '@modules/ad/core/ad.types'; export class CreateAdRequestDto { diff --git a/src/modules/ad/interface/grpc-controllers/dtos/validators/frequency.mapping.ts b/src/modules/ad/interface/grpc-controllers/dtos/transformers/int-to-frequency.ts similarity index 100% rename from src/modules/ad/interface/grpc-controllers/dtos/validators/frequency.mapping.ts rename to src/modules/ad/interface/grpc-controllers/dtos/transformers/int-to-frequency.ts diff --git a/src/modules/ad/interface/grpc-controllers/dtos/validators/to-precision.ts b/src/modules/ad/interface/grpc-controllers/dtos/transformers/to-precision.ts similarity index 100% rename from src/modules/ad/interface/grpc-controllers/dtos/validators/to-precision.ts rename to src/modules/ad/interface/grpc-controllers/dtos/transformers/to-precision.ts diff --git a/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/valid-position-indexes.validator.ts b/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/has-valid-position-indexes.decorator.ts similarity index 87% rename from src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/valid-position-indexes.validator.ts rename to src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/has-valid-position-indexes.decorator.ts index 5dede34..87e3a36 100644 --- a/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/valid-position-indexes.validator.ts +++ b/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/has-valid-position-indexes.decorator.ts @@ -1,5 +1,5 @@ import { ValidateBy, ValidationOptions, buildMessage } from 'class-validator'; -import { hasValidPositionIndexes } from '../waypoint-position'; +import { hasValidPositionIndexes } from '../has-valid-position-indexes.validator'; import { WaypointDto } from '../../waypoint.dto'; export const HasValidPositionIndexes = ( diff --git a/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-schedule.validator.ts b/src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-schedule.decorator.ts similarity index 100% rename from src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-schedule.validator.ts rename to src/modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-schedule.decorator.ts diff --git a/src/modules/ad/interface/grpc-controllers/dtos/validators/waypoint-position.ts b/src/modules/ad/interface/grpc-controllers/dtos/validators/has-valid-position-indexes.validator.ts similarity index 51% rename from src/modules/ad/interface/grpc-controllers/dtos/validators/waypoint-position.ts rename to src/modules/ad/interface/grpc-controllers/dtos/validators/has-valid-position-indexes.validator.ts index efd7300..04504a8 100644 --- a/src/modules/ad/interface/grpc-controllers/dtos/validators/waypoint-position.ts +++ b/src/modules/ad/interface/grpc-controllers/dtos/validators/has-valid-position-indexes.validator.ts @@ -1,14 +1,16 @@ import { WaypointDto } from '../waypoint.dto'; export const hasValidPositionIndexes = (waypoints: WaypointDto[]): boolean => { - if (!waypoints) return; + if (!waypoints) return false; + if (waypoints.length == 0) return false; if (waypoints.every((waypoint) => waypoint.position === undefined)) - return true; + return false; if (waypoints.every((waypoint) => typeof waypoint.position === 'number')) { - waypoints.sort((a, b) => a.position - b.position); - for (let i = 1; i < waypoints.length; i++) { - if (waypoints[i - 1].position >= waypoints[i].position) return false; - } + const positions = Array.from(waypoints, (waypoint) => waypoint.position); + positions.sort(); + for (let i = 1; i < positions.length; i++) + if (positions[i] != positions[i - 1] + 1) return false; + return true; } return false; diff --git a/src/modules/ad/tests/unit/interface/has-valid-position-indexes.decorator.spec.ts b/src/modules/ad/tests/unit/interface/has-valid-position-indexes.decorator.spec.ts new file mode 100644 index 0000000..bf61ce6 --- /dev/null +++ b/src/modules/ad/tests/unit/interface/has-valid-position-indexes.decorator.spec.ts @@ -0,0 +1,62 @@ +import { HasValidPositionIndexes } from '@modules/ad/interface/grpc-controllers/dtos/validators/decorators/has-valid-position-indexes.decorator'; +import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto'; +import { Validator } from 'class-validator'; + +describe('valid position indexes decorator', () => { + class MyClass { + @HasValidPositionIndexes() + waypoints: WaypointDto[]; + } + it('should return a property decorator has a function', () => { + const hasValidPositionIndexes = HasValidPositionIndexes(); + expect(typeof hasValidPositionIndexes).toBe('function'); + }); + it('should validate an array of waypoints with valid positions', async () => { + const myClassInstance = new MyClass(); + myClassInstance.waypoints = [ + { + position: 0, + lon: 48.8566, + lat: 2.3522, + locality: 'Paris', + postalCode: '75000', + country: 'France', + }, + { + position: 1, + lon: 49.2628, + lat: 4.0347, + locality: 'Reims', + postalCode: '51454', + country: 'France', + }, + ]; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(0); + }); + it('should not validate an array of waypoints with invalid positions', async () => { + const myClassInstance = new MyClass(); + myClassInstance.waypoints = [ + { + position: 1, + lon: 48.8566, + lat: 2.3522, + locality: 'Paris', + postalCode: '75000', + country: 'France', + }, + { + position: 1, + lon: 49.2628, + lat: 4.0347, + locality: 'Reims', + postalCode: '51454', + country: 'France', + }, + ]; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(1); + }); +}); diff --git a/src/modules/ad/tests/unit/interface/valid-position-indexes.spec.ts b/src/modules/ad/tests/unit/interface/has-valid-position-indexes.validator.spec.ts similarity index 83% rename from src/modules/ad/tests/unit/interface/valid-position-indexes.spec.ts rename to src/modules/ad/tests/unit/interface/has-valid-position-indexes.validator.spec.ts index f7d5272..ffc0272 100644 --- a/src/modules/ad/tests/unit/interface/valid-position-indexes.spec.ts +++ b/src/modules/ad/tests/unit/interface/has-valid-position-indexes.validator.spec.ts @@ -1,4 +1,4 @@ -import { hasValidPositionIndexes } from '@modules/ad/interface/grpc-controllers/dtos/validators/waypoint-position'; +import { hasValidPositionIndexes } from '@modules/ad/interface/grpc-controllers/dtos/validators/has-valid-position-indexes.validator'; import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto'; describe('addresses position validator', () => { @@ -26,10 +26,10 @@ describe('addresses position validator', () => { country: 'France', }; - it('should validate if no position is defined', () => { + it('should not validate if no position is defined', () => { expect( hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]), - ).toBeTruthy(); + ).toBeFalsy(); }); it('should not validate if only one position is defined', () => { mockAddress1.position = 0; @@ -61,11 +61,15 @@ describe('addresses position validator', () => { expect( hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]), ).toBeTruthy(); - mockAddress1.position = 10; - mockAddress2.position = 0; + mockAddress1.position = 1; + mockAddress2.position = 2; mockAddress3.position = 3; expect( hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]), ).toBeTruthy(); }); + it('should not validate if no waypoints are defined', () => { + expect(hasValidPositionIndexes(undefined)).toBeFalsy(); + expect(hasValidPositionIndexes([])).toBeFalsy(); + }); }); diff --git a/src/modules/ad/tests/unit/interface/frequency.mapping.spec.ts b/src/modules/ad/tests/unit/interface/int-to-frequency.spec.ts similarity index 92% rename from src/modules/ad/tests/unit/interface/frequency.mapping.spec.ts rename to src/modules/ad/tests/unit/interface/int-to-frequency.spec.ts index bd8928d..08f2729 100644 --- a/src/modules/ad/tests/unit/interface/frequency.mapping.spec.ts +++ b/src/modules/ad/tests/unit/interface/int-to-frequency.spec.ts @@ -1,5 +1,5 @@ import { Frequency } from '@modules/ad/core/ad.types'; -import { intToFrequency } from '@modules/ad/interface/grpc-controllers/dtos/validators/frequency.mapping'; +import { intToFrequency } from '@modules/ad/interface/grpc-controllers/dtos/transformers/int-to-frequency'; describe('frequency mapping', () => { it('should return punctual if frequency is 1', () => { diff --git a/src/modules/ad/tests/unit/interface/is-schedule.decorator.spec.ts b/src/modules/ad/tests/unit/interface/is-schedule.decorator.spec.ts new file mode 100644 index 0000000..613d0b4 --- /dev/null +++ b/src/modules/ad/tests/unit/interface/is-schedule.decorator.spec.ts @@ -0,0 +1,30 @@ +import { ScheduleDto } from '@modules/ad/interface/grpc-controllers/dtos/schedule.dto'; +import { IsSchedule } from '@modules/ad/interface/grpc-controllers/dtos/validators/decorators/is-schedule.decorator'; +import { Validator } from 'class-validator'; + +describe('schedule decorator', () => { + class MyClass { + @IsSchedule() + schedule: ScheduleDto; + } + it('should return a property decorator has a function', () => { + const isSchedule = IsSchedule(); + expect(typeof isSchedule).toBe('function'); + }); + it('should validate a valid schedule', async () => { + const myClassInstance = new MyClass(); + myClassInstance.schedule = { + mon: '07:15', + }; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(0); + }); + it('should not validate a invalid schedule', async () => { + const myClassInstance = new MyClass(); + myClassInstance.schedule = {}; + const validator = new Validator(); + const validation = await validator.validate(myClassInstance); + expect(validation.length).toBe(1); + }); +}); diff --git a/src/modules/ad/tests/unit/interface/to-precision.spec.ts b/src/modules/ad/tests/unit/interface/to-precision.spec.ts new file mode 100644 index 0000000..2da0933 --- /dev/null +++ b/src/modules/ad/tests/unit/interface/to-precision.spec.ts @@ -0,0 +1,14 @@ +import { toPrecision } from '@modules/ad/interface/grpc-controllers/dtos/transformers/to-precision'; + +describe('precision handler', () => { + it('should return a 6 digits float number for a 10 digits float input number and 6 as precision', () => { + const precised = toPrecision(1.1234567891, 6); + const stringPrecised = precised.toString().split('.')[1]; + expect(stringPrecised.length).toBe(6); + }); + it('should return a 2 digits float number for a 2 digits float input number and 4 as precision', () => { + const precised = toPrecision(1.12, 4); + const stringPrecised = precised.toString().split('.')[1]; + expect(stringPrecised.length).toBe(2); + }); +});