115 lines
3.3 KiB
TypeScript
115 lines
3.3 KiB
TypeScript
import { act, renderHook } from '@testing-library/react';
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import { travelFieldKey, useTravelTime, type TravelTimeEntry } from './useTravelTime';
|
|
|
|
describe('useTravelTime', () => {
|
|
it('creates backend field keys from mode and destination slug', () => {
|
|
expect(
|
|
travelFieldKey({
|
|
mode: 'transit',
|
|
slug: 'kings-cross',
|
|
label: 'Kings Cross',
|
|
timeRange: [0, 45],
|
|
useBest: true,
|
|
})
|
|
).toBe('tt_transit_kings-cross');
|
|
});
|
|
|
|
it('adds, updates, toggles, and removes travel-time entries', () => {
|
|
const { result } = renderHook(() => useTravelTime());
|
|
|
|
act(() => result.current.handleAddEntry('transit'));
|
|
expect(result.current.entries).toEqual([
|
|
{ mode: 'transit', slug: '', label: '', timeRange: null, useBest: false },
|
|
]);
|
|
expect(result.current.activeEntries).toEqual([]);
|
|
|
|
act(() => result.current.handleSetDestination(0, 'bank', 'Bank'));
|
|
expect(result.current.entries[0]).toMatchObject({
|
|
slug: 'bank',
|
|
label: 'Bank',
|
|
timeRange: [0, 120],
|
|
});
|
|
expect(result.current.activeEntries).toHaveLength(1);
|
|
|
|
act(() => result.current.handleTimeRangeChange(0, [10, 35]));
|
|
expect(result.current.entries[0].timeRange).toEqual([10, 35]);
|
|
|
|
act(() => result.current.handleToggleBest(0));
|
|
expect(result.current.entries[0].useBest).toBe(true);
|
|
|
|
act(() => result.current.handleRemoveEntry(0));
|
|
expect(result.current.entries).toEqual([]);
|
|
});
|
|
|
|
it('replaces entries wholesale for AI-generated filters', () => {
|
|
const initial: TravelTimeEntry = {
|
|
mode: 'walking',
|
|
slug: 'old',
|
|
label: 'Old',
|
|
timeRange: [0, 20],
|
|
useBest: false,
|
|
};
|
|
const replacement: TravelTimeEntry = {
|
|
mode: 'car',
|
|
slug: 'new',
|
|
label: 'New',
|
|
timeRange: [5, 30],
|
|
useBest: false,
|
|
};
|
|
const { result } = renderHook(() => useTravelTime({ entries: [initial] }));
|
|
|
|
act(() => result.current.handleSetEntries([replacement]));
|
|
|
|
expect(result.current.entries).toEqual([replacement]);
|
|
expect(result.current.activeEntries).toEqual([replacement]);
|
|
});
|
|
|
|
it('deduplicates initial and replacement entries using the tightest range', () => {
|
|
const wide: TravelTimeEntry = {
|
|
mode: 'transit',
|
|
slug: 'bank-tube-station',
|
|
label: 'Bank',
|
|
timeRange: [0, 60],
|
|
useBest: false,
|
|
};
|
|
const tight: TravelTimeEntry = {
|
|
mode: 'transit',
|
|
slug: 'bank-tube-station',
|
|
label: 'Bank',
|
|
timeRange: [10, 45],
|
|
useBest: false,
|
|
};
|
|
const replacement: TravelTimeEntry = {
|
|
mode: 'transit',
|
|
slug: 'bank-tube-station',
|
|
label: 'Bank',
|
|
timeRange: [20, 40],
|
|
useBest: true,
|
|
};
|
|
const { result } = renderHook(() => useTravelTime({ entries: [wide, tight] }));
|
|
|
|
expect(result.current.entries).toEqual([
|
|
{
|
|
mode: 'transit',
|
|
slug: 'bank-tube-station',
|
|
label: 'Bank',
|
|
timeRange: [10, 45],
|
|
useBest: false,
|
|
},
|
|
]);
|
|
|
|
act(() => result.current.handleSetEntries([wide, replacement]));
|
|
|
|
expect(result.current.entries).toEqual([
|
|
{
|
|
mode: 'transit',
|
|
slug: 'bank-tube-station',
|
|
label: 'Bank',
|
|
timeRange: [20, 40],
|
|
useBest: true,
|
|
},
|
|
]);
|
|
});
|
|
});
|