mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
151 lines
6.3 KiB
TypeScript
151 lines
6.3 KiB
TypeScript
/**
|
|
* FE-FERRATA-MAPLAYER-001 to FE-FERRATA-MAPLAYER-008: the via ferrata layer as
|
|
* one map surface holds it: off by default, the area the map reports, the
|
|
* trip's area to prefetch, the ferratas grouped from OSM's segments with their
|
|
* count in view, and the card a click opens.
|
|
*
|
|
* useTripFerratas is mocked: what it asks the server is its own suite's
|
|
* subject. This one checks what the layer hands it (the view, whether it is on
|
|
* at all, the trip's area) and what it hands the map back.
|
|
*/
|
|
import { act, renderHook } from '@testing-library/react';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import type { Ferrata, FerrataBbox } from '@trek/shared';
|
|
|
|
import { ferrataAreaOf, useFerrataMapLayer } from './useFerrataMapLayer';
|
|
import { useTripFerratas } from './useTripFerratas';
|
|
|
|
vi.mock('./useTripFerratas', () => ({ useTripFerratas: vi.fn() }));
|
|
|
|
const BOX: FerrataBbox = { south: 46.5, west: 11.7, north: 46.6, east: 11.9 };
|
|
const OTHER: FerrataBbox = { south: 47.4, west: 11.6, north: 47.5, east: 11.8 };
|
|
|
|
const segment = (id: number, lat: number): Ferrata => ({
|
|
id: `way/${id}`,
|
|
name: 'Via delle Trincee',
|
|
grade: { raw: String(id), level: id, plus: null },
|
|
routeName: null,
|
|
geometry: [
|
|
[lat, 11.8],
|
|
[lat + 0.001, 11.8],
|
|
],
|
|
osmUrl: `https://www.openstreetmap.org/way/${id}`,
|
|
});
|
|
// Two touching segments of one ferrata.
|
|
const LOWER = segment(2, 46.52);
|
|
const UPPER = segment(4, 46.521);
|
|
|
|
const lastCall = () => vi.mocked(useTripFerratas).mock.lastCall;
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(useTripFerratas).mockReturnValue({ ferratas: [LOWER, UPPER], status: 'ready', truncated: false });
|
|
});
|
|
|
|
describe('useFerrataMapLayer', () => {
|
|
it('FE-FERRATA-MAPLAYER-001: starts off, so nothing is asked for', () => {
|
|
const { result } = renderHook(() => useFerrataMapLayer(7));
|
|
expect(result.current.layer.active).toBe(false);
|
|
expect(result.current.layer.count).toBe(0);
|
|
expect(result.current.selected).toBeNull();
|
|
expect(lastCall()).toEqual([7, null, false, null, []]);
|
|
});
|
|
|
|
it('FE-FERRATA-MAPLAYER-002: an area reported while off is remembered without a re-render, and used once it is on', () => {
|
|
const { result } = renderHook(() => useFerrataMapLayer(7));
|
|
const renders = vi.mocked(useTripFerratas).mock.calls.length;
|
|
|
|
act(() => result.current.onViewportChange(BOX));
|
|
expect(vi.mocked(useTripFerratas).mock.calls.length).toBe(renders);
|
|
|
|
act(() => result.current.layer.onToggle());
|
|
expect(result.current.layer.active).toBe(true);
|
|
expect(lastCall()?.slice(0, 3)).toEqual([7, BOX, true]);
|
|
});
|
|
|
|
it('FE-FERRATA-MAPLAYER-003: while on, every new area reaches the request', () => {
|
|
const { result } = renderHook(() => useFerrataMapLayer(7));
|
|
act(() => result.current.layer.onToggle());
|
|
act(() => result.current.onViewportChange(OTHER));
|
|
expect(lastCall()?.slice(0, 3)).toEqual([7, OTHER, true]);
|
|
});
|
|
|
|
it("FE-FERRATA-MAPLAYER-004: hands the trip's area around its lines to the loader", () => {
|
|
const lines = [
|
|
[[46.5, 11.7]],
|
|
[
|
|
[46.7, 11.6],
|
|
[46.6, 11.9],
|
|
],
|
|
] as Array<Array<[number, number]>>;
|
|
renderHook(() => useFerrataMapLayer(7, lines));
|
|
expect(lastCall()?.[3]).toEqual({ south: 46.5, west: 11.6, north: 46.7, east: 11.9 });
|
|
expect(ferrataAreaOf([])).toBeNull();
|
|
expect(ferrataAreaOf([[[Number.NaN, 1]]])).toBeNull();
|
|
});
|
|
|
|
it('FE-FERRATA-MAPLAYER-005: groups the segments into one ferrata and counts the ferratas in view', () => {
|
|
const { result } = renderHook(() => useFerrataMapLayer(7));
|
|
act(() => result.current.onViewportChange(BOX));
|
|
act(() => result.current.layer.onToggle());
|
|
expect(result.current.layer.groups).toHaveLength(1);
|
|
expect(result.current.layer.groups[0]?.segments).toEqual([LOWER, UPPER]);
|
|
expect(result.current.layer.count).toBe(1);
|
|
|
|
act(() => result.current.onViewportChange(OTHER));
|
|
expect(result.current.layer.count).toBe(0);
|
|
// Out of view, still drawn.
|
|
expect(result.current.layer.groups).toHaveLength(1);
|
|
});
|
|
|
|
it('FE-FERRATA-MAPLAYER-006: a click opens the whole ferrata in the card, highlighted, and close shuts it', () => {
|
|
const { result } = renderHook(() => useFerrataMapLayer(7));
|
|
act(() => result.current.layer.onToggle());
|
|
const group = result.current.layer.groups[0];
|
|
if (!group) throw new Error('no group');
|
|
|
|
act(() => result.current.layer.onSelect(group, UPPER, { lat: 46.521, lng: 11.8 }));
|
|
expect(result.current.selected?.group.id).toBe(group.id);
|
|
expect(result.current.selected?.segment).toBe(UPPER);
|
|
expect(result.current.layer.selectedId).toBe(group.id);
|
|
|
|
act(() => result.current.close());
|
|
expect(result.current.selected).toBeNull();
|
|
expect(result.current.layer.selectedId).toBeNull();
|
|
});
|
|
|
|
it('FE-FERRATA-MAPLAYER-007: the card follows its ferrata when more of its segments load', () => {
|
|
const { result, rerender } = renderHook(() => useFerrataMapLayer(7));
|
|
act(() => result.current.layer.onToggle());
|
|
const group = result.current.layer.groups[0];
|
|
if (!group) throw new Error('no group');
|
|
act(() => result.current.layer.onSelect(group, UPPER, { lat: 46.521, lng: 11.8 }));
|
|
|
|
// A lower way loads and joins the ferrata; its id is now the group's.
|
|
const lowest = segment(1, 46.519);
|
|
vi.mocked(useTripFerratas).mockReturnValue({ ferratas: [LOWER, UPPER, lowest], status: 'ready', truncated: false });
|
|
rerender();
|
|
expect(result.current.selected?.group.segments).toHaveLength(3);
|
|
expect(result.current.selected?.segment).toBe(UPPER);
|
|
expect(result.current.layer.selectedId).toBe('group/way/1');
|
|
});
|
|
|
|
it('FE-FERRATA-MAPLAYER-008: switching the layer off closes the card and stops asking', () => {
|
|
const { result } = renderHook(() => useFerrataMapLayer(7));
|
|
act(() => result.current.layer.onToggle());
|
|
const group = result.current.layer.groups[0];
|
|
if (!group) throw new Error('no group');
|
|
act(() => result.current.layer.onSelect(group, LOWER, { lat: 46.52, lng: 11.8 }));
|
|
|
|
act(() => result.current.layer.onToggle());
|
|
expect(result.current.layer.active).toBe(false);
|
|
expect(result.current.selected).toBeNull();
|
|
expect(lastCall()?.[2]).toBe(false);
|
|
|
|
// On again, the card stays closed until the next click.
|
|
act(() => result.current.layer.onToggle());
|
|
expect(result.current.selected).toBeNull();
|
|
});
|
|
});
|