mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-24 07:53:09 +00:00
31859651d7
Every help screen checked against the v5 redesign. Tours is documented for the first time, as a screen of its own with twelve screens under it, and notifications get help of their own. All pictures are taken again on a realistic demo trip, with short loops where a still cannot show the motion. The English is plain and every language is written naturally rather than word for word. The switcher shows two levels at most, a screen's overview lists its sub-screens as cards above its guides, each wiki page is linked once, and the help sidebar is wider. Fixes found along the way: Save to Collection keeps a tour's route, a track dropped on the places column opens the Tours import, tour Share on desktop, the unsaved tour draft lives on the account, a route click no longer adds an end point, Trip places leaves the trip's tours out, Escape closes a stage's day menu, confirms before destructive deletes, DWD warnings sharing one id kept apart, a booking's date moves with it, and smaller fixes across notifications, bookings, the day plan, stays, Atlas, Collections, Vacay and the admin screens.
72 lines
3.3 KiB
TypeScript
72 lines
3.3 KiB
TypeScript
import type { APIRequestContext } from '@playwright/test';
|
|
import { seededTrip } from './fixtures';
|
|
import { TOUR_NAMES } from './tour-fixtures';
|
|
|
|
/**
|
|
* What the tour guide on the plan map needs beyond `ensureToursFixtures`: one
|
|
* of the trip's tours on a day, so the day's route has a tour to run to and on
|
|
* from. The Tours fixtures may already put one there; then nothing is added.
|
|
* Otherwise the Fushimi Inari hike goes onto day 5, the day that already holds
|
|
* Fushimi Inari Taisha, and `removeTourFromDay` takes exactly that assignment
|
|
* out again in `afterAll`, so the screens after this one see the seed as it was.
|
|
*/
|
|
|
|
interface DayAssignment {
|
|
id: number;
|
|
place_id: number;
|
|
place?: { name?: string };
|
|
}
|
|
|
|
/** The tour names, whatever shape the Tours fixtures export them in (a list or a map of them). */
|
|
export function tourNames(): string[] {
|
|
const values = Object.values(TOUR_NAMES as unknown as Record<string, unknown>);
|
|
return values.filter((v): v is string => typeof v === 'string');
|
|
}
|
|
|
|
export interface TourOnDay {
|
|
/** The day's number in the days column, 1-based. */
|
|
day: number;
|
|
/** The tour's name, as the list and its card show it. */
|
|
name: string;
|
|
/** The assignment this fixture created, to remove again; null when the tour was already on a day. */
|
|
created: { dayId: number; id: number } | null;
|
|
}
|
|
|
|
async function assignmentsOf(api: APIRequestContext, tripId: number, dayId: number): Promise<DayAssignment[]> {
|
|
const res = await api.get(`/api/trips/${tripId}/days/${dayId}/assignments`);
|
|
if (!res.ok()) throw new Error(`could not read the assignments of day ${dayId}: ${res.status()}`);
|
|
const body = (await res.json()) as { assignments?: DayAssignment[] };
|
|
return body.assignments ?? [];
|
|
}
|
|
|
|
export async function ensureTourOnDay(api: APIRequestContext): Promise<TourOnDay> {
|
|
const { tripId, dayIds } = seededTrip();
|
|
const names = tourNames();
|
|
if (!names.length) throw new Error('the Tours fixtures export no tour names');
|
|
|
|
for (let i = 0; i < dayIds.length; i++) {
|
|
const onDay = (await assignmentsOf(api, tripId, dayIds[i])).find((a) => names.includes(a.place?.name ?? ''));
|
|
if (onDay?.place?.name) return { day: i + 1, name: onDay.place.name, created: null };
|
|
}
|
|
|
|
const res = await api.get(`/api/trips/${tripId}/places`);
|
|
const body = (await res.json()) as { places?: { id: number; name: string }[] } | { id: number; name: string }[];
|
|
const places = Array.isArray(body) ? body : (body.places ?? []);
|
|
const tours = places.filter((p) => names.includes(p.name));
|
|
const tour = tours.find((p) => /fushimi/i.test(p.name)) ?? tours[0];
|
|
if (!tour) throw new Error(`none of the tours (${names.join(', ')}) is in the trip`);
|
|
|
|
const dayId = dayIds[4];
|
|
const created = await api.post(`/api/trips/${tripId}/days/${dayId}/assignments`, { data: { place_id: tour.id } });
|
|
if (!created.ok())
|
|
throw new Error(`could not put "${tour.name}" on day 5: ${created.status()} ${await created.text()}`);
|
|
const { assignment } = (await created.json()) as { assignment: { id: number } };
|
|
return { day: 5, name: tour.name, created: { dayId, id: assignment.id } };
|
|
}
|
|
|
|
export async function removeTourFromDay(api: APIRequestContext, onDay: TourOnDay | null): Promise<void> {
|
|
if (!onDay?.created) return;
|
|
const { tripId } = seededTrip();
|
|
await api.delete(`/api/trips/${tripId}/days/${onDay.created.dayId}/assignments/${onDay.created.id}`);
|
|
}
|