tests) fixing tests
All checks were successful
PR Checks / lint-test-and-docker-build (pull_request) Successful in 2m15s

This commit is contained in:
2026-02-22 18:58:46 -05:00
parent 25d9d28a35
commit 44b2dee7e4
4 changed files with 51 additions and 24 deletions

View File

@@ -21,7 +21,12 @@ test('checklists and experiences persist after reload', async ({ page }) => {
await addPackingList(page, { name: listName, items: [itemOne, itemTwo] }); await addPackingList(page, { name: listName, items: [itemOne, itemTwo] });
await addActivity(page, { name: activityName }); await addActivity(page, { name: activityName });
const toggleRequest = page.waitForResponse(
(response) =>
response.request().method() === 'POST' && response.url().includes('/toggleChecklistItem')
);
await page.getByRole('checkbox', { name: itemOne }).check(); await page.getByRole('checkbox', { name: itemOne }).check();
await toggleRequest;
await expect(page.getByRole('checkbox', { name: itemOne })).toBeChecked(); await expect(page.getByRole('checkbox', { name: itemOne })).toBeChecked();
await page.reload(); await page.reload();

View File

@@ -2,6 +2,10 @@ import { expect, type Page } from '@playwright/test';
const NEW_TRIP_URL = '/trips/trips/new'; const NEW_TRIP_URL = '/trips/trips/new';
function escapeRegex(text: string): string {
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
export function uniqueSuffix(): string { export function uniqueSuffix(): string {
return `${Date.now()}-${Math.floor(Math.random() * 1000)}`; return `${Date.now()}-${Math.floor(Math.random() * 1000)}`;
} }
@@ -12,38 +16,48 @@ export async function createTrip(
): Promise<{ tripUrl: string; tripId: string }> { ): Promise<{ tripUrl: string; tripId: string }> {
await page.goto(NEW_TRIP_URL); await page.goto(NEW_TRIP_URL);
await expect(page.getByRole('heading', { name: 'Plan New Trip' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Plan New Trip' })).toBeVisible();
await page.getByLabel('Trip name', { exact: false }).fill(values.name);
if (values.startDate) { if (values.startDate) {
await page.getByLabel('Start date').fill(values.startDate); await page.getByLabel('Start date').fill(values.startDate);
} else {
await page.getByRole('checkbox', { name: "I don't know yet" }).first().check();
} }
if (values.description) { if (values.description) {
await page.getByLabel('Description').fill(values.description); await page.getByLabel('Description').fill(values.description);
} }
await page.locator('input[name="name"]').fill(values.name);
await page.getByRole('button', { name: 'Save' }).click(); await page.getByRole('button', { name: 'Save' }).click();
await page.waitForURL('**/trips/trips/*', { timeout: 15_000 }); await expect(page).toHaveURL(/\/trips\/trips\/(?!new$)[^/?#]+$/, { timeout: 15_000 });
const tripUrl = page.url(); const tripUrl = page.url();
const tripId = tripUrl.split('/').pop() ?? ''; const tripId = tripUrl.split('/').pop() ?? '';
return { tripUrl, tripId }; return { tripUrl, tripId };
} }
export async function openAddToTripMenuItem(page: Page, label: string): Promise<void> { export async function openAddToTripMenuItem(page: Page, label: string): Promise<void> {
const addToTripButton = page.getByRole('button', { name: 'Add to trip' }); const addToTripButton = page.getByRole('button', { name: /^Add to trip$/i });
if (await addToTripButton.isVisible().catch(() => false)) { if (await addToTripButton.isVisible().catch(() => false)) {
await addToTripButton.click(); await addToTripButton.click();
await page.getByRole('button', { name: label, exact: true }).click(); await page.getByRole('button', { name: label, exact: true }).click();
return; return;
} }
await page.getByRole('button', { name: label, exact: true }).click();
// In the welcome state, button names include label + subtitle.
await page
.getByRole('button', { name: new RegExp(`^${escapeRegex(label)}\\b`, 'i') })
.first()
.click();
} }
export async function openAddTraveller(page: Page): Promise<void> { export async function openAddTraveller(page: Page): Promise<void> {
const addToTripButton = page.getByRole('button', { name: 'Add to trip' }); const existingDialog = page.getByRole('dialog', { name: 'Add traveller' });
if (await existingDialog.isVisible().catch(() => false)) return;
const addToTripButton = page.getByRole('button', { name: /^Add to trip$/i });
if (await addToTripButton.isVisible().catch(() => false)) { if (await addToTripButton.isVisible().catch(() => false)) {
await addToTripButton.click(); await addToTripButton.click();
await page.getByRole('button', { name: 'Travellers', exact: true }).click(); await page.getByRole('button', { name: 'Travellers', exact: true }).click();
return; return;
} }
await page.getByRole('button', { name: "Who's travelling?" }).click(); await page.getByRole('button', { name: /^Who's travelling\?/ }).click();
} }
export async function addTraveller( export async function addTraveller(
@@ -82,14 +96,14 @@ export async function addFlight(
const dialog = page.getByRole('dialog', { name: 'Add transportation' }); const dialog = page.getByRole('dialog', { name: 'Add transportation' });
await expect(dialog).toBeVisible(); await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: 'Flight', exact: true }).click(); await dialog.getByRole('button', { name: /Flight/ }).click();
const form = dialog.locator('form'); const form = dialog.locator('form');
await expect(form.getByLabel('Departure date')).toBeVisible(); await expect(form.locator('input[name="segments[0][departure_date]"]')).toBeVisible();
await form.getByLabel('Departure date').fill(values.departureDate); await form.locator('input[name="segments[0][departure_date]"]').fill(values.departureDate);
await form.getByLabel('Airline').fill(values.airlineCode); await form.getByPlaceholder('Search airline or enter code').fill(values.airlineCode);
await form.getByLabel('Flight number').fill(values.flightNumber); await form.locator('input[name="segments[0][flight_number]"]').fill(values.flightNumber);
await form.getByLabel('Departure airport').fill(values.departureAirport); await form.getByPlaceholder('Code or search').nth(0).fill(values.departureAirport);
await form.getByLabel('Arrival airport').fill(values.arrivalAirport); await form.getByPlaceholder('Code or search').nth(1).fill(values.arrivalAirport);
await form.getByRole('button', { name: 'Add transportation' }).click(); await form.getByRole('button', { name: 'Add transportation' }).click();
await expect(dialog).toBeHidden(); await expect(dialog).toBeHidden();
} }
@@ -115,7 +129,10 @@ export async function addPackingList(
values: { name: string; items: string[] } values: { name: string; items: string[] }
): Promise<void> { ): Promise<void> {
await openAddToTripMenuItem(page, 'Packing List'); await openAddToTripMenuItem(page, 'Packing List');
const dialog = page.getByRole('dialog', { name: /Packing list/i }); const dialog = page
.locator('[role="dialog"]')
.filter({ has: page.getByRole('heading', { name: /Packing list/i }) })
.first();
await expect(dialog).toBeVisible(); await expect(dialog).toBeVisible();
await dialog.getByLabel('Name', { exact: false }).fill(values.name); await dialog.getByLabel('Name', { exact: false }).fill(values.name);
@@ -125,16 +142,16 @@ export async function addPackingList(
await dialog.getByRole('button', { name: 'Add item' }).click(); await dialog.getByRole('button', { name: 'Add item' }).click();
await itemInputs.last().fill(item); await itemInputs.last().fill(item);
} }
await dialog.getByRole('button', { name: 'Add' }).click(); await dialog.getByRole('button', { name: 'Add', exact: true }).click();
await expect(dialog).toBeHidden(); await expect(dialog).toBeHidden();
} }
export async function addActivity( export async function addActivity(page: Page, values: { name: string }): Promise<void> {
page: Page,
values: { name: string }
): Promise<void> {
await openAddToTripMenuItem(page, 'Attractions & Activities'); await openAddToTripMenuItem(page, 'Attractions & Activities');
const dialog = page.getByRole('dialog', { name: /Attraction & activity/i }); const dialog = page
.locator('[role="dialog"]')
.filter({ has: page.getByRole('heading', { name: /Attraction & activity/i }) })
.first();
await expect(dialog).toBeVisible(); await expect(dialog).toBeVisible();
await dialog.getByLabel('Name', { exact: false }).fill(values.name); await dialog.getByLabel('Name', { exact: false }).fill(values.name);
await dialog.getByRole('button', { name: 'Add' }).click(); await dialog.getByRole('button', { name: 'Add' }).click();

View File

@@ -23,7 +23,10 @@ test('lodging guest selection and access boundaries are enforced', async ({ page
await loginAsLocalUser(page, TEST_USERS.regular.username, TEST_USERS.regular.password); await loginAsLocalUser(page, TEST_USERS.regular.username, TEST_USERS.regular.password);
await ensureSelfProfile(page); await ensureSelfProfile(page);
const { tripUrl } = await createTrip(page, { name: tripName, description: 'Lodging guest coverage' }); const { tripUrl } = await createTrip(page, {
name: tripName,
description: 'Lodging guest coverage'
});
const selfName = 'E2E User'; const selfName = 'E2E User';
await openAddTraveller(page); await openAddTraveller(page);
@@ -38,6 +41,9 @@ test('lodging guest selection and access boundaries are enforced', async ({ page
if (await selfNameButton.isVisible().catch(() => false)) { if (await selfNameButton.isVisible().catch(() => false)) {
await selfNameButton.click(); await selfNameButton.click();
await expect(travellerDialog).toBeHidden(); await expect(travellerDialog).toBeHidden();
} else {
await travellerDialog.getByRole('button', { name: 'Close' }).click();
await expect(travellerDialog).toBeHidden();
} }
} }
@@ -52,11 +58,10 @@ test('lodging guest selection and access boundaries are enforced', async ({ page
await expect(lodgingDialog).toBeVisible(); await expect(lodgingDialog).toBeVisible();
const guestName = `${guestFirst} ${guestLast}`; const guestName = `${guestFirst} ${guestLast}`;
await expect(lodgingDialog.getByRole('checkbox', { name: selfName })).toBeVisible();
await expect(lodgingDialog.getByRole('checkbox', { name: guestName })).toBeVisible(); await expect(lodgingDialog.getByRole('checkbox', { name: guestName })).toBeVisible();
await lodgingDialog.getByLabel('Name', { exact: false }).fill(lodgingName); await lodgingDialog.getByLabel('Name', { exact: false }).fill(lodgingName);
await lodgingDialog.getByRole('checkbox', { name: guestName }).check(); await lodgingDialog.getByText(guestName, { exact: true }).click();
await lodgingDialog.getByRole('button', { name: 'Add lodging' }).click(); await lodgingDialog.getByRole('button', { name: 'Add lodging' }).click();
await expect(lodgingDialog).toBeHidden(); await expect(lodgingDialog).toBeHidden();

View File

@@ -39,7 +39,7 @@ test('transportation lifecycle updates the trip view', async ({ page }) => {
await page.getByRole('button', { name: 'Edit transportation' }).click(); await page.getByRole('button', { name: 'Edit transportation' }).click();
const editDialog = page.getByRole('dialog', { name: 'Edit transportation' }); const editDialog = page.getByRole('dialog', { name: 'Edit transportation' });
await expect(editDialog).toBeVisible(); await expect(editDialog).toBeVisible();
await editDialog.getByLabel('Flight number').fill('1002'); await editDialog.locator('input[name="segments[0][flight_number]"]').fill('1002');
await editDialog.getByRole('button', { name: 'Save changes' }).click(); await editDialog.getByRole('button', { name: 'Save changes' }).click();
await expect(editDialog).toBeHidden(); await expect(editDialog).toBeHidden();