Files
backend/src/modules/investments/income/income-period.spec.ts
T
codex-bot 31b0e15579
Backend verify / commits (push) Skipped
Backend verify / security (push) Successful in 13s
Backend verify / verify (push) Failing after 7m1s
feat: unify income payment cards and drop period comparisons (WealthLedger/main#33) (#83)
feat: unify income payment cards and drop period comparisons (WealthLedger/main#33)
2026-10-13 18:16:46 +03:00

70 lines
2.4 KiB
TypeScript

import { BadRequestException } from '@nestjs/common';
import { dateOnlyBounds } from '../investment-calendar';
import { planIncomePeriod, rangeBuckets } from './income-period';
describe('income period planning', () => {
afterEach(() => jest.useRealTimers());
it('uses the Moscow current month and validates strict inclusive ranges', () => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2026-01-31T22:30:00.000Z'));
expect(planIncomePeriod(undefined, undefined)).toMatchObject({
selected: { from: '2026-02-01', to: '2026-02-01' },
});
for (const [from, to] of [
['2026-02-30', '2026-03-01'],
['2026-03-02', '2026-03-01'],
['2026-01-01', '2027-01-02'],
['2026-01-01', '2026-04-01'],
]) {
expect(() => planIncomePeriod(from, to)).toThrow(BadRequestException);
}
});
it('keeps empty buckets and skips removed comparison ranges', () => {
expect(
rangeBuckets({ from: '2026-01-01', to: '2026-02-15' }, 'week'),
).toHaveLength(7);
expect(planIncomePeriod('2026-03-01', '2026-03-31')).toEqual({
selected: { from: '2026-03-01', to: '2026-03-31' },
granularity: 'day',
});
});
it('accepts multi-year periods and creates monthly buckets for the entire range', () => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2026-09-09T12:00:00Z'));
const plan = planIncomePeriod('2020-01-01', '2025-12-31');
expect(plan.selected).toEqual({ from: '2020-01-01', to: '2025-12-31' });
expect(plan.granularity).toBe('month');
expect(rangeBuckets(plan.selected, plan.granularity)).toHaveLength(72);
});
it('does not send the unfinished Moscow day as a future instant', () => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2026-08-27T21:44:18.510Z'));
expect(dateOnlyBounds({ from: '2026-08-01', to: '2026-08-28' })).toEqual({
from: new Date('2026-07-31T21:00:00.000Z'),
to: new Date('2026-08-27T21:44:18.510Z'),
});
});
it.each([
['2024-02-29', '2024-02-28T21:00:00.000Z', '2024-02-29T21:00:00.000Z'],
['2025-12-31', '2025-12-30T21:00:00.000Z', '2025-12-31T21:00:00.000Z'],
])('maps inclusive %s to one full half-open Moscow day', (date, from, to) => {
expect(
dateOnlyBounds(
{ from: date, to: date },
new Date('2026-01-01T12:00:00Z'),
),
).toEqual({
from: new Date(from),
to: new Date(to),
});
});
});