# 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 >> should create a booking for a customer with sepa payment
- Location: src/manager/tests/e2e/booking/booking-create.spec.ts:16: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')
Timeout: 20000ms
- Expected - 1
+ Received + 2
- •••• 3201 IBAN
+ •••• 3201
+ SEPA via Stripe
Call log:
- Expect "toHaveText" with timeout 20000ms
- 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')
24 × locator resolved to
- unexpected value "•••• 3201
SEPA via Stripe"
```
# Page snapshot
```yaml
- generic [active] [ref=e1]:
- generic [ref=e6]:
- banner [ref=e7]:
- generic [ref=e8]:
- button [ref=e9] [cursor=pointer]:
- generic [ref=e11]:
- link [ref=e12] [cursor=pointer]:
- /url: /
- button "AS" [ref=e14] [cursor=pointer]:
- generic [ref=e18]: AS
- generic:
- text:
- text:
- navigation [ref=e19]:
- list [ref=e21]:
- generic [ref=e23]: Dashboard
- link "Tasks" [ref=e24] [cursor=pointer]:
- /url: /tasks
- img [ref=e27]
- generic [ref=e30]: Tasks
- link "Facility maps" [ref=e31] [cursor=pointer]:
- /url: /facility-map
- generic [ref=e33]:
- generic [ref=e35]: Facility maps
- link "Analytics" [ref=e36] [cursor=pointer]:
- /url: /dashboard
- generic [ref=e38]:
- generic [ref=e40]: Analytics
- generic [ref=e42]: Sales
- link "Bookings" [ref=e43] [cursor=pointer]:
- /url: /bookings
- generic [ref=e45]:
- generic [ref=e47]: Bookings
- link "Customers" [ref=e48] [cursor=pointer]:
- /url: /customers
- generic [ref=e50]:
- generic [ref=e52]: Customers
- link "Invoices" [ref=e53] [cursor=pointer]:
- /url: /invoices
- generic [ref=e55]:
- generic [ref=e57]: Invoices
- link "Credit notes" [ref=e58] [cursor=pointer]:
- /url: /credit-notes
- img [ref=e61]
- generic [ref=e64]: Credit notes
- link "Units" [ref=e65] [cursor=pointer]:
- /url: /units
- generic [ref=e67]:
- generic [ref=e69]: Units
- generic [ref=e71]: Site Management
- link "Locations" [ref=e72] [cursor=pointer]:
- /url: /locations
- generic [ref=e74]:
- generic [ref=e76]: Locations
- link "Unit types" [ref=e77] [cursor=pointer]:
- /url: /unit-types
- generic [ref=e79]:
- generic [ref=e81]: Unit types
- link "Protection Plans" [ref=e82] [cursor=pointer]:
- /url: /insurances
- generic [ref=e84]:
- generic [ref=e86]: Protection Plans
- link "Deposits" [ref=e87] [cursor=pointer]:
- /url: /deposits
- generic [ref=e89]:
- generic [ref=e91]: Deposits
- link "Products" [ref=e92] [cursor=pointer]:
- /url: /products
- generic [ref=e94]:
- generic [ref=e96]: Products
- link "Discounts" [ref=e97] [cursor=pointer]:
- /url: /discounts
- generic [ref=e99]:
- generic [ref=e101]: Discounts
- generic [ref=e102]:
- option "Emails" [ref=e103] [cursor=pointer]:
- generic [ref=e105]:
- generic [ref=e107]: Emails
- generic [ref=e109]:
- text:
- generic [ref=e111]: Admin
- link "Integrations" [ref=e112] [cursor=pointer]:
- /url: /connected-apps
- generic [ref=e114]:
- generic [ref=e116]: Integrations
- link "User & Roles" [ref=e117] [cursor=pointer]:
- /url: /users
- generic [ref=e119]:
- generic [ref=e121]: User & Roles
- generic [ref=e122]:
- option "Booking Portal" [ref=e123] [cursor=pointer]:
- generic [ref=e125]:
- generic [ref=e127]: Booking Portal
- generic [ref=e129]:
- text:
- generic [ref=e130]:
- option "JaneAI" [ref=e131] [cursor=pointer]:
- generic [ref=e133]:
- generic [ref=e135]: JaneAI
- generic [ref=e137]:
- text:
- generic [ref=e139]: Feedback
- link "Voting Portal" [ref=e140] [cursor=pointer]:
- /url: /voting-portal
- generic [ref=e142]:
- generic [ref=e144]: Voting Portal
- main [ref=e145]:
- generic [ref=e146]:
- generic [ref=e148]:
- generic [ref=e149]:
- link [ref=e151] [cursor=pointer]:
- /url: /bookings
- generic [ref=e153]:
- generic [ref=e156]:
- generic [ref=e157]: Bookings
- generic [ref=e158]:
- heading "Booking 1501-3211-44" [level=1] [ref=e159]:
- generic [ref=e160]: Booking 1501-3211-44
- generic [ref=e164]: Active
- button "Actions" [ref=e166] [cursor=pointer]:
- generic [ref=e167]:
- text: Actions
- generic [ref=e168]:
- generic [ref=e170]:
- generic [ref=e171]:
- generic [ref=e173]:
- heading "General" [level=3] [ref=e177]
- table [ref=e180]:
- rowgroup [ref=e181]:
- row "Customer Kevinio Privato" [ref=e182]:
- rowheader "Customer" [ref=e183]
- cell "Kevinio Privato" [ref=e184]:
- link "Kevinio Privato" [ref=e187] [cursor=pointer]:
- /url: /customers/2000200020
- generic [ref=e189]: Kevinio Privato
- row "Location Vienna South" [ref=e190]:
- rowheader "Location" [ref=e191]
- cell "Vienna South" [ref=e192]:
- link "Vienna South" [ref=e195] [cursor=pointer]:
- /url: /locations/561465857
- generic [ref=e197]: Vienna South
- row "Created at 10 Apr 2026" [ref=e198]:
- rowheader "Created at" [ref=e199]
- cell "10 Apr 2026" [ref=e200]:
- generic [ref=e202]: 10 Apr 2026
- row "Move-in 10 Apr 2026" [ref=e203]:
- rowheader "Move-in" [ref=e204]
- cell "10 Apr 2026" [ref=e205]:
- generic [ref=e207]: 10 Apr 2026
- row "Move-out -" [ref=e208]:
- rowheader "Move-out" [ref=e209]
- cell "-" [ref=e210]:
- generic [ref=e212]: "-"
- row "Cancelled at -" [ref=e213]:
- rowheader "Cancelled at" [ref=e214]
- cell "-" [ref=e215]:
- generic [ref=e217]: "-"
- row "Deposit excl. VAT -" [ref=e218]:
- rowheader "Deposit excl. VAT" [ref=e219]
- cell "-" [ref=e220]:
- generic [ref=e222]: "-"
- row "Discount -" [ref=e223]:
- rowheader "Discount" [ref=e224]
- cell "-" [ref=e225]:
- generic [ref=e227]: "-"
- row "Contract -" [ref=e228]:
- rowheader "Contract" [ref=e229]
- cell "-" [ref=e230]:
- generic [ref=e232]: "-"
- generic [ref=e233]:
- generic [ref=e234]:
- heading "Billing" [level=3] [ref=e238]
- table [ref=e241]:
- rowgroup [ref=e242]:
- row "Booking Plan Super flex (1 week)" [ref=e243]:
- rowheader "Booking Plan" [ref=e244]
- cell "Super flex (1 week)" [ref=e245]:
- generic [ref=e247]: Super flex (1 week)
- row "Current period 10 - 17 Apr 2026" [ref=e248]:
- rowheader "Current period" [ref=e249]
- cell "10 - 17 Apr 2026" [ref=e250]:
- generic [ref=e252]: 10 - 17 Apr 2026
- row "Amount excl. VAT €50.00" [ref=e253]:
- rowheader "Amount excl. VAT" [ref=e254]
- cell "€50.00" [ref=e255]:
- generic [ref=e257]: €50.00
- row "Price adjustment -" [ref=e258]:
- rowheader "Price adjustment" [ref=e259]
- cell "-" [ref=e260]:
- generic [ref=e262]: "-"
- row "Next invoice 17 Apr 2026" [ref=e263]:
- rowheader "Next invoice" [ref=e264]
- cell "17 Apr 2026" [ref=e265]:
- generic [ref=e267]: 17 Apr 2026
- row "Payment method •••• 3201 SEPA via Stripe" [ref=e268]:
- rowheader "Payment method" [ref=e269]
- cell "•••• 3201 SEPA via Stripe" [ref=e270]:
- generic [ref=e276]:
- generic [ref=e278]: •••• 3201
- generic [ref=e279]: SEPA via Stripe
- row "Payment option Automatic payment through Stripe" [ref=e280]:
- rowheader "Payment option" [ref=e281]
- cell "Automatic payment through Stripe" [ref=e282]:
- generic [ref=e284]: Automatic payment through Stripe
- generic [ref=e285]:
- generic [ref=e287]:
- heading "Notes" [level=3] [ref=e289]
- link [ref=e291] [cursor=pointer]:
- /url: /bookings/1501321144/edit/notes
- generic [ref=e293]:
- table [ref=e296]:
- rowgroup [ref=e297]:
- row "Note -" [ref=e298]:
- rowheader "Note" [ref=e299]
- cell "-" [ref=e300]:
- generic [ref=e302]: "-"
- generic [ref=e305]:
- heading "Items" [level=3] [ref=e309]
- generic [ref=e312]:
- generic [ref=e313]:
- generic [ref=e314]:
- link "VS 1 sqm Unit" [ref=e315] [cursor=pointer]:
- /url: /unit-types/561465857
- generic [ref=e317]: VS 1 sqm Unit
- text: /
- 'link "Unit 49 #49" [ref=e318] [cursor=pointer]':
- /url: /units/998976231
- generic [ref=e320]: "Unit 49 #49"
- generic [ref=e321]: €40.00
- generic [ref=e322]:
- link "VS - Insurance weekly - 10" [ref=e323] [cursor=pointer]:
- /url: /insurances/1970483263
- generic [ref=e325]: VS - Insurance weekly - 10
- generic [ref=e326]: €10.00
- generic [ref=e327]:
- generic [ref=e328]:
- strong [ref=e329]: Total excl. VAT
- strong [ref=e330]: €50.00
- generic [ref=e331]:
- generic [ref=e332]: VAT
- generic [ref=e333]: €10.00
- generic [ref=e334]:
- generic [ref=e335]: Total incl. VAT
- generic [ref=e336]: €60.00
- generic [ref=e339]:
- generic [ref=e341]:
- heading "Invoices" [level=3] [ref=e343]
- progressbar [ref=e346]:
- img [ref=e347]
- generic [ref=e354]:
- generic [ref=e356]:
- generic [ref=e358]:
- button "Select all" [ref=e366] [cursor=pointer]:
- generic [ref=e368]:
- generic [ref=e369]: Select all
- generic [ref=e370]:
- button "Mark as paid" [disabled] [ref=e373]:
- generic [ref=e375]:
- generic [ref=e376]: Mark as paid
- button "SEPA XML actions" [disabled] [ref=e379]:
- generic [ref=e381]:
- generic [ref=e382]: SEPA XML actions
- generic:
- generic [ref=e385]:
- button [ref=e386] [cursor=pointer]:
- generic [ref=e388]:
- generic:
- table [ref=e390]:
- rowgroup [ref=e391]:
- row "Number Status Payment option Due date Unit Total (incl. VAT) Amount due Issue date Actions" [ref=e392]:
- columnheader "Number" [ref=e393]:
- button "Number" [ref=e394] [cursor=pointer]:
- generic [ref=e396]: Number
- generic [ref=e399]:
- columnheader "Status" [ref=e400]:
- button "Status" [ref=e401] [cursor=pointer]:
- generic [ref=e403]: Status
- generic [ref=e406]:
- columnheader "Payment option" [ref=e407]:
- button "Payment option" [ref=e408] [cursor=pointer]:
- generic [ref=e410]: Payment option
- generic [ref=e413]:
- columnheader "Due date" [ref=e414]:
- button "Due date" [ref=e415] [cursor=pointer]:
- generic [ref=e417]: Due date
- generic [ref=e420]:
- columnheader "Unit" [ref=e421]:
- button "Unit" [ref=e422] [cursor=pointer]:
- generic [ref=e424]: Unit
- generic [ref=e427]:
- columnheader "Total (incl. VAT)" [ref=e428]:
- button "Total (incl. VAT)" [ref=e429] [cursor=pointer]:
- generic [ref=e430]:
- generic [ref=e431]: Total (incl. VAT)
- generic [ref=e433]:
- generic [ref=e436]:
- columnheader "Amount due" [ref=e437]:
- button "Amount due" [ref=e438] [cursor=pointer]:
- generic [ref=e440]: Amount due
- generic [ref=e443]:
- columnheader "Issue date" [ref=e444]:
- button "Issue date" [ref=e445] [cursor=pointer]:
- generic [ref=e447]: Issue date
- generic [ref=e450]:
- columnheader "Actions" [ref=e451]:
- generic [ref=e454]: Actions
- row [ref=e455]:
- columnheader [ref=e456]
- rowgroup [ref=e457]:
- row "No data yet" [ref=e458]:
- cell "No data yet" [ref=e459]:
- generic [ref=e460]: No data yet
- generic [ref=e463]:
- generic [ref=e464]:
- generic [ref=e465]: "Items per page:"
- combobox [ref=e468] [cursor=pointer]:
- generic [ref=e470]:
- generic [ref=e472]: "10"
- combobox "Items per page:": "10"
- generic [ref=e474]:
- generic [ref=e475]: 0-0 of 0
- generic [ref=e476]:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- generic [ref=e479]:
- generic [ref=e481]:
- heading "Payments" [level=3] [ref=e483]
- progressbar [ref=e486]:
- img [ref=e487]
- generic [ref=e494]:
- table [ref=e498]:
- rowgroup [ref=e499]:
- row "Total Status Invoice no. Date Payment method" [ref=e500]:
- columnheader "Total" [ref=e501]:
- button "Total" [ref=e502] [cursor=pointer]:
- generic [ref=e504]: Total
- generic [ref=e507]:
- columnheader "Status" [ref=e508]:
- button "Status" [ref=e509] [cursor=pointer]:
- generic [ref=e511]: Status
- generic [ref=e514]:
- columnheader "Invoice no." [ref=e515]:
- button "Invoice no." [ref=e516] [cursor=pointer]:
- generic [ref=e518]: Invoice no.
- generic [ref=e521]:
- columnheader "Date" [ref=e522]:
- button "Date" [ref=e523] [cursor=pointer]:
- generic [ref=e525]: Date
- generic [ref=e528]:
- columnheader "Payment method" [ref=e529]:
- button "Payment method" [ref=e530] [cursor=pointer]:
- generic [ref=e532]: Payment method
- generic [ref=e535]:
- row [ref=e536]:
- columnheader [ref=e537]
- rowgroup [ref=e538]:
- row "No data yet" [ref=e539]:
- cell "No data yet" [ref=e540]:
- generic [ref=e541]: No data yet
- generic [ref=e544]:
- generic [ref=e545]:
- generic [ref=e546]: "Items per page:"
- combobox [ref=e549] [cursor=pointer]:
- generic [ref=e551]:
- generic [ref=e553]: "10"
- combobox "Items per page:": "10"
- generic [ref=e555]:
- generic [ref=e556]: 0-0 of 0
- generic [ref=e557]:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- contentinfo [ref=e558]:
- generic [ref=e559]:
- generic [ref=e560]:
- text: Kinnovis GmbH
- generic [ref=e561]:
- text: "2026"
- generic [ref=e562]: v2026.04.08
- generic:
- 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.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 |
```