Files
gruperly/apps/backend/test/home-scheduler.test.ts
Jose Selesan f1e0fc5aae feat(home): implement home summary feature with routes and use case
- Added home routes and corresponding route handler for fetching home summary.
- Created GetHomeSummary use case to aggregate user data including groups, attendees, and upcoming payments.
- Introduced HomeSummaryDto and related schemas for data validation.
- Implemented nextClassOccurrence function to determine the next class based on user timezone.
- Added tests for home summary functionality and next class occurrence logic.
2026-09-23 10:35:24 -03:00

112 lines
2.9 KiB
TypeScript

import { describe, expect, it } from 'bun:test';
import { CLASS_WINDOW_HOURS, nextClassOccurrence } from '@/modules/home/lib/scheduler';
const TZ = 'America/Mexico_City';
describe('nextClassOccurrence', () => {
it('devuelve la próxima clase de hoy cuando aún no arrancó', () => {
const now = new Date('2026-09-23T18:00:00.000Z'); // miércoles 12:00 hora CDMX
const result = nextClassOccurrence({
days: ['WEDNESDAY'],
time: '18:00',
now,
timeZone: TZ,
});
expect(result).toEqual({
occurrenceAt: new Date('2026-09-24T00:00:00.000Z'),
isNow: false,
});
});
it('marca en curso si la clase arrancó hace menos de la ventana', () => {
const now = new Date('2026-09-24T01:00:00.000Z'); // miércoles 19:00 hora CDMX (1 h tras la clase)
const result = nextClassOccurrence({
days: ['WEDNESDAY'],
time: '18:00',
now,
timeZone: TZ,
});
expect(result).toEqual({
occurrenceAt: new Date('2026-09-24T00:00:00.000Z'),
isNow: true,
});
});
it('salta a la próxima semana si la clase ya pasó la ventana', () => {
const now = new Date('2026-09-24T03:00:00.000Z'); // miércoles 21:00 hora CDMX (3 h tras la clase)
const result = nextClassOccurrence({
days: ['WEDNESDAY'],
time: '18:00',
now,
timeZone: TZ,
});
expect(result).toEqual({
occurrenceAt: new Date('2026-10-01T00:00:00.000Z'),
isNow: false,
});
});
it('elige la ocurrencia más próxima entre varios días', () => {
const now = new Date('2026-09-23T18:00:00.000Z'); // miércoles 12:00 hora CDMX
const result = nextClassOccurrence({
days: ['MONDAY', 'WEDNESDAY', 'FRIDAY'],
time: '18:00',
now,
timeZone: TZ,
});
expect(result).toEqual({
occurrenceAt: new Date('2026-09-24T00:00:00.000Z'),
isNow: false,
});
});
it('cruza de mes sin problema', () => {
const now = new Date('2026-09-29T18:00:00.000Z'); // martes 12:00 hora CDMX (último día de septiembre es miércoles 30)
const result = nextClassOccurrence({
days: ['THURSDAY'],
time: '09:00',
now,
timeZone: TZ,
});
expect(result).toEqual({
occurrenceAt: new Date('2026-10-01T15:00:00.000Z'),
isNow: false,
});
});
it('devuelve null si no hay días de clase', () => {
const result = nextClassOccurrence({
days: [],
time: '18:00',
now: new Date('2026-09-23T18:00:00.000Z'),
timeZone: TZ,
});
expect(result).toBeNull();
});
it('devuelve null si la hora es inválida', () => {
const result = nextClassOccurrence({
days: ['WEDNESDAY'],
time: '99:99',
now: new Date('2026-09-23T18:00:00.000Z'),
timeZone: TZ,
});
expect(result).toBeNull();
});
it('expone el tamaño de la ventana de "en curso"', () => {
expect(CLASS_WINDOW_HOURS).toBeGreaterThan(0);
});
});