mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 21:46:49 +00:00
test(tours): the library reads and the forgotten water network, each at the repository
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* `PaddleWaterGraphsRepository` (PAD-11): the water network each paddle
|
||||
* region built for routing, recorded, found by the point it covers, and
|
||||
* forgotten when its file is gone.
|
||||
*/
|
||||
import { PaddleRegions } from '../../../../src/db/entities/PaddleRegions.entity';
|
||||
import { PaddleWaterGraphs } from '../../../../src/db/entities/PaddleWaterGraphs.entity';
|
||||
import type { PaddleRegionsRepository } from '../../../../src/db/repositories/PaddleRegions.repository';
|
||||
import type { PaddleWaterGraphsRepository } from '../../../../src/db/repositories/PaddleWaterGraphs.repository';
|
||||
import { dbNow } from '../../../../src/db/types';
|
||||
import { createSnapshotTestDb } from '../../../helpers/db-mock';
|
||||
import { resetTestDb } from '../../../helpers/test-db';
|
||||
import { createTestOrm, type TestOrm } from '../../../helpers/test-orm';
|
||||
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
const testDb = createSnapshotTestDb();
|
||||
let t: TestOrm;
|
||||
let graphs: PaddleWaterGraphsRepository;
|
||||
let regions: PaddleRegionsRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
t = await createTestOrm(testDb);
|
||||
graphs = t.repo(PaddleWaterGraphs);
|
||||
regions = t.repo(PaddleRegions);
|
||||
});
|
||||
beforeEach(() => {
|
||||
resetTestDb(testDb);
|
||||
t.clear();
|
||||
});
|
||||
afterAll(async () => {
|
||||
await t.close();
|
||||
testDb.close();
|
||||
});
|
||||
|
||||
const box = (min: number, max: number) => ({ min_lat: min, min_lng: min, max_lat: max, max_lng: max });
|
||||
|
||||
async function region(id: string, min: number, max: number, file = `${id}.bin`) {
|
||||
await regions.insertRegion({ id, name: id, boundary: null, ...box(min, max) });
|
||||
await graphs.saveGraph({
|
||||
region_id: id,
|
||||
file,
|
||||
rev: 'r1',
|
||||
bytes: 10,
|
||||
built_at: dbNow(),
|
||||
stats: '{}',
|
||||
...box(min, max),
|
||||
});
|
||||
}
|
||||
|
||||
describe('PaddleWaterGraphsRepository (PAD-11)', () => {
|
||||
it('PWG-001: records a network, replaces it when built again, and lists them by region', async () => {
|
||||
await region('b', 10, 20);
|
||||
await region('a', 0, 5);
|
||||
await graphs.saveGraph({
|
||||
region_id: 'a',
|
||||
file: 'a2.bin',
|
||||
rev: 'r2',
|
||||
bytes: 20,
|
||||
built_at: dbNow(),
|
||||
stats: '{"n":1}',
|
||||
...box(0, 6),
|
||||
});
|
||||
expect((await graphs.list()).map((row) => [row.region_id, row.file, row.rev])).toEqual([
|
||||
['a', 'a2.bin', 'r2'],
|
||||
['b', 'b.bin', 'r1'],
|
||||
]);
|
||||
expect(await graphs.findByRegion('a')).toMatchObject({ file: 'a2.bin', max_lat: 6 });
|
||||
expect(await graphs.findByRegion('none')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('PWG-002: finds the networks whose box holds a point, the smallest box first', async () => {
|
||||
await region('wide', 0, 20);
|
||||
await region('local', 4, 6);
|
||||
await region('far', 30, 40);
|
||||
expect((await graphs.coveringPoint(5, 5)).map((row) => row.region_id)).toEqual(['local', 'wide']);
|
||||
expect(await graphs.coveringPoint(25, 25)).toEqual([]);
|
||||
});
|
||||
|
||||
it('PWG-003: forgets a network whose file is gone, but not one built again under another name', async () => {
|
||||
await region('lake', 0, 5, 'lake-1.bin');
|
||||
expect(await graphs.forgetMissing('lake', 'lake-0.bin')).toBe(false);
|
||||
expect(await graphs.findByRegion('lake')).toBeDefined();
|
||||
expect(await graphs.forgetMissing('lake', 'lake-1.bin')).toBe(true);
|
||||
expect(await graphs.findByRegion('lake')).toBeUndefined();
|
||||
expect(await graphs.forgetMissing('lake', 'lake-1.bin')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* `ToursRepository`, the library reads of LIB-02: the tours of the trips a
|
||||
* user may see (TL1), how many each trip holds (TL2), and one of them for its
|
||||
* preview (TL3). Every read is bounded by the trips handed in.
|
||||
*/
|
||||
import { Tours } from '../../../../src/db/entities/Tours.entity';
|
||||
import type { ToursRepository } from '../../../../src/db/repositories/Tours.repository';
|
||||
import { createSnapshotTestDb } from '../../../helpers/db-mock';
|
||||
import { makePlace } from '../../../helpers/factories/places';
|
||||
import { addTourWaypoints, makeTour } from '../../../helpers/factories/tours';
|
||||
import { makeTrip } from '../../../helpers/factories/trips';
|
||||
import { makeUser } from '../../../helpers/factories/users';
|
||||
import { resetTestDb } from '../../../helpers/test-db';
|
||||
import { createTestOrm, type TestOrm } from '../../../helpers/test-orm';
|
||||
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
const testDb = createSnapshotTestDb();
|
||||
let t: TestOrm;
|
||||
let repo: ToursRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
t = await createTestOrm(testDb);
|
||||
repo = t.repo(Tours);
|
||||
});
|
||||
beforeEach(() => {
|
||||
resetTestDb(testDb);
|
||||
t.clear();
|
||||
});
|
||||
afterAll(async () => {
|
||||
await t.close();
|
||||
testDb.close();
|
||||
});
|
||||
|
||||
/** Two trips of one user, Alps with a hike and a paddle tour, Coast with one hike, and a third trip nobody asks about. */
|
||||
async function library() {
|
||||
const { user } = await makeUser(t);
|
||||
const alps = await makeTrip(t, user.id, { title: 'Alps' });
|
||||
const coast = await makeTrip(t, user.id, { title: 'Coast' });
|
||||
const hidden = await makeTrip(t, user.id, { title: 'Hidden' });
|
||||
const ridge = await makePlace(t, alps.id, { name: 'Ridge', description: 'Up high' });
|
||||
const lake = await makePlace(t, alps.id, { name: 'Lake' });
|
||||
const cliffs = await makePlace(t, coast.id, { name: 'Cliffs', route_geometry: '[[47,11],[47.1,11.1]]' });
|
||||
const secret = await makePlace(t, hidden.id, { name: 'Secret' });
|
||||
await makeTour(t, ridge.id, { distance: 8, max_hiking_difficulty: 3, created_at: '2026-01-01 10:00:00' });
|
||||
await makeTour(t, lake.id, {
|
||||
tourTypeRef: 'kayak',
|
||||
boat_type: 'canoe',
|
||||
water_context: 'lake',
|
||||
created_at: '2026-01-02 10:00:00',
|
||||
});
|
||||
await makeTour(t, cliffs.id, { distance: 5, created_at: '2026-01-03 10:00:00' });
|
||||
await makeTour(t, secret.id);
|
||||
await addTourWaypoints(t, cliffs.id, [
|
||||
{ lat: 47, lng: 11 },
|
||||
{ lat: 47.05, lng: 11.05 },
|
||||
{ lat: 47.1, lng: 11.1 },
|
||||
]);
|
||||
return { alps, coast, hidden, ridge, lake, cliffs, secret };
|
||||
}
|
||||
|
||||
describe('ToursRepository library reads (LIB-02)', () => {
|
||||
it('TL1-001: lists the tours of the trips handed in, newest trip and tour first, with the trip they are in', async () => {
|
||||
const { alps, coast, ridge, lake, cliffs } = await library();
|
||||
const rows = await repo.listForLibrary([alps.id, coast.id], {}, 50);
|
||||
expect(rows.map((row) => [row.name, row.trip_title])).toEqual([
|
||||
['Cliffs', 'Coast'],
|
||||
['Lake', 'Alps'],
|
||||
['Ridge', 'Alps'],
|
||||
]);
|
||||
expect(rows[0]).toMatchObject({
|
||||
place_id: cliffs.id,
|
||||
tour_type: 'hike',
|
||||
distance: 5,
|
||||
has_waypoints: 1,
|
||||
origin: 'trek',
|
||||
});
|
||||
expect(rows.find((row) => row.place_id === ridge.id)).toMatchObject({
|
||||
description: 'Up high',
|
||||
max_hiking_difficulty: 3,
|
||||
has_waypoints: 0,
|
||||
});
|
||||
expect(rows.find((row) => row.place_id === lake.id)?.tour_type).toBe('kayak');
|
||||
});
|
||||
|
||||
it('TL1-002: narrows by trip and by type, keeps to its limit, and answers nothing for no trips', async () => {
|
||||
const { alps, coast } = await library();
|
||||
expect((await repo.listForLibrary([alps.id, coast.id], { trip_id: alps.id }, 50)).map((row) => row.name)).toEqual([
|
||||
'Lake',
|
||||
'Ridge',
|
||||
]);
|
||||
expect((await repo.listForLibrary([alps.id, coast.id], { tour_type: 'kayak' }, 50)).map((row) => row.name)).toEqual(
|
||||
['Lake'],
|
||||
);
|
||||
expect(await repo.listForLibrary([alps.id, coast.id], {}, 1)).toHaveLength(1);
|
||||
expect(await repo.listForLibrary([], {}, 50)).toEqual([]);
|
||||
});
|
||||
|
||||
it('TL1-003: a trip filter outside the trips handed in finds nothing', async () => {
|
||||
const { alps, hidden } = await library();
|
||||
expect(await repo.listForLibrary([alps.id], { trip_id: hidden.id }, 50)).toEqual([]);
|
||||
});
|
||||
|
||||
it('TL2-001: counts the tours of each trip handed in, newest trip first, and nothing for no trips', async () => {
|
||||
const { alps, coast } = await library();
|
||||
expect(await repo.countForLibrary([alps.id, coast.id])).toEqual([
|
||||
{ id: coast.id, title: 'Coast', tour_count: 1 },
|
||||
{ id: alps.id, title: 'Alps', tour_count: 2 },
|
||||
]);
|
||||
expect(await repo.countForLibrary([])).toEqual([]);
|
||||
});
|
||||
|
||||
it('TL3-001: reads one tour with its line and how many control points it has, only within the trips handed in', async () => {
|
||||
const { alps, coast, cliffs, ridge, secret } = await library();
|
||||
expect(await repo.findForLibrary([alps.id, coast.id], cliffs.id)).toMatchObject({
|
||||
place_id: cliffs.id,
|
||||
trip_title: 'Coast',
|
||||
route_geometry: '[[47,11],[47.1,11.1]]',
|
||||
waypoint_count: 3,
|
||||
has_waypoints: 1,
|
||||
});
|
||||
expect(await repo.findForLibrary([alps.id], ridge.id)).toMatchObject({ waypoint_count: 0, has_waypoints: 0 });
|
||||
expect(await repo.findForLibrary([alps.id, coast.id], secret.id)).toBeUndefined();
|
||||
expect(await repo.findForLibrary([], cliffs.id)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user