# 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/invoice/invoice-issue-credit-note.spec.ts >> issues a partial credit note for an open invoice with one item by reducing the credit net amount
- Location: src/manager/tests/e2e/invoice/invoice-issue-credit-note.spec.ts:29:7
# Error details
```
Error: expect(locator).toHaveText(expected) failed
Locator: locator('.v-dialog:has([data-test-id="invoice-issue-credit-note-dialog"]):has(.v-overlay__content:not(.dialog-bottom-transition-enter-active))').locator('fieldset:has(legend:has-text("Items to credit"))').getByTestId('totals-summary-section').getByTestId('total-excl-vat-value')
Expected: "€10.00"
Received: "€600.00"
Timeout: 30000ms
Call log:
- Expect "toHaveText" with timeout 30000ms
- waiting for locator('.v-dialog:has([data-test-id="invoice-issue-credit-note-dialog"]):has(.v-overlay__content:not(.dialog-bottom-transition-enter-active))').locator('fieldset:has(legend:has-text("Items to credit"))').getByTestId('totals-summary-section').getByTestId('total-excl-vat-value')
34 × locator resolved to
€600.00
- unexpected value "€600.00"
```
# Page snapshot
```yaml
- generic [ref=e1]:
- generic [ref=e6]:
- navigation [ref=e7]:
- generic [ref=e9]:
- link [ref=e10] [cursor=pointer]:
- /url: /
- generic [ref=e11]:
- generic [ref=e12]: KINNOVIS
- generic [ref=e13]: Manager
- button [ref=e15] [cursor=pointer]:
- img [ref=e16]
- list [ref=e19]:
- generic [ref=e22]: Dashboard
- link "Tasks" [ref=e23] [cursor=pointer]:
- /url: /tasks
- img [ref=e26]
- generic [ref=e29]: Tasks
- link "Facility maps" [ref=e30] [cursor=pointer]:
- /url: /facility-map
- generic [ref=e32]:
- generic [ref=e34]: Facility maps
- link "Analytics" [ref=e35] [cursor=pointer]:
- /url: /dashboard
- generic [ref=e37]:
- generic [ref=e39]: Analytics
- generic [ref=e41]: Sales
- link "Bookings" [ref=e42] [cursor=pointer]:
- /url: /bookings
- generic [ref=e44]:
- generic [ref=e46]: Bookings
- link "Customers" [ref=e47] [cursor=pointer]:
- /url: /customers
- generic [ref=e49]:
- generic [ref=e51]: Customers
- link "Invoices" [ref=e52] [cursor=pointer]:
- /url: /invoices
- generic [ref=e54]:
- generic [ref=e56]: Invoices
- link "Credit notes" [ref=e57] [cursor=pointer]:
- /url: /credit-notes
- img [ref=e60]
- generic [ref=e63]: Credit notes
- link "Units" [ref=e64] [cursor=pointer]:
- /url: /units
- generic [ref=e66]:
- generic [ref=e68]: Units
- generic [ref=e70]: Site management
- link "Locations" [ref=e71] [cursor=pointer]:
- /url: /locations
- generic [ref=e73]:
- generic [ref=e75]: Locations
- link "Unit types" [ref=e76] [cursor=pointer]:
- /url: /unit-types
- generic [ref=e78]:
- generic [ref=e80]: Unit types
- link "Protection Plans" [ref=e81] [cursor=pointer]:
- /url: /insurances
- generic [ref=e83]:
- generic [ref=e85]: Protection Plans
- link "Deposits" [ref=e86] [cursor=pointer]:
- /url: /deposits
- generic [ref=e88]:
- generic [ref=e90]: Deposits
- link "Products" [ref=e91] [cursor=pointer]:
- /url: /products
- generic [ref=e93]:
- generic [ref=e95]: Products
- link "Discounts" [ref=e96] [cursor=pointer]:
- /url: /discounts
- generic [ref=e98]:
- generic [ref=e100]: Discounts
- generic [ref=e101]:
- option "Emails" [ref=e102] [cursor=pointer]:
- generic [ref=e104]:
- generic [ref=e106]: Emails
- generic [ref=e110]:
- text:
- generic [ref=e112]: Admin
- link "Integrations" [ref=e113] [cursor=pointer]:
- /url: /connected-apps
- generic [ref=e115]:
- generic [ref=e117]: Integrations
- link "User & Roles" [ref=e118] [cursor=pointer]:
- /url: /users
- generic [ref=e120]:
- generic [ref=e122]: User & Roles
- generic [ref=e123]:
- option "Booking Portal" [ref=e124] [cursor=pointer]:
- generic [ref=e126]:
- generic [ref=e128]: Booking Portal
- generic [ref=e132]:
- text:
- generic [ref=e133]:
- option "JaneAI" [ref=e134] [cursor=pointer]:
- generic [ref=e136]:
- generic [ref=e138]: JaneAI
- generic [ref=e142]:
- text:
- generic [ref=e144]: Feedback
- link "Voting Portal" [ref=e145] [cursor=pointer]:
- /url: /voting-portal
- generic [ref=e147]:
- generic [ref=e149]: Voting Portal
- generic [ref=e152]:
- button "AS Andreas Stadler andreas.stadler@storeroom.at" [ref=e155] [cursor=pointer]:
- generic [ref=e158]: AS
- generic [ref=e159]:
- generic [ref=e160]: Andreas Stadler
- generic "andreas.stadler@storeroom.at" [ref=e161]
- generic [ref=e162]:
- generic:
- text:
- text:
- button [ref=e163] [cursor=pointer]:
- generic [ref=e165]:
- main [ref=e166]:
- generic [ref=e168]:
- generic [ref=e170]:
- generic [ref=e171]:
- link "Invoices" [ref=e172] [cursor=pointer]:
- /url: /invoices
- generic [ref=e173]: Invoices
- generic [ref=e174]:
- generic [ref=e175]: INV-2108663
- generic [ref=e180]: Open
- button "Actions" [ref=e182] [cursor=pointer]:
- generic [ref=e183]:
- text: Actions
- generic [ref=e184]:
- generic:
- generic [ref=e186]:
- generic [ref=e188]:
- heading "General" [level=3] [ref=e192]
- table [ref=e195]:
- rowgroup [ref=e196]:
- row "Location Vienna South" [ref=e197]:
- rowheader "Location" [ref=e198]
- cell "Vienna South" [ref=e199]:
- generic [ref=e201]: Vienna South
- row "Issue date 20 Aug 2026" [ref=e202]:
- rowheader "Issue date" [ref=e203]
- cell "20 Aug 2026" [ref=e204]:
- generic [ref=e206]: 20 Aug 2026
- row "Due date 22 Aug 2026" [ref=e207]:
- rowheader "Due date" [ref=e208]
- cell "22 Aug 2026" [ref=e209]:
- generic [ref=e211]: 22 Aug 2026
- row "Total €720.00" [ref=e212]:
- rowheader "Total" [ref=e213]
- cell "€720.00" [ref=e214]:
- generic [ref=e216]: €720.00
- row "Amount due €720.00" [ref=e217]:
- rowheader "Amount due" [ref=e218]
- cell "€720.00" [ref=e219]:
- generic [ref=e221]: €720.00
- row "Period -" [ref=e222]:
- rowheader "Period" [ref=e223]
- cell "-" [ref=e224]:
- generic [ref=e226]: "-"
- row "Payment option Manual" [ref=e227]:
- rowheader "Payment option" [ref=e228]
- cell "Manual" [ref=e229]:
- generic [ref=e231]: Manual
- row "Payment link https://invoice.stripe.com/i/acct_1MeJfDB0vsavZFES/test_YWNjdF8xTWVKZkRCMHZzYXZaRkVTLF9WNmNhd1MzVHJUcE9YZ2tGNzZOMzdzdkFqVEREeEFOLDE3Nzc0NzY0MQ02003UdUOVU4?s=ap" [ref=e232]:
- rowheader "Payment link" [ref=e233]
- cell "https://invoice.stripe.com/i/acct_1MeJfDB0vsavZFES/test_YWNjdF8xTWVKZkRCMHZzYXZaRkVTLF9WNmNhd1MzVHJUcE9YZ2tGNzZOMzdzdkFqVEREeEFOLDE3Nzc0NzY0MQ02003UdUOVU4?s=ap" [ref=e234]:
- generic [ref=e235]:
- generic [ref=e238]: https://invoice.stripe.com/i/acct_1MeJfDB0vsavZFES/test_YWNjdF8xTWVKZkRCMHZzYXZaRkVTLF9WNmNhd1MzVHJUcE9YZ2tGNzZOMzdzdkFqVEREeEFOLDE3Nzc0NzY0MQ02003UdUOVU4?s=ap
- button [ref=e240] [cursor=pointer]:
- generic [ref=e242]:
- generic [ref=e244]:
- heading "Customer details" [level=3] [ref=e248]
- table [ref=e251]:
- rowgroup [ref=e252]:
- row "Name Raymond Schmeler" [ref=e253]:
- rowheader "Name" [ref=e254]
- cell "Raymond Schmeler" [ref=e255]:
- link "Raymond Schmeler" [ref=e258] [cursor=pointer]:
- /url: /customers/53809381
- generic [ref=e260]: Raymond Schmeler
- row "Customer type Private" [ref=e261]:
- rowheader "Customer type" [ref=e262]
- cell "Private" [ref=e263]:
- generic [ref=e265]: Private
- row "Email angie8@yahoo.com" [ref=e266]:
- rowheader "Email" [ref=e267]
- cell "angie8@yahoo.com" [ref=e268]:
- link "angie8@yahoo.com" [ref=e271] [cursor=pointer]:
- /url: mailto:angie8@yahoo.com
- row "Phone number +43 50 0172 4097" [ref=e272]:
- rowheader "Phone number" [ref=e273]
- cell "+43 50 0172 4097" [ref=e274]:
- generic [ref=e276]: +43 50 0172 4097
- row "Billing address Wunsch Ranch 85166-7364 Stratford Austria" [ref=e277]:
- rowheader "Billing address" [ref=e278]
- cell "Wunsch Ranch 85166-7364 Stratford Austria" [ref=e279]:
- generic [ref=e281]: Wunsch Ranch 85166-7364 Stratford Austria
- generic [ref=e283]:
- heading "Payments" [level=3] [ref=e287]
- generic [ref=e291]:
- table [ref=e295]:
- rowgroup [ref=e296]:
- row "Total Status Invoice no. Date Payment method" [ref=e297]:
- columnheader "Total" [ref=e298]:
- button "Total" [ref=e299] [cursor=pointer]:
- generic [ref=e301]: Total
- generic [ref=e304]:
- columnheader "Status" [ref=e305]:
- button "Status" [ref=e306] [cursor=pointer]:
- generic [ref=e308]: Status
- generic [ref=e311]:
- columnheader "Invoice no." [ref=e312]:
- button "Invoice no." [ref=e313] [cursor=pointer]:
- generic [ref=e315]: Invoice no.
- generic [ref=e318]:
- columnheader "Date" [ref=e319]:
- button "Date" [ref=e320] [cursor=pointer]:
- generic [ref=e322]: Date
- generic [ref=e325]:
- columnheader "Payment method" [ref=e326]:
- button "Payment method" [ref=e327] [cursor=pointer]:
- generic [ref=e329]: Payment method
- generic [ref=e332]:
- row [ref=e333]:
- columnheader [ref=e334]
- rowgroup [ref=e335]:
- row "€720.00 Not paid yet INV-2108663 20 Aug 2026" [ref=e336]:
- cell "€720.00" [ref=e337]:
- generic [ref=e338]: €720.00
- cell "Not paid yet" [ref=e339]:
- generic [ref=e343]: Not paid yet
- cell "INV-2108663" [ref=e344]:
- generic [ref=e345]: INV-2108663
- cell "20 Aug 2026" [ref=e346]:
- generic [ref=e347]: 20 Aug 2026
- cell [ref=e348]
- generic [ref=e351]:
- generic [ref=e352]:
- generic [ref=e353]: "Items per page:"
- combobox [ref=e356]:
- generic [ref=e358] [cursor=pointer]:
- generic [ref=e360]: "10"
- combobox "Items per page:": "10"
- generic [ref=e362]:
- generic [ref=e363]: 1-1 of 1
- generic [ref=e364]:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- generic [ref=e367]:
- heading "Late Fees" [level=3] [ref=e372]
- generic [ref=e376]:
- table [ref=e380]:
- rowgroup [ref=e381]:
- row "Invoice no. Invoice note Created by Total Status Issue date Due date" [ref=e382]:
- columnheader "Invoice no." [ref=e383]:
- generic [ref=e386]: Invoice no.
- columnheader "Invoice note" [ref=e387]:
- generic [ref=e390]: Invoice note
- columnheader "Created by" [ref=e391]:
- generic [ref=e394]: Created by
- columnheader "Total" [ref=e395]:
- generic [ref=e398]: Total
- columnheader "Status" [ref=e399]:
- generic [ref=e402]: Status
- columnheader "Issue date" [ref=e403]:
- generic [ref=e406]: Issue date
- columnheader "Due date" [ref=e407]:
- generic [ref=e410]: Due date
- row [ref=e411]:
- columnheader [ref=e412]
- rowgroup [ref=e413]:
- row "No data yet" [ref=e414]:
- cell "No data yet" [ref=e415]:
- generic [ref=e416]: No data yet
- generic [ref=e419]:
- generic [ref=e420]:
- generic [ref=e421]: "Items per page:"
- combobox [ref=e424]:
- generic [ref=e426] [cursor=pointer]:
- generic [ref=e428]: "10"
- combobox "Items per page:": "10"
- generic [ref=e430]:
- generic [ref=e431]: 0-0 of 0
- generic [ref=e432]:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- button [disabled]:
- generic:
- generic:
- generic:
- 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
- dialog:
- generic [ref=e435]:
- generic [ref=e436]:
- generic [ref=e438]:
- generic [ref=e439]:
- button [ref=e440] [cursor=pointer]:
- generic [ref=e442]:
- heading "Issue Credit Note" [level=2] [ref=e444]
- button "Save" [ref=e446] [cursor=pointer]:
- generic [ref=e447]: Save
- separator [ref=e448]
- generic [ref=e450]:
- group "Invoice INV-2108663 Open" [ref=e451]:
- heading "Invoice INV-2108663 Open" [level=3] [ref=e453]:
- generic [ref=e455]:
- text: Invoice INV-2108663
- generic [ref=e457]: Open
- generic [ref=e460]:
- generic [ref=e462]:
- textbox "Reason *" [ref=e464]: Example reason!
- generic:
- generic: Reason *
- alert [ref=e465]
- group "Items to credit" [ref=e467]:
- heading "Items to credit" [level=3] [ref=e469]:
- generic [ref=e471]: Items to credit
- generic [ref=e472]:
- generic [ref=e473]:
- table [ref=e475]:
- rowgroup [ref=e476]:
- row "Description Credit QTY Price VAT Net credit amount" [ref=e477]:
- columnheader "Description" [ref=e478]
- columnheader "Credit QTY" [ref=e479]
- columnheader "Price" [ref=e480]
- columnheader "VAT" [ref=e481]
- columnheader "Net credit amount" [ref=e482]
- rowgroup [ref=e483]:
- row "Generic Product KbeVkL Generic Product KbeVkL €200.00 20% 600 €" [ref=e484]:
- cell "Generic Product KbeVkL Generic Product KbeVkL" [ref=e485]:
- generic [ref=e488]:
- generic [ref=e490]:
- generic [ref=e491]:
- checkbox "Generic Product KbeVkL" [checked] [ref=e492] [cursor=pointer]
- generic [ref=e493] [cursor=pointer]: Generic Product KbeVkL
- cell [ref=e494]:
- generic [ref=e495]:
- combobox [ref=e497]:
- generic [ref=e499]:
- generic [ref=e501]: "3"
- combobox [ref=e502]
- button [ref=e504] [cursor=pointer]:
- alert [ref=e505]
- cell "€200.00" [ref=e507]
- cell "20%" [ref=e508]
- cell "600 €" [ref=e509]:
- generic [ref=e510]:
- generic [ref=e513]:
- spinbutton [active] [ref=e514]: "600"
- generic [ref=e516]: €
- alert [ref=e517]
- alert [ref=e519]
- generic [ref=e523]:
- generic [ref=e524]:
- generic [ref=e525]: Total excl.VAT
- generic [ref=e526]: €600.00
- generic [ref=e527]:
- generic [ref=e528]: VAT
- generic [ref=e529]: €120.00
- generic [ref=e530]:
- generic [ref=e531]: Total incl.VAT
- generic [ref=e532]: €720.00
- generic [ref=e534]:
- generic [ref=e536]:
- generic [ref=e537]: The customer will receive an email with the credit note + an adjusted invoice attached. The invoice will be adjusted with the credited amount. The payment link will be updated for the correct amount as well.
- 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 |
```