# Instructions - Following Playwright test failed. - Explain why, be concise, respect Playwright best practices. - Provide a snippet of code with the fix, if possible. # Test info - Name: src/manager/tests/e2e/booking/booking-create.spec.ts >> creates a booking using the most recently added payment method - Location: src/manager/tests/e2e/booking/booking-create.spec.ts:330:5 # Error details ``` Error: expect(locator).toHaveText(expected) failed Locator: getByTestId('app-page').getByTestId('app-page-content').locator('[data-test-id=app-details-card]:has([data-test-id=title]:has-text("Billing"))').locator('[data-test-id=key-value-item]:has([data-test-id=key]:text-is("Payment method"))').getByTestId('payment-method-row') Expected: "•••• 4444 Card" Timeout: 30000ms Error: element(s) not found Call log: - Expect "toHaveText" with timeout 30000ms - waiting for getByTestId('app-page').getByTestId('app-page-content').locator('[data-test-id=app-details-card]:has([data-test-id=title]:has-text("Billing"))').locator('[data-test-id=key-value-item]:has([data-test-id=key]:text-is("Payment method"))').getByTestId('payment-method-row') ``` ```yaml - navigation: - link: - /url: / - text: KINNOVIS Manager - button: - img - list: - text: Dashboard - link "Tasks": - /url: /tasks - img - text: Tasks - link "Facility maps": - /url: /facility-map - link "Analytics": - /url: /dashboard - text: Sales - link "Bookings": - /url: /bookings - link "Customers": - /url: /customers - link "Invoices": - /url: /invoices - link "Credit notes": - /url: /credit-notes - img - text: Credit notes - link "Units": - /url: /units - text: Site management - link "Locations": - /url: /locations - link "Unit types": - /url: /unit-types - link "Protection Plans": - /url: /insurances - link "Deposits": - /url: /deposits - link "Products": - /url: /products - link "Discounts": - /url: /discounts - option "Emails" - link "Document templates": - /url: /document-templates - text: Admin - link "Integrations": - /url: /connected-apps - link "User & Roles": - /url: /users - option "Booking Portal" - option "JaneAI" - text: Feedback - link "Voting Portal": - /url: /voting-portal - button "AS Andreas Stadler andreas.stadler@storeroom.at" - button - main: - link "Bookings": - /url: /bookings - text: Booking 3163-6214-3922-46 Active - button "Actions" - heading "General" [level=3] - table: - rowgroup: - row "Customer Jaycee Jaskolski": - rowheader "Customer" - cell "Jaycee Jaskolski": - link "Jaycee Jaskolski": - /url: /customers/1501321144 - row "Location Vienna South": - rowheader "Location" - cell "Vienna South": - link "Vienna South": - /url: /locations/5000500050 - row "Created at 17 Aug 2026": - rowheader "Created at" - cell "17 Aug 2026" - row "Move-in 17 Aug 2026": - rowheader "Move-in" - cell "17 Aug 2026" - row "Move-out -": - rowheader "Move-out" - cell "-" - row "Cancelled at -": - rowheader "Cancelled at" - cell "-" - row "Deposit excl. VAT -": - rowheader "Deposit excl. VAT" - cell "-" - row "Discount -": - rowheader "Discount" - cell "-" - row "Contract -": - rowheader "Contract" - cell "-" - heading "Billing" [level=3] - table: - rowgroup: - row "Booking Plan Basic (1 month)": - rowheader "Booking Plan" - cell "Basic (1 month)" - row "Current period 17 Aug - 17 Sep 2026": - rowheader "Current period" - cell "17 Aug - 17 Sep 2026" - row "Amount excl. VAT €50.00": - rowheader "Amount excl. VAT" - cell "€50.00" - row "Price adjustment -": - rowheader "Price adjustment" - cell "-" - row "Next invoice 17 Sep 2026 Show preview": - rowheader "Next invoice" - cell "17 Sep 2026 Show preview": - text: 17 Sep 2026 - link "Show preview": - /url: /bookings/31636214392246/upcoming-invoice - row "Payment method -": - rowheader "Payment method" - cell "-" - row "Payment option Automatic payment through Stripe": - rowheader "Payment option" - cell "Automatic payment through Stripe" - heading "Notes" [level=3] - link: - /url: /bookings/31636214392246/edit/notes - table: - rowgroup: - row "Note -": - rowheader "Note" - cell "-" - heading "Items" [level=3] - link "Electronic Box x8FZ7E": - /url: /unit-types/1421084114 - text: / - link "Unit 1MCZjo": - /url: /units/2100067786 - text: €50.00 - strong: Total excl. VAT - strong: €50.00 - text: VAT €8.50 - strong: Total incl. VAT - strong: €58.50 - heading "Invoices" [level=3] - button "Select all" - button "Mark as paid" [disabled] - button "SEPA XML actions" [disabled] - button: - img - table: - rowgroup: - row "Number Status Payment option Due date Unit Discount Total (incl. VAT) Amount due Issue date Actions": - columnheader: - checkbox - columnheader "Number": - button "Number" - columnheader "Status": - button "Status" - columnheader "Payment option": - button "Payment option" - columnheader "Due date": - button "Due date" - columnheader "Unit": - button "Unit" - columnheader "Discount" - columnheader "Total (incl. VAT)": - button "Total (incl. VAT)" - columnheader "Amount due": - button "Amount due" - columnheader "Issue date": - button "Issue date" - columnheader "Actions" - row: - columnheader - rowgroup: - row "INV-2102577 Open Auto charge 19 Aug 2026 - €58.50 €58.50 17 Aug 2026": - cell: - checkbox - cell "INV-2102577": - link "INV-2102577": - /url: /invoices/1999655537 - cell "Open": - link "Open": - /url: /invoices/1999655537 - cell "Auto charge": - link "Auto charge": - /url: /invoices/1999655537 - cell "19 Aug 2026": - link "19 Aug 2026": - /url: /invoices/1999655537 - cell: - link: - /url: /invoices/1999655537 - cell "-" - cell "€58.50": - link "€58.50": - /url: /invoices/1999655537 - cell "€58.50": - link "€58.50": - /url: /invoices/1999655537 - cell "17 Aug 2026": - link "17 Aug 2026": - /url: /invoices/1999655537 - cell: - button - text: "Items per page:" - combobox: - text: "10" - combobox "Items per page:": "10" - text: 1-1 of 1 - button [disabled] - button [disabled] - button [disabled] - button [disabled] - heading "Payments" [level=3] - table: - rowgroup: - row "Total Status Invoice no. Date Payment method": - columnheader "Total": - button "Total" - columnheader "Status": - button "Status" - columnheader "Invoice no.": - button "Invoice no." - columnheader "Date": - button "Date" - columnheader "Payment method": - button "Payment method" - row: - columnheader - rowgroup: - row "€58.50 Not paid yet INV-2102577 17 Aug 2026": - cell "€58.50" - cell "Not paid yet" - cell "INV-2102577" - cell "17 Aug 2026" - cell - text: "Items per page:" - combobox: - text: "10" - combobox "Items per page:": "10" - text: 1-1 of 1 - button [disabled] - button [disabled] - button [disabled] - button [disabled] - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip - tooltip ``` # Test source ```ts 1 | import { expect, Locator } from '@playwright/test'; 2 | 3 | export async function expectMultiLocatorToHaveText(locator: Locator, text: string[] | undefined): Promise { 4 | if (!text) { 5 | await expectLocatorToBeEmpty(locator); 6 | return; 7 | } 8 | 9 | const expectedValue = RegExp(text.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')); 10 | 11 | for (const element of await locator.all()) { 12 | await expectSingleLocatorToHaveText(element, expectedValue); 13 | } 14 | } 15 | 16 | export async function expectSingleLocatorToHaveText( 17 | locator: Locator, 18 | text: string | RegExp | undefined 19 | ): Promise { 20 | text > 21 | ? await expect(locator).toHaveText(text, { ignoreCase: true, useInnerText: true }) | ^ Error: expect(locator).toHaveText(expected) failed 22 | : await expectLocatorToBeEmpty(locator); 23 | } 24 | 25 | export async function expectLocatorToBeEmpty(locator: Locator): Promise { 26 | await expect(locator).toHaveText(/^(\s*-?\s*)$/); 27 | } 28 | ```