fix bad tests, fix invalid value object validations

This commit is contained in:
sbriat 2023-09-20 11:00:04 +02:00
parent 6b6a169dee
commit c9c682c1fc
16 changed files with 394 additions and 111 deletions

View File

@ -20,7 +20,7 @@ export abstract class Algorithm {
for (const processor of this.processors) {
this.candidates = await processor.execute(this.candidates);
}
console.log(JSON.stringify(this.candidates, null, 2));
// console.log(JSON.stringify(this.candidates, null, 2));
return this.candidates.map((candidate: CandidateEntity) =>
MatchEntity.create({ adId: candidate.id }),
);

View File

@ -1,7 +1,7 @@
import { ArgumentInvalidException, ValueObject } from '@mobicoop/ddd-library';
import { Role } from '../ad.types';
import { Target } from '../candidate.types';
import { ActorProps } from './actor.value-object';
import { Actor, ActorProps } from './actor.value-object';
/** Note:
* Value Objects with multiple properties can contain
@ -26,6 +26,7 @@ export class ActorTime extends ValueObject<ActorTimeProps> {
get maxTime(): string {
return this.props.maxTime;
}
get role(): Role {
return this.props.role;
}
@ -35,6 +36,11 @@ export class ActorTime extends ValueObject<ActorTimeProps> {
}
protected validate(props: ActorTimeProps): void {
// validate actor props
new Actor({
role: props.role,
target: props.target,
});
this._validateTime(props.time, 'time');
this._validateTime(props.minTime, 'minTime');
this._validateTime(props.maxTime, 'maxTime');

View File

@ -1,9 +1,11 @@
import {
ArgumentInvalidException,
ArgumentOutOfRangeException,
ValueObject,
} from '@mobicoop/ddd-library';
import { ScheduleItemProps } from './schedule-item.value-object';
import { ScheduleItem, ScheduleItemProps } from './schedule-item.value-object';
import { ActorTime } from './actor-time.value-object';
import { Actor } from './actor.value-object';
/** Note:
* Value Objects with multiple properties can contain
@ -29,14 +31,37 @@ export class Journey extends ValueObject<JourneyProps> {
return this.props.actorTimes;
}
get day(): number {
return this.props.day;
}
get time(): string {
return this.props.time;
}
get margin(): number {
return this.props.margin;
}
protected validate(props: JourneyProps): void {
// validate scheduleItem props
new ScheduleItem({
day: props.day,
time: props.time,
margin: props.margin,
});
// validate actor times
props.actorTimes.forEach((actorTime: ActorTime) => {
new Actor({
role: actorTime.role,
target: actorTime.target,
});
});
if (props.firstDate > props.lastDate)
throw new ArgumentInvalidException('firstDate must be before lastDate');
if (props.actorTimes.length < 4)
throw new ArgumentOutOfRangeException(
'firstDate must be before lastDate',
);
if (props.actorTimes.length <= 0)
throw new ArgumentOutOfRangeException(
'at least one actorTime is required',
'at least 4 actorTimes are required',
);
}
}

View File

@ -1,5 +1,5 @@
import { ArgumentInvalidException, ValueObject } from '@mobicoop/ddd-library';
import { PointProps } from './point.value-object';
import { Point, PointProps } from './point.value-object';
/** Note:
* Value Objects with multiple properties can contain
@ -29,6 +29,11 @@ export class Step extends ValueObject<StepProps> {
}
protected validate(props: StepProps): void {
// validate point props
new Point({
lon: props.lon,
lat: props.lat,
});
if (props.duration < 0)
throw new ArgumentInvalidException(
'duration must be greater than or equal to 0',

View File

@ -0,0 +1,49 @@
import { Role } from '@modules/ad/core/domain/ad.types';
import { Target } from '@modules/ad/core/domain/candidate.types';
import { ActorTime } from '@modules/ad/core/domain/value-objects/actor-time.value-object';
describe('Actor time value object', () => {
it('should create an actor time value object', () => {
const actorTimeVO = new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:45',
maxTime: '07:15',
});
expect(actorTimeVO.role).toBe(Role.DRIVER);
expect(actorTimeVO.target).toBe(Target.START);
expect(actorTimeVO.time).toBe('07:00');
expect(actorTimeVO.minTime).toBe('06:45');
expect(actorTimeVO.maxTime).toBe('07:15');
});
it('should throw an error if a time is invalid', () => {
expect(() => {
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '27:00',
minTime: '06:45',
maxTime: '07:15',
});
}).toThrow();
expect(() => {
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:95',
maxTime: '07:15',
});
}).toThrow();
expect(() => {
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:45',
maxTime: '07',
});
}).toThrow();
});
});

View File

@ -101,17 +101,13 @@ describe('Carpool Path Creator Service', () => {
expect(carpoolSteps[5].actors.length).toBe(1);
});
it('should throw an exception if less than 2 driver waypoints are given', () => {
try {
expect(() => {
new CarpoolPathCreator([waypoint1], [waypoint3, waypoint4]);
} catch (e: any) {
expect(e).toBeInstanceOf(CarpoolPathCreatorException);
}
}).toThrow(CarpoolPathCreatorException);
});
it('should throw an exception if less than 2 passenger waypoints are given', () => {
try {
expect(() => {
new CarpoolPathCreator([waypoint1, waypoint6], [waypoint3]);
} catch (e: any) {
expect(e).toBeInstanceOf(CarpoolPathCreatorException);
}
}).toThrow(CarpoolPathCreatorException);
});
});

View File

@ -28,7 +28,7 @@ describe('CarpoolStep value object', () => {
expect(carpoolStepVO.actors).toHaveLength(2);
});
it('should throw an exception if actors is empty', () => {
try {
expect(() => {
new CarpoolStep({
point: new Point({
lat: 48.689445,
@ -36,12 +36,10 @@ describe('CarpoolStep value object', () => {
}),
actors: [],
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if actors contains more than one driver', () => {
try {
expect(() => {
new CarpoolStep({
point: new Point({
lat: 48.689445,
@ -58,8 +56,6 @@ describe('CarpoolStep value object', () => {
}),
],
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
});

View File

@ -0,0 +1,165 @@
import {
ArgumentInvalidException,
ArgumentOutOfRangeException,
} from '@mobicoop/ddd-library';
import { Role } from '@modules/ad/core/domain/ad.types';
import { Target } from '@modules/ad/core/domain/candidate.types';
import { ActorTime } from '@modules/ad/core/domain/value-objects/actor-time.value-object';
import { Journey } from '@modules/ad/core/domain/value-objects/journey.value-object';
describe('Journey value object', () => {
it('should create a journey value object', () => {
const journeyVO = new Journey({
firstDate: new Date('2023-09-20'),
lastDate: new Date('2024-09-20'),
actorTimes: [
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:45',
maxTime: '07:15',
}),
new ActorTime({
role: Role.PASSENGER,
target: Target.START,
time: '07:10',
minTime: '06:55',
maxTime: '07:25',
}),
new ActorTime({
role: Role.DRIVER,
target: Target.FINISH,
time: '08:30',
minTime: '08:15',
maxTime: '08:45',
}),
new ActorTime({
role: Role.PASSENGER,
target: Target.FINISH,
time: '08:40',
minTime: '08:25',
maxTime: '08:55',
}),
],
day: 0,
time: '07:00',
margin: 900,
});
expect(journeyVO.day).toBe(0);
expect(journeyVO.time).toBe('07:00');
expect(journeyVO.margin).toBe(900);
expect(journeyVO.actorTimes).toHaveLength(4);
expect(journeyVO.firstDate.getDate()).toBe(20);
expect(journeyVO.lastDate.getMonth()).toBe(8);
});
it('should throw an exception if day is invalid', () => {
expect(() => {
new Journey({
firstDate: new Date('2023-09-20'),
lastDate: new Date('2024-09-20'),
actorTimes: [
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:45',
maxTime: '07:15',
}),
new ActorTime({
role: Role.PASSENGER,
target: Target.START,
time: '07:10',
minTime: '06:55',
maxTime: '07:25',
}),
new ActorTime({
role: Role.DRIVER,
target: Target.FINISH,
time: '08:30',
minTime: '08:15',
maxTime: '08:45',
}),
new ActorTime({
role: Role.PASSENGER,
target: Target.FINISH,
time: '08:40',
minTime: '08:25',
maxTime: '08:55',
}),
],
day: 7,
time: '07:00',
margin: 900,
});
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if actor times is too short', () => {
expect(() => {
new Journey({
firstDate: new Date('2023-09-20'),
lastDate: new Date('2024-09-20'),
actorTimes: [
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:45',
maxTime: '07:15',
}),
new ActorTime({
role: Role.DRIVER,
target: Target.FINISH,
time: '08:30',
minTime: '08:15',
maxTime: '08:45',
}),
],
day: 0,
time: '07:00',
margin: 900,
});
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if dates are invalid', () => {
expect(() => {
new Journey({
firstDate: new Date('2023-09-20'),
lastDate: new Date('2023-09-19'),
actorTimes: [
new ActorTime({
role: Role.DRIVER,
target: Target.START,
time: '07:00',
minTime: '06:45',
maxTime: '07:15',
}),
new ActorTime({
role: Role.PASSENGER,
target: Target.START,
time: '07:10',
minTime: '06:55',
maxTime: '07:25',
}),
new ActorTime({
role: Role.DRIVER,
target: Target.FINISH,
time: '08:30',
minTime: '08:15',
maxTime: '08:45',
}),
new ActorTime({
role: Role.PASSENGER,
target: Target.FINISH,
time: '08:40',
minTime: '08:25',
maxTime: '08:55',
}),
],
day: 0,
time: '07:00',
margin: 900,
});
}).toThrow(ArgumentInvalidException);
});
});

View File

@ -70,20 +70,16 @@ describe('Path Creator Service', () => {
).toHaveLength(2);
});
it('should throw an exception if a role is not given', () => {
try {
expect(() => {
new PathCreator(
[],
[originWaypoint, intermediateWaypoint, destinationWaypoint],
);
} catch (e: any) {
expect(e).toBeInstanceOf(PathCreatorException);
}
}).toThrow(PathCreatorException);
});
it('should throw an exception if less than 2 waypoints are given', () => {
try {
expect(() => {
new PathCreator([Role.DRIVER], [originWaypoint]);
} catch (e: any) {
expect(e).toBeInstanceOf(PathCreatorException);
}
}).toThrow(PathCreatorException);
});
});

View File

@ -27,39 +27,31 @@ describe('Point value object', () => {
expect(pointVO.isSame(differentPointVO)).toBeFalsy();
});
it('should throw an exception if longitude is invalid', () => {
try {
expect(() => {
new Point({
lat: 48.689445,
lon: 186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Point({
lat: 48.689445,
lon: -186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if latitude is invalid', () => {
try {
expect(() => {
new Point({
lat: 148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Point({
lat: -148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
});

View File

@ -16,47 +16,39 @@ describe('Schedule item value object', () => {
expect(scheduleItemVO.margin).toBe(900);
});
it('should throw an exception if day is invalid', () => {
try {
expect(() => {
new ScheduleItem({
day: 7,
time: '07:00',
margin: 900,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if time is invalid', () => {
try {
expect(() => {
new ScheduleItem({
day: 0,
time: '07,00',
margin: 900,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentInvalidException);
}
}).toThrow(ArgumentInvalidException);
});
it('should throw an exception if the hour of the time is invalid', () => {
try {
expect(() => {
new ScheduleItem({
day: 0,
time: '25:00',
margin: 900,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentInvalidException);
}
}).toThrow(ArgumentInvalidException);
});
it('should throw an exception if the minutes of the time are invalid', () => {
try {
expect(() => {
new ScheduleItem({
day: 0,
time: '07:63',
margin: 900,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentInvalidException);
}
}).toThrow(ArgumentInvalidException);
});
});

View File

@ -0,0 +1,76 @@
import {
ArgumentInvalidException,
ArgumentOutOfRangeException,
} from '@mobicoop/ddd-library';
import { Step } from '@modules/ad/core/domain/value-objects/step.value-object';
describe('Step value object', () => {
it('should create a step value object', () => {
const stepVO = new Step({
lat: 48.689445,
lon: 6.17651,
duration: 150,
distance: 12000,
});
expect(stepVO.duration).toBe(150);
expect(stepVO.distance).toBe(12000);
expect(stepVO.lat).toBe(48.689445);
expect(stepVO.lon).toBe(6.17651);
});
it('should throw an exception if longitude is invalid', () => {
expect(() => {
new Step({
lat: 48.689445,
lon: 186.17651,
duration: 150,
distance: 12000,
});
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Step({
lat: 48.689445,
lon: -186.17651,
duration: 150,
distance: 12000,
});
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if latitude is invalid', () => {
expect(() => {
new Step({
lat: 248.689445,
lon: 6.17651,
duration: 150,
distance: 12000,
});
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Step({
lat: -148.689445,
lon: 6.17651,
duration: 150,
distance: 12000,
});
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if distance is invalid', () => {
expect(() => {
new Step({
lat: 48.689445,
lon: 6.17651,
duration: 150,
distance: -12000,
});
}).toThrow(ArgumentInvalidException);
});
it('should throw an exception if duration is invalid', () => {
expect(() => {
new Step({
lat: 48.689445,
lon: 6.17651,
duration: -150,
distance: 12000,
});
}).toThrow(ArgumentInvalidException);
});
});

View File

@ -22,7 +22,7 @@ export class Point extends ValueObject<PointProps> {
return this.props.lat;
}
protected validate(props: PointProps): void {
validate(props: PointProps): void {
if (props.lon > 180 || props.lon < -180)
throw new ArgumentOutOfRangeException('lon must be between -180 and 180');
if (props.lat > 90 || props.lat < -90)

View File

@ -1,5 +1,5 @@
import { ArgumentInvalidException, ValueObject } from '@mobicoop/ddd-library';
import { PointProps } from './point.value-object';
import { Point, PointProps } from './point.value-object';
/** Note:
* Value Objects with multiple properties can contain
@ -29,6 +29,11 @@ export class Step extends ValueObject<StepProps> {
}
protected validate(props: StepProps): void {
// validate point props
new Point({
lon: props.lon,
lat: props.lat,
});
if (props.duration < 0)
throw new ArgumentInvalidException(
'duration must be greater than or equal to 0',

View File

@ -11,39 +11,31 @@ describe('Point value object', () => {
expect(pointVO.lon).toBe(6.17651);
});
it('should throw an exception if longitude is invalid', () => {
try {
expect(() => {
new Point({
lat: 48.689445,
lon: 186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Point({
lat: 48.689445,
lon: -186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if latitude is invalid', () => {
try {
expect(() => {
new Point({
lat: 148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Point({
lat: -148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
});

View File

@ -18,71 +18,59 @@ describe('Step value object', () => {
expect(stepVO.lon).toBe(6.17651);
});
it('should throw an exception if longitude is invalid', () => {
try {
expect(() => {
new Step({
lat: 48.689445,
lon: 186.17651,
duration: 150,
distance: 12000,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Step({
lon: 48.689445,
lat: -186.17651,
lat: 48.689445,
lon: -186.17651,
duration: 150,
distance: 12000,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if latitude is invalid', () => {
try {
expect(() => {
new Step({
lat: 248.689445,
lon: 6.17651,
duration: 150,
distance: 12000,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
}).toThrow(ArgumentOutOfRangeException);
expect(() => {
new Step({
lon: -148.689445,
lat: 6.17651,
lat: -148.689445,
lon: 6.17651,
duration: 150,
distance: 12000,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
}).toThrow(ArgumentOutOfRangeException);
});
it('should throw an exception if distance is invalid', () => {
try {
expect(() => {
new Step({
lat: 48.689445,
lon: 6.17651,
duration: 150,
distance: -12000,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentInvalidException);
}
}).toThrow(ArgumentInvalidException);
});
it('should throw an exception if duration is invalid', () => {
try {
expect(() => {
new Step({
lat: 48.689445,
lon: 6.17651,
duration: -150,
distance: 12000,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentInvalidException);
}
}).toThrow(ArgumentInvalidException);
});
});