import { expect, test } from '../fixtures/test'; import { SKYLINE_AGENT } from '../fixtures/accounts'; test.beforeEach(async ({ signInAs, shell, search }) => { await signInAs(SKYLINE_AGENT); await shell.goToSearch(); await search.settled(); }); test.describe('Flight search', () => { test('opens with the agency inventory already listed', async ({ search }) => { await expect(search.results.first()).toBeVisible(); await expect(search.resultSummary).toContainText('flights'); expect(await search.totalResults()).toBeGreaterThan(0); }); test('offers only airports this agency flies', async ({ search }) => { const codes = await search.origin.locator('option').allInnerTexts(); expect(codes.join(' ')).toContain('JFK'); expect(codes.join(' ')).toContain('LHR'); expect(codes[0]).toContain('Any airport'); }); test('narrows results to a route', async ({ search, evidence }) => { const before = await search.totalResults(); await evidence.step('Full inventory before filtering', { flightsVisible: before }); await search.searchRoute('JFK', 'LHR'); const after = await search.totalResults(); await evidence.step('Filtered to JFK to LHR', { route: 'JFK to LHR', flightsBefore: before, flightsAfter: after, cheapestFare: `$${(await search.card(0).fare()).toFixed(2)}`, firstFlight: await search.card(0).flightNumber(), }); expect(after).toBeGreaterThan(0); expect(after).toBeLessThan(before); // Every visible card should be on the requested route. const cards = await search.results.all(); for (const card of cards) { await expect(card.locator('.iata').first()).toHaveText('JFK'); await expect(card.locator('.iata').last()).toHaveText('LHR'); } }); test('a route with no inventory shows an empty state', async ({ search }) => { // Nothing in the seed data flies Heathrow to Heathrow. await search.searchRoute('LHR', 'LHR'); await expect(search.emptyState).toBeVisible(); await expect(search.emptyState).toContainText('Nothing on this route yet'); await expect(search.results).toHaveCount(0); }); test('resets back to the full list', async ({ search }) => { await search.searchRoute('JFK', 'LHR'); const narrowed = await search.totalResults(); await search.resetButton.click(); await search.settled(); expect(await search.totalResults()).toBeGreaterThan(narrowed); await expect(search.origin).toHaveValue(''); }); test('sorts by lowest fare', async ({ search, evidence }) => { await search.searchRoute('JFK', 'LHR'); await search.sortBy('price'); const fares: number[] = []; for (let i = 0; i < (await search.results.count()); i++) { fares.push(await search.card(i).fare()); } expect(fares.length).toBeGreaterThan(1); expect([...fares]).toEqual([...fares].sort((a, b) => a - b)); await evidence.step('Results ordered by lowest fare', { sortedBy: 'price', faresOnPage: fares.map((f) => `$${f.toFixed(2)}`).join(', '), lowest: `$${fares[0].toFixed(2)}`, highest: `$${fares[fares.length - 1].toFixed(2)}`, ascending: true, }); }); test('sorts by shortest trip', async ({ search }) => { await search.sortBy('duration'); const durations: number[] = []; for (let i = 0; i < Math.min(5, await search.results.count()); i++) { durations.push(await search.card(i).durationMinutes()); } expect([...durations]).toEqual([...durations].sort((a, b) => a - b)); }); test('filters by cabin', async ({ search }) => { await search.cabin.selectOption('business'); await search.searchButton.click(); await search.settled(); const count = await search.results.count(); expect(count).toBeGreaterThan(0); for (let i = 0; i < count; i++) { await expect(search.results.nth(i).locator('.fare-tags .badge').first()).toHaveText( /business/i, ); } }); test('hides flights without room for the whole party', async ({ search }) => { await search.setTravellers(9); const count = await search.results.count(); for (let i = 0; i < count; i++) { expect(await search.card(i).seatsLeft()).toBeGreaterThanOrEqual(9); } }); test('pages through results without repeating them', async ({ search }) => { await expect(search.prevPage).toBeDisabled(); const firstPage = await search.results.first().innerText(); await search.nextPage.click(); await search.settled(); await expect(search.prevPage).toBeEnabled(); await expect(search.resultSummary).toContainText('Showing 11'); expect(await search.results.first().innerText()).not.toBe(firstPage); await search.prevPage.click(); await search.settled(); await expect(search.resultSummary).toContainText('Showing 1–10'); }); test('a result card carries everything needed to choose', async ({ search }) => { const card = search.card(0); await expect(card.root.locator('.carrier-name')).not.toBeEmpty(); await expect(card.root.locator('.leg-duration')).toContainText(/\d+h|\d+m/); await expect(card.price).toContainText('$'); await expect(card.seatsBadge).toContainText('left'); await expect(card.root.locator('.departure-date')).not.toBeEmpty(); await expect(card.selectButton).toBeEnabled(); }); });