import type { Page, Locator } from '@playwright/test'; /** * Page object for `/export` (see [frontend/src/routes/export/+page.svelte]). * * The two archive buttons are BOTH labelled exactly "Download" — the format is carried by * the surrounding card ("ZIP-Archiv" / "HTML-Viewer"), not by the accessible name. Earlier * versions of this file looked for `/zip.*herunter/i` and `/^herunterladen$/i`, which match * nothing on this page; any test asserting `not.toBeVisible()` on those passed no matter * what the page rendered. Locators here must match the real UI, so scope by card. * * "Herunterladen" IS a real label — but only inside the HTML-guide confirm modal, which is * a different element entirely. */ export class ExportPage { readonly page: Page; /** Empty state shown while the host has not released the export yet. */ readonly notAvailableBanner: Locator; /** Any "Download" button on the page (both cards). Useful for absence assertions. */ readonly downloadButtons: Locator; readonly zipDownloadButton: Locator; readonly htmlDownloadButton: Locator; /** Confirm button inside the "Hinweis zum HTML-Viewer" modal. */ readonly htmlGuideModalContinue: Locator; constructor(page: Page) { this.page = page; this.notAvailableBanner = page.getByText('Export noch nicht verfügbar'); this.downloadButtons = page.getByRole('button', { name: 'Download', exact: true }); this.zipDownloadButton = this.cardButton('ZIP-Archiv'); this.htmlDownloadButton = this.cardButton('HTML-Viewer'); this.htmlGuideModalContinue = page .getByRole('dialog') .getByRole('button', { name: /^herunterladen$/i }); } /** * The "Download" button inside the card whose heading is `heading`. * * Scoped to the card element rather than "any div containing the heading" — the latter * also matches the page wrapper, which contains BOTH cards' buttons. * * The scope class is `div.card` (see the ZIP/HTML cards in * frontend/src/routes/export/+page.svelte). It was previously `div.rounded-xl`, which * matched NOTHING: `.card` is a Tailwind `@apply` component class * (frontend/src/lib/styles/components.css) so the DOM only ever carries `class="card p-5"` * — and the utility it applies is `rounded-2xl` anyway. Both card-scoped locators were * therefore dead, which is why the "shows enabled download buttons" test was red. */ private cardButton(heading: string): Locator { return this.page .locator('div.card') .filter({ has: this.page.getByRole('heading', { name: heading, exact: true }) }) .getByRole('button', { name: 'Download', exact: true }); } async goto() { await this.page.goto('/export'); } }