Browse Source

Preparations

pull/8177/head
Thomas Kaul 23 hours ago
parent
commit
ff4afd71dd
  1. 4
      libs/common/src/lib/dtos/create-account-balance.dto.ts
  2. 31
      libs/common/src/lib/helper.spec.ts
  3. 6
      libs/common/src/lib/helper.ts
  4. 35
      libs/common/src/lib/validator-constraints/is-not-in-the-future.spec.ts
  5. 26
      libs/common/src/lib/validator-constraints/is-not-in-the-future.ts
  6. 11
      libs/common/src/lib/validator-constraints/is-valid-account-balance-date.spec.ts
  7. 22
      libs/common/src/lib/validator-constraints/is-valid-account-balance-date.ts

4
libs/common/src/lib/dtos/create-account-balance.dto.ts

@ -1,4 +1,4 @@
import { IsNotInTheFutureConstraint } from '@ghostfolio/common/validator-constraints/is-not-in-the-future';
import { IsValidAccountBalanceDateConstraint } from '@ghostfolio/common/validator-constraints/is-valid-account-balance-date';
import { IsISO8601, IsNumber, IsUUID, Validate } from 'class-validator';
@ -10,6 +10,6 @@ export class CreateAccountBalanceDto {
balance: number;
@IsISO8601()
@Validate(IsNotInTheFutureConstraint)
@Validate(IsValidAccountBalanceDateConstraint)
date: string;
}

31
libs/common/src/lib/helper.spec.ts

@ -18,6 +18,7 @@ import {
isCurrencySymbol,
isDarkColorScheme,
isSplitRatio,
isValidAccountBalanceDate,
isValidCurrencyCode,
isValidCustomAssetProfileSymbol,
isValidDateAfter1970,
@ -558,6 +559,36 @@ describe('Helper', () => {
});
});
describe('Is valid account balance date', () => {
beforeAll(() => {
jest.useFakeTimers().setSystemTime(new Date('2026-09-03T23:30:00.000Z'));
});
afterAll(() => {
jest.useRealTimers();
});
it('Accepts a date in the past', () => {
expect(isValidAccountBalanceDate('2026-09-02')).toBe(true);
});
it('Accepts the current date', () => {
expect(isValidAccountBalanceDate('2026-09-03')).toBe(true);
});
it('Accepts the current date of a user in a time zone ahead of the instance', () => {
expect(isValidAccountBalanceDate('2026-09-04')).toBe(true);
});
it('Refuses a date in the future', () => {
expect(isValidAccountBalanceDate('2026-09-05')).toBe(false);
});
it('Refuses a date which is not valid', () => {
expect(isValidAccountBalanceDate('2026-02-30')).toBe(false);
});
});
describe('Is valid currency code', () => {
it('Currency code in lower case', () => {
expect(isValidCurrencyCode('usd')).toEqual(false);

6
libs/common/src/lib/helper.ts

@ -735,6 +735,12 @@ export function isUserSettingOfAuthenticatedUser(aKey: string) {
);
}
export function isValidAccountBalanceDate(aDate: string) {
const date = parseISO(aDate);
return isValid(date) && !isAccountBalanceInFuture({ date: resetHours(date) });
}
export function isValidCurrencyCode(aCurrency: string) {
if (!aCurrency) {
return false;

35
libs/common/src/lib/validator-constraints/is-not-in-the-future.spec.ts

@ -1,35 +0,0 @@
import { IsNotInTheFutureConstraint } from './is-not-in-the-future';
describe('IsNotInTheFutureConstraint', () => {
const constraint = new IsNotInTheFutureConstraint();
beforeAll(() => {
jest.useFakeTimers().setSystemTime(new Date('2026-09-03T23:30:00.000Z'));
});
afterAll(() => {
jest.useRealTimers();
});
it('Accepts a date in the past', () => {
expect(constraint.validate('2026-09-02')).toBe(true);
});
it('Accepts the current date', () => {
expect(constraint.validate('2026-09-03')).toBe(true);
});
it('Accepts the current date of a user in a time zone ahead of the instance', () => {
expect(constraint.validate('2026-09-04')).toBe(true);
});
it('Refuses a date in the future', () => {
expect(constraint.validate('2026-09-05')).toBe(false);
});
it('Leaves a value which is not a string to IsISO8601', () => {
expect(constraint.validate(undefined)).toBe(true);
expect(constraint.validate(null)).toBe(true);
expect(constraint.validate(123)).toBe(true);
});
});

26
libs/common/src/lib/validator-constraints/is-not-in-the-future.ts

@ -1,26 +0,0 @@
import {
isAccountBalanceInFuture,
resetHours
} from '@ghostfolio/common/helper';
import {
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator';
import { parseISO } from 'date-fns';
@ValidatorConstraint({ name: 'isNotInTheFuture' })
export class IsNotInTheFutureConstraint implements ValidatorConstraintInterface {
public defaultMessage() {
return '$property must not be a date in the future';
}
public validate(aDate: unknown) {
// IsISO8601 refuses a value which is not a string
if (typeof aDate !== 'string') {
return true;
}
return !isAccountBalanceInFuture({ date: resetHours(parseISO(aDate)) });
}
}

11
libs/common/src/lib/validator-constraints/is-valid-account-balance-date.spec.ts

@ -0,0 +1,11 @@
import { IsValidAccountBalanceDateConstraint } from './is-valid-account-balance-date';
describe('IsValidAccountBalanceDateConstraint', () => {
const constraint = new IsValidAccountBalanceDateConstraint();
it('Leaves a value which is not a string to IsISO8601', () => {
expect(constraint.validate(undefined)).toBe(true);
expect(constraint.validate(null)).toBe(true);
expect(constraint.validate(123)).toBe(true);
});
});

22
libs/common/src/lib/validator-constraints/is-valid-account-balance-date.ts

@ -0,0 +1,22 @@
import { isValidAccountBalanceDate } from '@ghostfolio/common/helper';
import {
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator';
@ValidatorConstraint({ name: 'isValidAccountBalanceDate' })
export class IsValidAccountBalanceDateConstraint implements ValidatorConstraintInterface {
public defaultMessage() {
return '$property must be a valid date which is not in the future';
}
public validate(aDate: unknown) {
// IsISO8601 refuses a value which is not a string
if (typeof aDate !== 'string') {
return true;
}
return isValidAccountBalanceDate(aDate);
}
}
Loading…
Cancel
Save