transform to output
This commit is contained in:
parent
218595553d
commit
df92245357
|
@ -2,5 +2,8 @@ export const AD_MESSAGE_PUBLISHER = Symbol('AD_MESSAGE_PUBLISHER');
|
||||||
export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER');
|
export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER');
|
||||||
export const TIMEZONE_FINDER = Symbol('TIMEZONE_FINDER');
|
export const TIMEZONE_FINDER = Symbol('TIMEZONE_FINDER');
|
||||||
export const TIME_CONVERTER = Symbol('TIME_CONVERTER');
|
export const TIME_CONVERTER = Symbol('TIME_CONVERTER');
|
||||||
export const DATETIME_TRANSFORMER = Symbol('DATETIME_TRANSFORMER');
|
export const INPUT_DATETIME_TRANSFORMER = Symbol('INPUT_DATETIME_TRANSFORMER');
|
||||||
|
export const OUTPUT_DATETIME_TRANSFORMER = Symbol(
|
||||||
|
'OUTPUT_DATETIME_TRANSFORMER',
|
||||||
|
);
|
||||||
export const AD_REPOSITORY = Symbol('AD_REPOSITORY');
|
export const AD_REPOSITORY = Symbol('AD_REPOSITORY');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Mapper } from '@mobicoop/ddd-library';
|
import { Mapper } from '@mobicoop/ddd-library';
|
||||||
import { AdResponseDto } from './interface/dtos/ad.response.dto';
|
import { AdResponseDto } from './interface/dtos/ad.response.dto';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { AdEntity } from './core/domain/ad.entity';
|
import { AdEntity } from './core/domain/ad.entity';
|
||||||
import {
|
import {
|
||||||
AdWriteModel,
|
AdWriteModel,
|
||||||
|
@ -12,6 +12,8 @@ import { Frequency } from './core/domain/ad.types';
|
||||||
import { WaypointProps } from './core/domain/value-objects/waypoint.value-object';
|
import { WaypointProps } from './core/domain/value-objects/waypoint.value-object';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.value-object';
|
import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.value-object';
|
||||||
|
import { OUTPUT_DATETIME_TRANSFORMER } from './ad.di-tokens';
|
||||||
|
import { DateTimeTransformerPort } from './core/application/ports/datetime-transformer.port';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper constructs objects that are used in different layers:
|
* Mapper constructs objects that are used in different layers:
|
||||||
|
@ -24,6 +26,11 @@ import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.val
|
||||||
export class AdMapper
|
export class AdMapper
|
||||||
implements Mapper<AdEntity, AdReadModel, AdWriteModel, AdResponseDto>
|
implements Mapper<AdEntity, AdReadModel, AdWriteModel, AdResponseDto>
|
||||||
{
|
{
|
||||||
|
constructor(
|
||||||
|
@Inject(OUTPUT_DATETIME_TRANSFORMER)
|
||||||
|
private readonly outputDatetimeTransformer: DateTimeTransformerPort,
|
||||||
|
) {}
|
||||||
|
|
||||||
toPersistence = (entity: AdEntity): AdWriteModel => {
|
toPersistence = (entity: AdEntity): AdWriteModel => {
|
||||||
const copy = entity.getProps();
|
const copy = entity.getProps();
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
@ -129,12 +136,42 @@ export class AdMapper
|
||||||
response.driver = props.driver;
|
response.driver = props.driver;
|
||||||
response.passenger = props.passenger;
|
response.passenger = props.passenger;
|
||||||
response.frequency = props.frequency;
|
response.frequency = props.frequency;
|
||||||
response.fromDate = props.fromDate;
|
response.fromDate = this.outputDatetimeTransformer.fromDate(
|
||||||
response.toDate = props.toDate;
|
{
|
||||||
|
date: props.fromDate,
|
||||||
|
time: props.schedule[0].time,
|
||||||
|
coordinates: props.waypoints[0].address.coordinates,
|
||||||
|
},
|
||||||
|
props.frequency,
|
||||||
|
);
|
||||||
|
response.toDate = this.outputDatetimeTransformer.toDate(
|
||||||
|
props.toDate,
|
||||||
|
{
|
||||||
|
date: props.fromDate,
|
||||||
|
time: props.schedule[0].time,
|
||||||
|
coordinates: props.waypoints[0].address.coordinates,
|
||||||
|
},
|
||||||
|
props.frequency,
|
||||||
|
);
|
||||||
response.schedule = props.schedule.map(
|
response.schedule = props.schedule.map(
|
||||||
(scheduleItem: ScheduleItemProps) => ({
|
(scheduleItem: ScheduleItemProps) => ({
|
||||||
day: scheduleItem.day,
|
day: this.outputDatetimeTransformer.day(
|
||||||
time: scheduleItem.time,
|
scheduleItem.day,
|
||||||
|
{
|
||||||
|
date: props.fromDate,
|
||||||
|
time: scheduleItem.time,
|
||||||
|
coordinates: props.waypoints[0].address.coordinates,
|
||||||
|
},
|
||||||
|
props.frequency,
|
||||||
|
),
|
||||||
|
time: this.outputDatetimeTransformer.time(
|
||||||
|
{
|
||||||
|
date: props.fromDate,
|
||||||
|
time: scheduleItem.time,
|
||||||
|
coordinates: props.waypoints[0].address.coordinates,
|
||||||
|
},
|
||||||
|
props.frequency,
|
||||||
|
),
|
||||||
margin: scheduleItem.margin,
|
margin: scheduleItem.margin,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { CqrsModule } from '@nestjs/cqrs';
|
||||||
import {
|
import {
|
||||||
AD_MESSAGE_PUBLISHER,
|
AD_MESSAGE_PUBLISHER,
|
||||||
AD_REPOSITORY,
|
AD_REPOSITORY,
|
||||||
DATETIME_TRANSFORMER,
|
INPUT_DATETIME_TRANSFORMER,
|
||||||
|
OUTPUT_DATETIME_TRANSFORMER,
|
||||||
PARAMS_PROVIDER,
|
PARAMS_PROVIDER,
|
||||||
TIMEZONE_FINDER,
|
TIMEZONE_FINDER,
|
||||||
TIME_CONVERTER,
|
TIME_CONVERTER,
|
||||||
|
@ -20,7 +21,8 @@ import { FindAdByIdQueryHandler } from './core/application/queries/find-ad-by-id
|
||||||
import { PublishMessageWhenAdIsCreatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-ad-is-created.domain-event-handler';
|
import { PublishMessageWhenAdIsCreatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-ad-is-created.domain-event-handler';
|
||||||
import { PrismaService } from './infrastructure/prisma.service';
|
import { PrismaService } from './infrastructure/prisma.service';
|
||||||
import { MessageBrokerPublisher } from '@mobicoop/message-broker-module';
|
import { MessageBrokerPublisher } from '@mobicoop/message-broker-module';
|
||||||
import { DateTimeTransformer } from './infrastructure/datetime-transformer';
|
import { InputDateTimeTransformer } from './infrastructure/input-datetime-transformer';
|
||||||
|
import { OutputDateTimeTransformer } from './infrastructure/output-datetime-transformer';
|
||||||
|
|
||||||
const grpcControllers = [CreateAdGrpcController, FindAdByIdGrpcController];
|
const grpcControllers = [CreateAdGrpcController, FindAdByIdGrpcController];
|
||||||
|
|
||||||
|
@ -63,8 +65,12 @@ const adapters: Provider[] = [
|
||||||
useClass: TimeConverter,
|
useClass: TimeConverter,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: DATETIME_TRANSFORMER,
|
provide: INPUT_DATETIME_TRANSFORMER,
|
||||||
useClass: DateTimeTransformer,
|
useClass: InputDateTimeTransformer,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: OUTPUT_DATETIME_TRANSFORMER,
|
||||||
|
useClass: OutputDateTimeTransformer,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { CreateAdCommand } from './create-ad.command';
|
||||||
import { Inject } from '@nestjs/common';
|
import { Inject } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
AD_REPOSITORY,
|
AD_REPOSITORY,
|
||||||
DATETIME_TRANSFORMER,
|
INPUT_DATETIME_TRANSFORMER,
|
||||||
PARAMS_PROVIDER,
|
PARAMS_PROVIDER,
|
||||||
} from '@modules/ad/ad.di-tokens';
|
} from '@modules/ad/ad.di-tokens';
|
||||||
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
|
@ -25,7 +25,7 @@ export class CreateAdService implements ICommandHandler {
|
||||||
private readonly repository: AdRepositoryPort,
|
private readonly repository: AdRepositoryPort,
|
||||||
@Inject(PARAMS_PROVIDER)
|
@Inject(PARAMS_PROVIDER)
|
||||||
private readonly defaultParamsProvider: DefaultParamsProviderPort,
|
private readonly defaultParamsProvider: DefaultParamsProviderPort,
|
||||||
@Inject(DATETIME_TRANSFORMER)
|
@Inject(INPUT_DATETIME_TRANSFORMER)
|
||||||
private readonly datetimeTransformer: DateTimeTransformerPort,
|
private readonly datetimeTransformer: DateTimeTransformerPort,
|
||||||
) {
|
) {
|
||||||
this._defaultParams = defaultParamsProvider.getParams();
|
this._defaultParams = defaultParamsProvider.getParams();
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
export interface TimeConverterPort {
|
export interface TimeConverterPort {
|
||||||
localStringTimeToUtcStringTime(time: string, timezone: string): string;
|
localStringTimeToUtcStringTime(time: string, timezone: string): string;
|
||||||
|
utcStringTimeToLocalStringTime(time: string, timezone: string): string;
|
||||||
localStringDateTimeToUtcDate(
|
localStringDateTimeToUtcDate(
|
||||||
date: string,
|
date: string,
|
||||||
time: string,
|
time: string,
|
||||||
timezone: string,
|
timezone: string,
|
||||||
dst?: boolean,
|
dst?: boolean,
|
||||||
): Date;
|
): Date;
|
||||||
|
utcStringDateTimeToLocalIsoString(
|
||||||
|
date: string,
|
||||||
|
time: string,
|
||||||
|
timezone: string,
|
||||||
|
dst?: boolean,
|
||||||
|
): string;
|
||||||
utcUnixEpochDayFromTime(time: string, timezone: string): number;
|
utcUnixEpochDayFromTime(time: string, timezone: string): number;
|
||||||
|
localUnixEpochDayFromTime(time: string, timezone: string): number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,9 @@ export class FindAdByIdQueryHandler implements IQueryHandler {
|
||||||
private readonly repository: AdRepositoryPort,
|
private readonly repository: AdRepositoryPort,
|
||||||
) {}
|
) {}
|
||||||
async execute(query: FindAdByIdQuery): Promise<AdEntity> {
|
async execute(query: FindAdByIdQuery): Promise<AdEntity> {
|
||||||
return await this.repository.findOneById(query.id, { waypoints: true });
|
return await this.repository.findOneById(query.id, {
|
||||||
|
waypoints: true,
|
||||||
|
schedule: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { TimezoneFinderPort } from '../core/application/ports/timezone-finder.po
|
||||||
import { DefaultParamsProviderPort } from '../core/application/ports/default-params-provider.port';
|
import { DefaultParamsProviderPort } from '../core/application/ports/default-params-provider.port';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DateTimeTransformer implements DateTimeTransformerPort {
|
export class InputDateTimeTransformer implements DateTimeTransformerPort {
|
||||||
private readonly _defaultTimezone: string;
|
private readonly _defaultTimezone: string;
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(PARAMS_PROVIDER)
|
@Inject(PARAMS_PROVIDER)
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
DateTimeTransformerPort,
|
||||||
|
Frequency,
|
||||||
|
GeoDateTime,
|
||||||
|
} from '../core/application/ports/datetime-transformer.port';
|
||||||
|
import { TimeConverterPort } from '../core/application/ports/time-converter.port';
|
||||||
|
import { TIMEZONE_FINDER, TIME_CONVERTER } from '../ad.di-tokens';
|
||||||
|
import { TimezoneFinderPort } from '../core/application/ports/timezone-finder.port';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OutputDateTimeTransformer implements DateTimeTransformerPort {
|
||||||
|
constructor(
|
||||||
|
@Inject(TIMEZONE_FINDER)
|
||||||
|
private readonly timezoneFinder: TimezoneFinderPort,
|
||||||
|
@Inject(TIME_CONVERTER) private readonly timeConverter: TimeConverterPort,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the fromDate : if an ad is punctual, the departure date
|
||||||
|
* is converted from UTC to the local date with the time and timezone
|
||||||
|
*/
|
||||||
|
fromDate = (geoFromDate: GeoDateTime, frequency: Frequency): string => {
|
||||||
|
if (frequency === Frequency.RECURRENT) return geoFromDate.date;
|
||||||
|
return this.timeConverter
|
||||||
|
.utcStringDateTimeToLocalIsoString(
|
||||||
|
geoFromDate.date,
|
||||||
|
geoFromDate.time,
|
||||||
|
this.timezoneFinder.timezones(
|
||||||
|
geoFromDate.coordinates.lon,
|
||||||
|
geoFromDate.coordinates.lat,
|
||||||
|
)[0],
|
||||||
|
)
|
||||||
|
.split('T')[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the toDate depending on frequency, time and timezone :
|
||||||
|
* if the ad is punctual, the toDate is equal to the fromDate
|
||||||
|
*/
|
||||||
|
toDate = (
|
||||||
|
toDate: string,
|
||||||
|
geoFromDate: GeoDateTime,
|
||||||
|
frequency: Frequency,
|
||||||
|
): string => {
|
||||||
|
if (frequency === Frequency.RECURRENT) return toDate;
|
||||||
|
return this.fromDate(geoFromDate, frequency);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the day for a schedule item :
|
||||||
|
* - if the ad is punctual, the day is infered from fromDate
|
||||||
|
* - if the ad is recurrent, the day is computed by converting the time from utc to local time
|
||||||
|
*/
|
||||||
|
day = (
|
||||||
|
day: number,
|
||||||
|
geoFromDate: GeoDateTime,
|
||||||
|
frequency: Frequency,
|
||||||
|
): number => {
|
||||||
|
if (frequency === Frequency.RECURRENT)
|
||||||
|
return this.recurrentDay(
|
||||||
|
day,
|
||||||
|
geoFromDate.time,
|
||||||
|
this.timezoneFinder.timezones(
|
||||||
|
geoFromDate.coordinates.lon,
|
||||||
|
geoFromDate.coordinates.lat,
|
||||||
|
)[0],
|
||||||
|
);
|
||||||
|
return new Date(this.fromDate(geoFromDate, frequency)).getDay();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the utc time
|
||||||
|
*/
|
||||||
|
time = (geoFromDate: GeoDateTime, frequency: Frequency): string => {
|
||||||
|
if (frequency === Frequency.RECURRENT)
|
||||||
|
return this.timeConverter.utcStringTimeToLocalStringTime(
|
||||||
|
geoFromDate.time,
|
||||||
|
this.timezoneFinder.timezones(
|
||||||
|
geoFromDate.coordinates.lon,
|
||||||
|
geoFromDate.coordinates.lat,
|
||||||
|
)[0],
|
||||||
|
);
|
||||||
|
return this.timeConverter
|
||||||
|
.utcStringDateTimeToLocalIsoString(
|
||||||
|
geoFromDate.date,
|
||||||
|
geoFromDate.time,
|
||||||
|
this.timezoneFinder.timezones(
|
||||||
|
geoFromDate.coordinates.lon,
|
||||||
|
geoFromDate.coordinates.lat,
|
||||||
|
)[0],
|
||||||
|
)
|
||||||
|
.split('T')[1]
|
||||||
|
.split(':', 2)
|
||||||
|
.join(':');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the day for a schedule item for a recurrent ad
|
||||||
|
* The day may change when transforming from utc to local timezone
|
||||||
|
*/
|
||||||
|
private recurrentDay = (
|
||||||
|
day: number,
|
||||||
|
time: string,
|
||||||
|
timezone: string,
|
||||||
|
): number => {
|
||||||
|
const unixEpochDay = 4; // 1970-01-01 is a thursday !
|
||||||
|
const localBaseDay = this.timeConverter.localUnixEpochDayFromTime(
|
||||||
|
time,
|
||||||
|
timezone,
|
||||||
|
);
|
||||||
|
if (unixEpochDay == localBaseDay) return day;
|
||||||
|
if (unixEpochDay > localBaseDay) return day > 0 ? day - 1 : 6;
|
||||||
|
return day < 6 ? day + 1 : 0;
|
||||||
|
};
|
||||||
|
}
|
|
@ -17,6 +17,17 @@ export class TimeConverter implements TimeConverterPort {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
utcStringTimeToLocalStringTime = (time: string, timezone: string): string => {
|
||||||
|
try {
|
||||||
|
if (!time || !timezone) throw new Error();
|
||||||
|
return new DateTime(`${this.UNIX_EPOCH}T${time}`, TimeZone.zone('UTC'))
|
||||||
|
.convert(TimeZone.zone(timezone))
|
||||||
|
.format('HH:mm');
|
||||||
|
} catch (e) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
localStringDateTimeToUtcDate = (
|
localStringDateTimeToUtcDate = (
|
||||||
date: string,
|
date: string,
|
||||||
time: string,
|
time: string,
|
||||||
|
@ -24,7 +35,7 @@ export class TimeConverter implements TimeConverterPort {
|
||||||
dst = true,
|
dst = true,
|
||||||
): Date => {
|
): Date => {
|
||||||
try {
|
try {
|
||||||
if (!time || !timezone) throw new Error();
|
if (!date || !time || !timezone) throw new Error();
|
||||||
return new Date(
|
return new Date(
|
||||||
new DateTime(
|
new DateTime(
|
||||||
`${date}T${time}`,
|
`${date}T${time}`,
|
||||||
|
@ -36,6 +47,22 @@ export class TimeConverter implements TimeConverterPort {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
utcStringDateTimeToLocalIsoString = (
|
||||||
|
date: string,
|
||||||
|
time: string,
|
||||||
|
timezone: string,
|
||||||
|
dst?: boolean,
|
||||||
|
): string => {
|
||||||
|
try {
|
||||||
|
if (!date || !time || !timezone) throw new Error();
|
||||||
|
return new DateTime(`${date}T${time}`, TimeZone.zone('UTC'))
|
||||||
|
.convert(TimeZone.zone(timezone, dst))
|
||||||
|
.toIsoString();
|
||||||
|
} catch (e) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
utcUnixEpochDayFromTime = (time: string, timezone: string): number => {
|
utcUnixEpochDayFromTime = (time: string, timezone: string): number => {
|
||||||
try {
|
try {
|
||||||
if (!time || !timezone) throw new Error();
|
if (!time || !timezone) throw new Error();
|
||||||
|
@ -52,4 +79,18 @@ export class TimeConverter implements TimeConverterPort {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
localUnixEpochDayFromTime = (time: string, timezone: string): number => {
|
||||||
|
try {
|
||||||
|
if (!time || !timezone) throw new Error();
|
||||||
|
return new Date(
|
||||||
|
new DateTime(`${this.UNIX_EPOCH}T${time}`, TimeZone.zone('UTC'))
|
||||||
|
.convert(TimeZone.zone(timezone))
|
||||||
|
.toIsoString()
|
||||||
|
.split('T')[0],
|
||||||
|
).getDay();
|
||||||
|
} catch (e) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ message ScheduleItem {
|
||||||
|
|
||||||
message Waypoint {
|
message Waypoint {
|
||||||
int32 position = 1;
|
int32 position = 1;
|
||||||
float lon = 2;
|
double lon = 2;
|
||||||
float lat = 3;
|
double lat = 3;
|
||||||
string name = 4;
|
string name = 4;
|
||||||
string houseNumber = 5;
|
string houseNumber = 5;
|
||||||
string street = 6;
|
string street = 6;
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
import { Transform } from 'class-transformer';
|
|
||||||
import { IsLatitude, IsLongitude } from 'class-validator';
|
import { IsLatitude, IsLongitude } from 'class-validator';
|
||||||
import { toPrecision } from './transformers/to-precision';
|
|
||||||
|
|
||||||
export class CoordinatesDto {
|
export class CoordinatesDto {
|
||||||
@Transform(({ value }) => toPrecision(value, 6), {
|
|
||||||
toClassOnly: true,
|
|
||||||
})
|
|
||||||
@IsLongitude()
|
@IsLongitude()
|
||||||
lon: number;
|
lon: number;
|
||||||
|
|
||||||
@Transform(({ value }) => toPrecision(value, 6), {
|
|
||||||
toClassOnly: true,
|
|
||||||
})
|
|
||||||
@IsLatitude()
|
@IsLatitude()
|
||||||
lat: number;
|
lat: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
|
||||||
|
|
||||||
export const intToFrequency = (frequencyAsInt: number): Frequency => {
|
|
||||||
if (frequencyAsInt == 1) return Frequency.PUNCTUAL;
|
|
||||||
if (frequencyAsInt == 2) return Frequency.RECURRENT;
|
|
||||||
throw new Error('Unknown frequency value');
|
|
||||||
};
|
|
|
@ -1,4 +0,0 @@
|
||||||
export const toPrecision = (input: number, precision: number): number => {
|
|
||||||
const multiplier = 10 ** precision;
|
|
||||||
return Math.round((input + Number.EPSILON) * multiplier) / multiplier;
|
|
||||||
};
|
|
|
@ -23,7 +23,7 @@ export class FindAdByIdGrpcController {
|
||||||
private readonly queryBus: QueryBus,
|
private readonly queryBus: QueryBus,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@GrpcMethod('AdsService', 'FindOneById')
|
@GrpcMethod('AdService', 'FindOneById')
|
||||||
async findOnebyId(data: FindAdByIdRequestDto): Promise<AdResponseDto> {
|
async findOnebyId(data: FindAdByIdRequestDto): Promise<AdResponseDto> {
|
||||||
try {
|
try {
|
||||||
const ad: AdEntity = await this.queryBus.execute(
|
const ad: AdEntity = await this.queryBus.execute(
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import { OUTPUT_DATETIME_TRANSFORMER } from '@modules/ad/ad.di-tokens';
|
||||||
import { AdMapper } from '@modules/ad/ad.mapper';
|
import { AdMapper } from '@modules/ad/ad.mapper';
|
||||||
|
import { DateTimeTransformerPort } from '@modules/ad/core/application/ports/datetime-transformer.port';
|
||||||
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||||
import {
|
import {
|
||||||
|
@ -111,12 +113,25 @@ const adReadModel: AdReadModel = {
|
||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockOutputDatetimeTransformer: DateTimeTransformerPort = {
|
||||||
|
fromDate: jest.fn(),
|
||||||
|
toDate: jest.fn(),
|
||||||
|
day: jest.fn(),
|
||||||
|
time: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
describe('Ad Mapper', () => {
|
describe('Ad Mapper', () => {
|
||||||
let adMapper: AdMapper;
|
let adMapper: AdMapper;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const module = await Test.createTestingModule({
|
const module = await Test.createTestingModule({
|
||||||
providers: [AdMapper],
|
providers: [
|
||||||
|
AdMapper,
|
||||||
|
{
|
||||||
|
provide: OUTPUT_DATETIME_TRANSFORMER,
|
||||||
|
useValue: mockOutputDatetimeTransformer,
|
||||||
|
},
|
||||||
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
adMapper = module.get<AdMapper>(AdMapper);
|
adMapper = module.get<AdMapper>(AdMapper);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import {
|
import {
|
||||||
AD_REPOSITORY,
|
AD_REPOSITORY,
|
||||||
DATETIME_TRANSFORMER,
|
INPUT_DATETIME_TRANSFORMER,
|
||||||
PARAMS_PROVIDER,
|
PARAMS_PROVIDER,
|
||||||
} from '@modules/ad/ad.di-tokens';
|
} from '@modules/ad/ad.di-tokens';
|
||||||
import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto';
|
import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto';
|
||||||
|
@ -76,7 +76,7 @@ const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockDateTimeTransformer: DateTimeTransformerPort = {
|
const mockInputDateTimeTransformer: DateTimeTransformerPort = {
|
||||||
fromDate: jest.fn(),
|
fromDate: jest.fn(),
|
||||||
toDate: jest.fn(),
|
toDate: jest.fn(),
|
||||||
day: jest.fn(),
|
day: jest.fn(),
|
||||||
|
@ -98,8 +98,8 @@ describe('create-ad.service', () => {
|
||||||
useValue: mockDefaultParamsProvider,
|
useValue: mockDefaultParamsProvider,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: DATETIME_TRANSFORMER,
|
provide: INPUT_DATETIME_TRANSFORMER,
|
||||||
useValue: mockDateTimeTransformer,
|
useValue: mockInputDateTimeTransformer,
|
||||||
},
|
},
|
||||||
CreateAdService,
|
CreateAdService,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import { OUTPUT_DATETIME_TRANSFORMER } from '@modules/ad/ad.di-tokens';
|
||||||
import { AdMapper } from '@modules/ad/ad.mapper';
|
import { AdMapper } from '@modules/ad/ad.mapper';
|
||||||
|
import { DateTimeTransformerPort } from '@modules/ad/core/application/ports/datetime-transformer.port';
|
||||||
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
||||||
import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
|
import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
|
||||||
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
|
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
|
||||||
|
@ -8,6 +10,13 @@ const mockMessagePublisher = {
|
||||||
publish: jest.fn().mockImplementation(),
|
publish: jest.fn().mockImplementation(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockOutputDatetimeTransformer: DateTimeTransformerPort = {
|
||||||
|
fromDate: jest.fn(),
|
||||||
|
toDate: jest.fn(),
|
||||||
|
day: jest.fn(),
|
||||||
|
time: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
describe('Ad repository', () => {
|
describe('Ad repository', () => {
|
||||||
let prismaService: PrismaService;
|
let prismaService: PrismaService;
|
||||||
let adMapper: AdMapper;
|
let adMapper: AdMapper;
|
||||||
|
@ -16,7 +25,14 @@ describe('Ad repository', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
imports: [EventEmitterModule.forRoot()],
|
imports: [EventEmitterModule.forRoot()],
|
||||||
providers: [PrismaService, AdMapper],
|
providers: [
|
||||||
|
PrismaService,
|
||||||
|
AdMapper,
|
||||||
|
{
|
||||||
|
provide: OUTPUT_DATETIME_TRANSFORMER,
|
||||||
|
useValue: mockOutputDatetimeTransformer,
|
||||||
|
},
|
||||||
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
prismaService = module.get<PrismaService>(PrismaService);
|
prismaService = module.get<PrismaService>(PrismaService);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Frequency } from '@modules/ad/core/application/ports/datetime-transform
|
||||||
import { DefaultParamsProviderPort } from '@modules/ad/core/application/ports/default-params-provider.port';
|
import { DefaultParamsProviderPort } from '@modules/ad/core/application/ports/default-params-provider.port';
|
||||||
import { TimeConverterPort } from '@modules/ad/core/application/ports/time-converter.port';
|
import { TimeConverterPort } from '@modules/ad/core/application/ports/time-converter.port';
|
||||||
import { TimezoneFinderPort } from '@modules/ad/core/application/ports/timezone-finder.port';
|
import { TimezoneFinderPort } from '@modules/ad/core/application/ports/timezone-finder.port';
|
||||||
import { DateTimeTransformer } from '@modules/ad/infrastructure/datetime-transformer';
|
import { InputDateTimeTransformer } from '@modules/ad/infrastructure/input-datetime-transformer';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
||||||
|
@ -32,12 +32,14 @@ const mockTimeConverter: TimeConverterPort = {
|
||||||
localStringTimeToUtcStringTime: jest
|
localStringTimeToUtcStringTime: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementationOnce(() => '00:15'),
|
.mockImplementationOnce(() => '00:15'),
|
||||||
|
utcStringTimeToLocalStringTime: jest.fn(),
|
||||||
localStringDateTimeToUtcDate: jest
|
localStringDateTimeToUtcDate: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementationOnce(() => new Date('2023-07-30T06:15:00.000Z'))
|
.mockImplementationOnce(() => new Date('2023-07-30T06:15:00.000Z'))
|
||||||
.mockImplementationOnce(() => new Date('2023-07-20T08:15:00.000Z'))
|
.mockImplementationOnce(() => new Date('2023-07-20T08:15:00.000Z'))
|
||||||
.mockImplementationOnce(() => new Date('2023-07-19T23:15:00.000Z'))
|
.mockImplementationOnce(() => new Date('2023-07-19T23:15:00.000Z'))
|
||||||
.mockImplementationOnce(() => new Date('2023-07-19T23:15:00.000Z')),
|
.mockImplementationOnce(() => new Date('2023-07-19T23:15:00.000Z')),
|
||||||
|
utcStringDateTimeToLocalIsoString: jest.fn(),
|
||||||
utcUnixEpochDayFromTime: jest
|
utcUnixEpochDayFromTime: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementationOnce(() => 4)
|
.mockImplementationOnce(() => 4)
|
||||||
|
@ -45,10 +47,11 @@ const mockTimeConverter: TimeConverterPort = {
|
||||||
.mockImplementationOnce(() => 3)
|
.mockImplementationOnce(() => 3)
|
||||||
.mockImplementationOnce(() => 5)
|
.mockImplementationOnce(() => 5)
|
||||||
.mockImplementationOnce(() => 5),
|
.mockImplementationOnce(() => 5),
|
||||||
|
localUnixEpochDayFromTime: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Datetime Transformer', () => {
|
describe('Input Datetime Transformer', () => {
|
||||||
let datetimeTransformer: DateTimeTransformer;
|
let inputDatetimeTransformer: InputDateTimeTransformer;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
@ -65,20 +68,22 @@ describe('Datetime Transformer', () => {
|
||||||
provide: TIME_CONVERTER,
|
provide: TIME_CONVERTER,
|
||||||
useValue: mockTimeConverter,
|
useValue: mockTimeConverter,
|
||||||
},
|
},
|
||||||
DateTimeTransformer,
|
InputDateTimeTransformer,
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
datetimeTransformer = module.get<DateTimeTransformer>(DateTimeTransformer);
|
inputDatetimeTransformer = module.get<InputDateTimeTransformer>(
|
||||||
|
InputDateTimeTransformer,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
expect(datetimeTransformer).toBeDefined();
|
expect(inputDatetimeTransformer).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('fromDate', () => {
|
describe('fromDate', () => {
|
||||||
it('should return fromDate as is if frequency is recurrent', () => {
|
it('should return fromDate as is if frequency is recurrent', () => {
|
||||||
const transformedFromDate: string = datetimeTransformer.fromDate(
|
const transformedFromDate: string = inputDatetimeTransformer.fromDate(
|
||||||
{
|
{
|
||||||
date: '2023-07-30',
|
date: '2023-07-30',
|
||||||
time: '07:15',
|
time: '07:15',
|
||||||
|
@ -92,7 +97,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(transformedFromDate).toBe('2023-07-30');
|
expect(transformedFromDate).toBe('2023-07-30');
|
||||||
});
|
});
|
||||||
it('should return transformed fromDate if frequency is punctual and coordinates are those of Nancy', () => {
|
it('should return transformed fromDate if frequency is punctual and coordinates are those of Nancy', () => {
|
||||||
const transformedFromDate: string = datetimeTransformer.fromDate(
|
const transformedFromDate: string = inputDatetimeTransformer.fromDate(
|
||||||
{
|
{
|
||||||
date: '2023-07-30',
|
date: '2023-07-30',
|
||||||
time: '07:15',
|
time: '07:15',
|
||||||
|
@ -109,7 +114,7 @@ describe('Datetime Transformer', () => {
|
||||||
|
|
||||||
describe('toDate', () => {
|
describe('toDate', () => {
|
||||||
it('should return toDate as is if frequency is recurrent', () => {
|
it('should return toDate as is if frequency is recurrent', () => {
|
||||||
const transformedToDate: string = datetimeTransformer.toDate(
|
const transformedToDate: string = inputDatetimeTransformer.toDate(
|
||||||
'2024-07-29',
|
'2024-07-29',
|
||||||
{
|
{
|
||||||
date: '2023-07-20',
|
date: '2023-07-20',
|
||||||
|
@ -124,7 +129,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(transformedToDate).toBe('2024-07-29');
|
expect(transformedToDate).toBe('2024-07-29');
|
||||||
});
|
});
|
||||||
it('should return transformed fromDate if frequency is punctual', () => {
|
it('should return transformed fromDate if frequency is punctual', () => {
|
||||||
const transformedToDate: string = datetimeTransformer.toDate(
|
const transformedToDate: string = inputDatetimeTransformer.toDate(
|
||||||
'2024-07-30',
|
'2024-07-30',
|
||||||
{
|
{
|
||||||
date: '2023-07-20',
|
date: '2023-07-20',
|
||||||
|
@ -142,7 +147,7 @@ describe('Datetime Transformer', () => {
|
||||||
|
|
||||||
describe('day', () => {
|
describe('day', () => {
|
||||||
it('should not change day if frequency is recurrent and converted UTC time is on the same day', () => {
|
it('should not change day if frequency is recurrent and converted UTC time is on the same day', () => {
|
||||||
const day: number = datetimeTransformer.day(
|
const day: number = inputDatetimeTransformer.day(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
date: '2023-07-24',
|
date: '2023-07-24',
|
||||||
|
@ -157,7 +162,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(day).toBe(1);
|
expect(day).toBe(1);
|
||||||
});
|
});
|
||||||
it('should change day if frequency is recurrent and converted UTC time is on the previous day', () => {
|
it('should change day if frequency is recurrent and converted UTC time is on the previous day', () => {
|
||||||
const day: number = datetimeTransformer.day(
|
const day: number = inputDatetimeTransformer.day(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
date: '2023-07-24',
|
date: '2023-07-24',
|
||||||
|
@ -172,7 +177,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(day).toBe(0);
|
expect(day).toBe(0);
|
||||||
});
|
});
|
||||||
it('should change day if frequency is recurrent and converted UTC time is on the previous day and given day is sunday', () => {
|
it('should change day if frequency is recurrent and converted UTC time is on the previous day and given day is sunday', () => {
|
||||||
const day: number = datetimeTransformer.day(
|
const day: number = inputDatetimeTransformer.day(
|
||||||
0,
|
0,
|
||||||
{
|
{
|
||||||
date: '2023-07-23',
|
date: '2023-07-23',
|
||||||
|
@ -187,7 +192,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(day).toBe(6);
|
expect(day).toBe(6);
|
||||||
});
|
});
|
||||||
it('should change day if frequency is recurrent and converted UTC time is on the next day', () => {
|
it('should change day if frequency is recurrent and converted UTC time is on the next day', () => {
|
||||||
const day: number = datetimeTransformer.day(
|
const day: number = inputDatetimeTransformer.day(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
date: '2023-07-24',
|
date: '2023-07-24',
|
||||||
|
@ -202,7 +207,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(day).toBe(2);
|
expect(day).toBe(2);
|
||||||
});
|
});
|
||||||
it('should change day if frequency is recurrent and converted UTC time is on the next day and given day is saturday(6)', () => {
|
it('should change day if frequency is recurrent and converted UTC time is on the next day and given day is saturday(6)', () => {
|
||||||
const day: number = datetimeTransformer.day(
|
const day: number = inputDatetimeTransformer.day(
|
||||||
6,
|
6,
|
||||||
{
|
{
|
||||||
date: '2023-07-29',
|
date: '2023-07-29',
|
||||||
|
@ -217,7 +222,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(day).toBe(0);
|
expect(day).toBe(0);
|
||||||
});
|
});
|
||||||
it('should return utc fromDate day if frequency is punctual', () => {
|
it('should return utc fromDate day if frequency is punctual', () => {
|
||||||
const day: number = datetimeTransformer.day(
|
const day: number = inputDatetimeTransformer.day(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
date: '2023-07-20',
|
date: '2023-07-20',
|
||||||
|
@ -235,7 +240,7 @@ describe('Datetime Transformer', () => {
|
||||||
|
|
||||||
describe('time', () => {
|
describe('time', () => {
|
||||||
it('should transform given time to utc time if frequency is recurrent', () => {
|
it('should transform given time to utc time if frequency is recurrent', () => {
|
||||||
const time: string = datetimeTransformer.time(
|
const time: string = inputDatetimeTransformer.time(
|
||||||
{
|
{
|
||||||
date: '2023-07-24',
|
date: '2023-07-24',
|
||||||
time: '01:15',
|
time: '01:15',
|
||||||
|
@ -249,7 +254,7 @@ describe('Datetime Transformer', () => {
|
||||||
expect(time).toBe('00:15');
|
expect(time).toBe('00:15');
|
||||||
});
|
});
|
||||||
it('should return given time to utc time if frequency is punctual', () => {
|
it('should return given time to utc time if frequency is punctual', () => {
|
||||||
const time: string = datetimeTransformer.time(
|
const time: string = inputDatetimeTransformer.time(
|
||||||
{
|
{
|
||||||
date: '2023-07-24',
|
date: '2023-07-24',
|
||||||
time: '01:15',
|
time: '01:15',
|
|
@ -54,6 +54,54 @@ describe('Time Converter', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('utcStringTimeToLocalStringTime', () => {
|
||||||
|
it('should convert a utc time to a paris time', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringTimeToLocalStringTime(
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBe('08:00');
|
||||||
|
});
|
||||||
|
it('should return undefined if time is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcTime = '27:00';
|
||||||
|
const parisTime = timeConverter.utcStringTimeToLocalStringTime(
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if time is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcTime = undefined;
|
||||||
|
const parisTime = timeConverter.utcStringTimeToLocalStringTime(
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if timezone is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringTimeToLocalStringTime(
|
||||||
|
utcTime,
|
||||||
|
'Foo/Bar',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if timezone is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringTimeToLocalStringTime(
|
||||||
|
utcTime,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('localStringDateTimeToUtcDate', () => {
|
describe('localStringDateTimeToUtcDate', () => {
|
||||||
it('should convert a summer paris date and time to a utc date', () => {
|
it('should convert a summer paris date and time to a utc date', () => {
|
||||||
const timeConverter: TimeConverter = new TimeConverter();
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
@ -111,6 +159,28 @@ describe('Time Converter', () => {
|
||||||
);
|
);
|
||||||
expect(utcDate.toISOString()).toBe('2023-02-03T01:00:00.000Z');
|
expect(utcDate.toISOString()).toBe('2023-02-03T01:00:00.000Z');
|
||||||
});
|
});
|
||||||
|
it('should return undefined if date is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const parisDate = '2023-06-32';
|
||||||
|
const parisTime = '08:00';
|
||||||
|
const utcDate = timeConverter.localStringDateTimeToUtcDate(
|
||||||
|
parisDate,
|
||||||
|
parisTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(utcDate).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if date is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const parisDate = undefined;
|
||||||
|
const parisTime = '08:00';
|
||||||
|
const utcDate = timeConverter.localStringDateTimeToUtcDate(
|
||||||
|
parisDate,
|
||||||
|
parisTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(utcDate).toBeUndefined();
|
||||||
|
});
|
||||||
it('should return undefined if time is invalid', () => {
|
it('should return undefined if time is invalid', () => {
|
||||||
const timeConverter: TimeConverter = new TimeConverter();
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
const parisDate = '2023-06-22';
|
const parisDate = '2023-06-22';
|
||||||
|
@ -157,7 +227,132 @@ describe('Time Converter', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('utcBaseDayFromTime', () => {
|
describe('utcStringDateTimeToLocalIsoString', () => {
|
||||||
|
it('should convert a utc string date and time to a summer paris date isostring', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-22';
|
||||||
|
const utcTime = '10:00';
|
||||||
|
const localIsoString = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(localIsoString).toBe('2023-06-22T12:00:00.000+02:00');
|
||||||
|
});
|
||||||
|
it('should convert a utc string date and time to a winter paris date isostring', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-02-02';
|
||||||
|
const utcTime = '10:00';
|
||||||
|
const localIsoString = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(localIsoString).toBe('2023-02-02T11:00:00.000+01:00');
|
||||||
|
});
|
||||||
|
it('should convert a utc string date and time to a summer paris date isostring without dst', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-22';
|
||||||
|
const utcTime = '10:00';
|
||||||
|
const localIsoString = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
expect(localIsoString).toBe('2023-06-22T11:00:00.000+01:00');
|
||||||
|
});
|
||||||
|
it('should convert a utc date to a tonga date isostring', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-02-01';
|
||||||
|
const utcTime = '23:00';
|
||||||
|
const localIsoString = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Pacific/Tongatapu',
|
||||||
|
);
|
||||||
|
expect(localIsoString).toBe('2023-02-02T12:00:00.000+13:00');
|
||||||
|
});
|
||||||
|
it('should convert a utc date to a papeete date isostring', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-02-03';
|
||||||
|
const utcTime = '01:00';
|
||||||
|
const localIsoString = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Pacific/Tahiti',
|
||||||
|
);
|
||||||
|
expect(localIsoString).toBe('2023-02-02T15:00:00.000-10:00');
|
||||||
|
});
|
||||||
|
it('should return undefined if date is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-32';
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if date is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = undefined;
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if time is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-22';
|
||||||
|
const utcTime = '27:00';
|
||||||
|
const parisTime = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if time is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-22';
|
||||||
|
const utcTime = undefined;
|
||||||
|
const parisTime = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Europe/Paris',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if timezone is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-22';
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
'Foo/Bar',
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if timezone is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
const utcDate = '2023-06-22';
|
||||||
|
const utcTime = '07:00';
|
||||||
|
const parisTime = timeConverter.utcStringDateTimeToLocalIsoString(
|
||||||
|
utcDate,
|
||||||
|
utcTime,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
expect(parisTime).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('utcUnixEpochDayFromTime', () => {
|
||||||
it('should get the utc day of paris at 12:00', () => {
|
it('should get the utc day of paris at 12:00', () => {
|
||||||
const timeConverter: TimeConverter = new TimeConverter();
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
expect(
|
expect(
|
||||||
|
@ -201,4 +396,49 @@ describe('Time Converter', () => {
|
||||||
).toBeUndefined();
|
).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('localUnixEpochDayFromTime', () => {
|
||||||
|
it('should get the day of paris at 12:00 utc', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime('12:00', 'Europe/Paris'),
|
||||||
|
).toBe(4);
|
||||||
|
});
|
||||||
|
it('should get the day of paris at 23:00 utc', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime('23:00', 'Europe/Paris'),
|
||||||
|
).toBe(5);
|
||||||
|
});
|
||||||
|
it('should get the day of papeete at 05:00 utc', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime('05:00', 'Pacific/Tahiti'),
|
||||||
|
).toBe(3);
|
||||||
|
});
|
||||||
|
it('should return undefined if time is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime('28:00', 'Europe/Paris'),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if time is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime(undefined, 'Europe/Paris'),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if timezone is invalid', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime('12:00', 'Foo/Bar'),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should return undefined if timezone is undefined', () => {
|
||||||
|
const timeConverter: TimeConverter = new TimeConverter();
|
||||||
|
expect(
|
||||||
|
timeConverter.localUnixEpochDayFromTime('12:00', undefined),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
|
||||||
import { intToFrequency } from '@modules/ad/interface/grpc-controllers/dtos/transformers/int-to-frequency';
|
|
||||||
|
|
||||||
describe('frequency mapping', () => {
|
|
||||||
it('should return punctual if frequency is 1', () => {
|
|
||||||
expect(intToFrequency(1)).toBe(Frequency.PUNCTUAL);
|
|
||||||
});
|
|
||||||
it('should return recurrent if frequency is 2', () => {
|
|
||||||
expect(intToFrequency(2)).toBe(Frequency.RECURRENT);
|
|
||||||
});
|
|
||||||
it('should throw an error if frequency is unknown', () => {
|
|
||||||
expect(() => intToFrequency(0)).toThrow();
|
|
||||||
expect(() => intToFrequency(3)).toThrow();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,14 +0,0 @@
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue