Tonight
This commit is contained in:
parent
28323f145e
commit
94f9c0d594
76 changed files with 3238 additions and 1230 deletions
100
frontend/src/hooks/useMapData.test.ts
Normal file
100
frontend/src/hooks/useMapData.test.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import { act, renderHook } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { useMapData } from './useMapData';
|
||||
import type { ApiResponse, Bounds, ViewChangeParams } from '../types';
|
||||
|
||||
vi.mock('../lib/pocketbase', () => ({
|
||||
default: { authStore: { isValid: false, token: '' } },
|
||||
}));
|
||||
|
||||
function response(features: ApiResponse['features']): Response {
|
||||
return new Response(JSON.stringify({ features }), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
function viewChange(bounds: Bounds): ViewChangeParams {
|
||||
return {
|
||||
resolution: 8,
|
||||
bounds,
|
||||
zoom: 10,
|
||||
latitude: (bounds.south + bounds.north) / 2,
|
||||
longitude: (bounds.west + bounds.east) / 2,
|
||||
};
|
||||
}
|
||||
|
||||
async function flushPromises() {
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
}
|
||||
|
||||
describe('useMapData', () => {
|
||||
const requests: Array<{ url: string; resolve: (response: Response) => void }> = [];
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
requests.length = 0;
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn((url: string | URL | Request) => {
|
||||
return new Promise<Response>((resolve) => {
|
||||
requests.push({ url: String(url), resolve });
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('ignores a stale map response after the view has already changed', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMapData({
|
||||
filters: {},
|
||||
features: [],
|
||||
viewFeature: null,
|
||||
activeFeature: null,
|
||||
pinnedFeature: null,
|
||||
travelTimeEntries: [],
|
||||
})
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
result.current.handleViewChange(
|
||||
viewChange({ south: 1, west: 1, north: 2, east: 2 })
|
||||
);
|
||||
});
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(150);
|
||||
});
|
||||
expect(requests).toHaveLength(1);
|
||||
|
||||
await act(async () => {
|
||||
result.current.handleViewChange(
|
||||
viewChange({ south: 3, west: 3, north: 4, east: 4 })
|
||||
);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
requests[0].resolve(response([{ h3: 'old', count: 99, lat: 1.5, lon: 1.5 }]));
|
||||
await flushPromises();
|
||||
});
|
||||
expect(result.current.data).toEqual([]);
|
||||
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(150);
|
||||
});
|
||||
expect(requests).toHaveLength(2);
|
||||
|
||||
await act(async () => {
|
||||
requests[1].resolve(response([{ h3: 'new', count: 7, lat: 3.5, lon: 3.5 }]));
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
expect(result.current.data).toEqual([{ h3: 'new', count: 7, lat: 3.5, lon: 3.5 }]);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue