316e5def72
Update Expo and React dependencies to compatible versions. Create a custom Metro config to resolve module conflicts in the workspace and map Jest modules to local node_modules. Add a SharedArrayBuffer polyfill for older runtimes and introduce an adapter for expo-notifications to abstract direct imports.
182 lines
6.0 KiB
TypeScript
182 lines
6.0 KiB
TypeScript
// Tests for notification service
|
|
// Mock notification adapter before importing
|
|
jest.mock('../services/expoNotifications', () => ({
|
|
setNotificationHandler: jest.fn(),
|
|
requestPermissionsAsync: jest.fn().mockResolvedValue({ status: 'granted' }),
|
|
scheduleNotificationAsync: jest.fn().mockResolvedValue({ identifier: 'mock-id' }),
|
|
cancelScheduledNotificationAsync: jest.fn().mockResolvedValue(undefined),
|
|
getAllScheduledNotificationsAsync: jest.fn().mockResolvedValue([]),
|
|
cancelAllScheduledNotificationsAsync: jest.fn().mockResolvedValue(undefined),
|
|
SchedulableTriggerInputTypes: {
|
|
DATE: 'date',
|
|
CALENDAR: 'calendar',
|
|
DAILY: 'daily',
|
|
WEEKLY: 'weekly',
|
|
MONTHLY: 'monthly',
|
|
YEARLY: 'yearly',
|
|
TIME_INTERVAL: 'timeInterval',
|
|
},
|
|
}));
|
|
|
|
import { calculateLeaveByTime } from '../services/notifications';
|
|
import type { Event, Journey } from '@timetoleave/core';
|
|
|
|
describe('notifications service', () => {
|
|
describe('calculateLeaveByTime', () => {
|
|
it('should calculate leave-by time from event time minus arrival buffer minus reminder buffer', () => {
|
|
const event: Event = {
|
|
id: 'test-1',
|
|
title: 'Test Event',
|
|
destination: 'Test Destination',
|
|
eventTime: new Date('2025-01-01T10:00:00Z'),
|
|
source: 'manual',
|
|
};
|
|
|
|
const leaveByTime = calculateLeaveByTime(event, [], 30, 5);
|
|
|
|
// Leave-by time should be 30 minutes before event time
|
|
// (arrival buffer) minus 5 minutes reminder buffer
|
|
// = event time - 35 minutes total
|
|
const expectedTime = new Date('2025-01-01T09:25:00Z');
|
|
expect(leaveByTime.getTime()).toBe(expectedTime.getTime());
|
|
});
|
|
|
|
it('should use earliest journey departure time if available', () => {
|
|
const event: Event = {
|
|
id: 'test-1',
|
|
title: 'Test Event',
|
|
destination: 'Test Destination',
|
|
eventTime: new Date('2025-01-01T10:00:00Z'),
|
|
source: 'manual',
|
|
};
|
|
|
|
const journeys: Journey[] = [
|
|
{
|
|
id: 'journey-1',
|
|
sD: new Date('2025-01-01T08:00:00Z'),
|
|
rD: new Date('2025-01-01T08:00:00Z'),
|
|
sA: new Date('2025-01-01T09:00:00Z'),
|
|
rA: new Date('2025-01-01T09:00:00Z'),
|
|
delay: 0,
|
|
platform: '1',
|
|
changes: 0,
|
|
trains: ['S1'],
|
|
cancelled: false,
|
|
},
|
|
{
|
|
id: 'journey-2',
|
|
sD: new Date('2025-01-01T07:00:00Z'),
|
|
rD: new Date('2025-01-01T07:00:00Z'),
|
|
sA: new Date('2025-01-01T08:00:00Z'),
|
|
rA: new Date('2025-01-01T08:00:00Z'),
|
|
delay: 0,
|
|
platform: '2',
|
|
changes: 1,
|
|
trains: ['U3', 'S2'],
|
|
cancelled: false,
|
|
},
|
|
];
|
|
|
|
const leaveByTime = calculateLeaveByTime(event, journeys, 30, 5);
|
|
|
|
// Should use earliest non-cancelled journey (journey-2 at 07:00)
|
|
// Leave-by time = journey departure (07:00) - reminder buffer (5 min)
|
|
const expectedTime = new Date('2025-01-01T06:55:00Z');
|
|
expect(leaveByTime.getTime()).toBe(expectedTime.getTime());
|
|
});
|
|
|
|
it('should skip cancelled journeys', () => {
|
|
const event: Event = {
|
|
id: 'test-1',
|
|
title: 'Test Event',
|
|
destination: 'Test Destination',
|
|
eventTime: new Date('2025-01-01T10:00:00Z'),
|
|
source: 'manual',
|
|
};
|
|
|
|
const journeys: Journey[] = [
|
|
{
|
|
id: 'journey-1',
|
|
sD: new Date('2025-01-01T08:00:00Z'),
|
|
rD: new Date('2025-01-01T08:00:00Z'),
|
|
sA: new Date('2025-01-01T09:00:00Z'),
|
|
rA: new Date('2025-01-01T09:00:00Z'),
|
|
delay: 0,
|
|
platform: '1',
|
|
changes: 0,
|
|
trains: ['S1'],
|
|
cancelled: true,
|
|
},
|
|
{
|
|
id: 'journey-2',
|
|
sD: new Date('2025-01-01T07:00:00Z'),
|
|
rD: new Date('2025-01-01T07:00:00Z'),
|
|
sA: new Date('2025-01-01T08:00:00Z'),
|
|
rA: new Date('2025-01-01T08:00:00Z'),
|
|
delay: 0,
|
|
platform: '2',
|
|
changes: 1,
|
|
trains: ['U3', 'S2'],
|
|
cancelled: false,
|
|
},
|
|
];
|
|
|
|
const leaveByTime = calculateLeaveByTime(event, journeys, 30, 5);
|
|
|
|
// Should use journey-2 since journey-1 is cancelled
|
|
// Leave-by time = journey departure (07:00) - reminder buffer (5 min)
|
|
const expectedTime = new Date('2025-01-01T06:55:00Z');
|
|
expect(leaveByTime.getTime()).toBe(expectedTime.getTime());
|
|
});
|
|
|
|
it('should fall back to event time minus buffer when all journeys cancelled', () => {
|
|
const event: Event = {
|
|
id: 'test-1',
|
|
title: 'Test Event',
|
|
destination: 'Test Destination',
|
|
eventTime: new Date('2025-01-01T10:00:00Z'),
|
|
source: 'manual',
|
|
};
|
|
|
|
const journeys: Journey[] = [
|
|
{
|
|
id: 'journey-1',
|
|
sD: new Date('2025-01-01T08:00:00Z'),
|
|
rD: new Date('2025-01-01T08:00:00Z'),
|
|
sA: new Date('2025-01-01T09:00:00Z'),
|
|
rA: new Date('2025-01-01T09:00:00Z'),
|
|
delay: 0,
|
|
platform: '1',
|
|
changes: 0,
|
|
trains: ['S1'],
|
|
cancelled: true,
|
|
},
|
|
];
|
|
|
|
const leaveByTime = calculateLeaveByTime(event, journeys, 30, 5);
|
|
|
|
// All journeys cancelled, fall back to event time minus arrival buffer minus reminder buffer
|
|
// = 10:00 - 30 min - 5 min = 09:25
|
|
const expectedTime = new Date('2025-01-01T09:25:00Z');
|
|
expect(leaveByTime.getTime()).toBe(expectedTime.getTime());
|
|
});
|
|
|
|
it('should handle zero buffer correctly', () => {
|
|
const event: Event = {
|
|
id: 'test-1',
|
|
title: 'Test Event',
|
|
destination: 'Test Destination',
|
|
eventTime: new Date('2025-01-01T10:00:00Z'),
|
|
source: 'manual',
|
|
};
|
|
|
|
const leaveByTime = calculateLeaveByTime(event, [], 30, 0);
|
|
|
|
// With zero reminder buffer, leave-by time = event time - arrival buffer
|
|
// = 10:00 AM - 30 minutes = 09:30 AM
|
|
const expectedTime = new Date('2025-01-01T09:30:00Z');
|
|
expect(leaveByTime.getTime()).toBe(expectedTime.getTime());
|
|
});
|
|
});
|
|
});
|