# 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 sepa auto-charged booking - Location: src/manager/tests/e2e/booking/booking-create.spec.ts:84:7 # 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: "•••• 3201 SEPA via Stripe" 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 7217-1848-7385-274 Active - button "Actions" - heading "General" [level=3] - table: - rowgroup: - row "Customer Alfreda Steuber": - rowheader "Customer" - cell "Alfreda Steuber": - link "Alfreda Steuber": - /url: /customers/788622353 - row "Location Vienna South": - rowheader "Location" - cell "Vienna South": - link "Vienna South": - /url: /locations/5000500050 - row "Created at 22 Aug 2026": - rowheader "Created at" - cell "22 Aug 2026" - row "Move-in 22 Aug 2026": - rowheader "Move-in" - cell "22 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 week)": - rowheader "Booking Plan" - cell "Basic (1 week)" - row "Current period 22 - 29 Aug 2026": - rowheader "Current period" - cell "22 - 29 Aug 2026" - row "Amount excl. VAT €50.00": - rowheader "Amount excl. VAT" - cell "€50.00" - row "Price adjustment -": - rowheader "Price adjustment" - cell "-" - row "Next invoice 29 Aug 2026 Show preview": - rowheader "Next invoice" - cell "29 Aug 2026 Show preview": - text: 29 Aug 2026 - link "Show preview": - /url: /bookings/721718487385274/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/721718487385274/edit/notes - table: - rowgroup: - row "Note -": - rowheader "Note" - cell "-" - heading "Items" [level=3] - link "Fresh Box I5XofR": - /url: /unit-types/1074096054 - text: / - link "Unit iergSV": - /url: /units/944659000 - 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-2111680 Open Auto charge 24 Aug 2026 - €58.50 €58.50 22 Aug 2026": - cell: - checkbox - cell "INV-2111680": - link "INV-2111680": - /url: /invoices/1451494330 - cell "Open": - link "Open": - /url: /invoices/1451494330 - cell "Auto charge": - link "Auto charge": - /url: /invoices/1451494330 - cell "24 Aug 2026": - link "24 Aug 2026": - /url: /invoices/1451494330 - cell: - link: - /url: /invoices/1451494330 - cell "-" - cell "€58.50": - link "€58.50": - /url: /invoices/1451494330 - cell "€58.50": - link "€58.50": - /url: /invoices/1451494330 - cell "22 Aug 2026": - link "22 Aug 2026": - /url: /invoices/1451494330 - 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-2111680 22 Aug 2026": - cell "€58.50" - cell "Not paid yet" - cell "INV-2111680" - cell "22 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 { escapeRegExp } from '@/shared/utils/regex-utils'; 2 | import { expect, Locator } from '@playwright/test'; 3 | 4 | export async function expectMultiLocatorToHaveText(locator: Locator, text: string[] | undefined): Promise { 5 | if (!text) { 6 | await expectLocatorToBeEmpty(locator); 7 | return; 8 | } 9 | 10 | const expectedValue = RegExp(text.map(escapeRegExp).join('|')); 11 | 12 | for (const element of await locator.all()) { 13 | await expectSingleLocatorToHaveText(element, expectedValue); 14 | } 15 | } 16 | 17 | export async function expectSingleLocatorToHaveText( 18 | locator: Locator, 19 | text: string | RegExp | undefined 20 | ): Promise { 21 | text > 22 | ? await expect(locator).toHaveText(text, { ignoreCase: true, useInnerText: true }) | ^ Error: expect(locator).toHaveText(expected) failed 23 | : await expectLocatorToBeEmpty(locator); 24 | } 25 | 26 | export async function expectLocatorToBeEmpty(locator: Locator): Promise { 27 | await expect(locator).toHaveText(/^(\s*-?\s*)$/); 28 | } 29 | ```