# 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/discount/discount-create.spec.ts >> creates a discount reusing a code for a different billing plan - Location: src/manager/tests/e2e/discount/discount-create.spec.ts:184:5 # Error details ``` Test timeout of 90000ms exceeded. ``` ``` Error: page.waitForURL: Test timeout of 90000ms exceeded. =========================== logs =========================== waiting for navigation until "load" ============================================================ ``` # Page snapshot ```yaml - generic [active] [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] - list [ref=e19]: - generic [ref=e21]: Dashboard - link "Tasks" [ref=e23] [cursor=pointer]: - /url: /tasks - link "Facility maps" [ref=e30] [cursor=pointer]: - /url: /facility-map - generic [ref=e31]: 󰧾 - link "Analytics" [ref=e35] [cursor=pointer]: - /url: /dashboard - generic [ref=e36]: 󱖶 - generic [ref=e40]: Sales - link "Bookings" [ref=e42] [cursor=pointer]: - /url: /bookings - generic [ref=e43]: 󰇡 - link "Customers" [ref=e47] [cursor=pointer]: - /url: /customers - generic [ref=e48]: 󰀏 - link "Invoices" [ref=e52] [cursor=pointer]: - /url: /invoices - generic [ref=e53]: 󰷉 - link "Credit notes" [ref=e57] [cursor=pointer]: - /url: /credit-notes - link "Units" [ref=e64] [cursor=pointer]: - /url: /units - generic [ref=e65]: 󰍀 - generic [ref=e69]: Site management - link "Locations" [ref=e71] [cursor=pointer]: - /url: /locations - generic [ref=e72]: 󰟙 - link "Unit types" [ref=e76] [cursor=pointer]: - /url: /unit-types - generic [ref=e77]: 󰆧 - link "Protection Plans" [ref=e81] [cursor=pointer]: - /url: /insurances - generic [ref=e82]: 󰳌 - link "Deposits" [ref=e86] [cursor=pointer]: - /url: /deposits - generic [ref=e87]: 󱙆 - link "Products" [ref=e91] [cursor=pointer]: - /url: /products - generic [ref=e92]: 󰄑 - link "Discounts" [ref=e96] [cursor=pointer]: - /url: /discounts - generic [ref=e97]: 󰓼 - generic [ref=e101]: - option "Emails" [ref=e102] [cursor=pointer]: - generic [ref=e103]: 󰻨 - generic [ref=e107]: 󰅀 - text: 󱡰 󰁥 - link "Document templates" [ref=e111] [cursor=pointer]: - /url: /document-templates - generic [ref=e112]: 󰷉 - generic [ref=e116]: Admin - link "Integrations" [ref=e118] [cursor=pointer]: - /url: /connected-apps - generic [ref=e119]: 󱘖 - link "User & Roles" [ref=e123] [cursor=pointer]: - /url: /users - generic [ref=e124]: 󰭘 - generic [ref=e128]: - option "Booking Portal" [ref=e129] [cursor=pointer]: - generic [ref=e130]: 󱃁 - generic [ref=e134]: 󰅀 - text: 󰖟 󰟙 - generic [ref=e138]: - option "JaneAI" [ref=e139] [cursor=pointer]: - generic [ref=e140]: 󱙺 - generic [ref=e144]: 󰅀 - text: 󱜹 - generic [ref=e148]: Feedback - link "Voting Portal" [ref=e150] [cursor=pointer]: - /url: /voting-portal - generic [ref=e151]: 󰔔 - generic [ref=e157]: - button "AS Andreas Stadler andreas.stadler@storeroom.at" [ref=e160] [cursor=pointer]: - generic [ref=e161]: AS - generic [ref=e164]: - generic [ref=e165]: Andreas Stadler - generic "andreas.stadler@storeroom.at" [ref=e166] - generic [ref=e167]: 󰇙 - generic: 󰗊 󰅀 󰷖 󰍃 - button [ref=e168] [cursor=pointer]: - generic [ref=e169]: 󰋽 - main [ref=e171]: - generic [ref=e173]: - generic [ref=e175]: - generic [ref=e176]: Discounts - link "Create discount" [ref=e179] [cursor=pointer]: - /url: /discounts/create - generic [ref=e180]: 󰐕 - generic [ref=e184]: - generic [ref=e186]: - button [ref=e187] [cursor=pointer]: - generic [ref=e188]: - heading "Filters" [level=3] [ref=e191] - generic [ref=e193]: - button [ref=e195]: - generic [ref=e196]: - generic [ref=e197]: 󰑐 - text: Reset filters - generic [ref=e199]: 󰅀 - generic [ref=e207]: - generic [ref=e212]: - generic [ref=e213]: 󰍉 - generic [ref=e215]: - generic: Search - textbox "Search" [ref=e216] - text: 󰅙 - combobox [ref=e220]: - generic [ref=e221]: - generic: Location - combobox "Location" [ref=e223] - button [ref=e225] [cursor=pointer]: 󰍝 - generic [ref=e227]: - table [ref=e231]: - rowgroup [ref=e232]: - row [ref=e233]: - columnheader [ref=e234]: - button "Name" [ref=e235] [cursor=pointer]: - generic [ref=e238]: 󰁝 - columnheader [ref=e241]: - button "Location" [ref=e242] [cursor=pointer]: - generic [ref=e245]: 󰁝 - columnheader "Terms" [ref=e248] - columnheader "Codes" [ref=e252] - columnheader "Redemptions" [ref=e256] - columnheader "Redeemable till" [ref=e260] - row [ref=e264]: - columnheader [ref=e265] - rowgroup [ref=e266]: - row [ref=e267]: - cell [ref=e268]: - link "Frozen Sale 1BNp0r" [ref=e269] [cursor=pointer]: - /url: /discounts/808599373 - cell [ref=e271]: - link "Storeroom Innsbruck" [ref=e272] [cursor=pointer]: - /url: /discounts/808599373 - cell [ref=e274]: - link "41% off once" [ref=e275] [cursor=pointer]: - /url: /discounts/808599373 - cell [ref=e277]: - link "REUSEDLOCATION" [ref=e278] [cursor=pointer]: - /url: /discounts/808599373 - cell [ref=e280]: - link "0" [ref=e281] [cursor=pointer]: - /url: /discounts/808599373 - cell [ref=e283]: - link "-" [ref=e284] [cursor=pointer]: - /url: /discounts/808599373 - row [ref=e286]: - cell [ref=e287]: - link "Fresh Sale hUxtz7" [ref=e288] [cursor=pointer]: - /url: /discounts/1760505757 - cell [ref=e290]: - link "Storeroom Innsbruck" [ref=e291] [cursor=pointer]: - /url: /discounts/1760505757 - cell [ref=e293]: - link "8% off once" [ref=e294] [cursor=pointer]: - /url: /discounts/1760505757 - cell [ref=e296]: - link "REUSEDPLAN" [ref=e297] [cursor=pointer]: - /url: /discounts/1760505757 - cell [ref=e299]: - link "0" [ref=e300] [cursor=pointer]: - /url: /discounts/1760505757 - cell [ref=e302]: - link "-" [ref=e303] [cursor=pointer]: - /url: /discounts/1760505757 - row [ref=e305]: - cell [ref=e306]: - link "Bespoke Sale NDtBM9" [ref=e307] [cursor=pointer]: - /url: /discounts/1466376243 - cell [ref=e309]: - link "Vienna South" [ref=e310] [cursor=pointer]: - /url: /discounts/1466376243 - cell [ref=e312]: - link "25% off once" [ref=e313] [cursor=pointer]: - /url: /discounts/1466376243 - cell [ref=e315]: - link "-" [ref=e316] [cursor=pointer]: - /url: /discounts/1466376243 - cell [ref=e318]: - link "0" [ref=e319] [cursor=pointer]: - /url: /discounts/1466376243 - cell [ref=e321]: - link "-" [ref=e322] [cursor=pointer]: - /url: /discounts/1466376243 - row [ref=e324]: - cell [ref=e325]: - link "Sleek Sale RqGa1A" [ref=e326] [cursor=pointer]: - /url: /discounts/2132611397 - cell [ref=e328]: - link "Storeroom Innsbruck" [ref=e329] [cursor=pointer]: - /url: /discounts/2132611397 - cell [ref=e331]: - link "40% off once" [ref=e332] [cursor=pointer]: - /url: /discounts/2132611397 - cell [ref=e334]: - link "REUSEDPRODUCT" [ref=e335] [cursor=pointer]: - /url: /discounts/2132611397 - cell [ref=e337]: - link "0" [ref=e338] [cursor=pointer]: - /url: /discounts/2132611397 - cell [ref=e340]: - link "-" [ref=e341] [cursor=pointer]: - /url: /discounts/2132611397 - row [ref=e343]: - cell [ref=e344]: - link "Small Sale 82Shrp" [ref=e345] [cursor=pointer]: - /url: /discounts/951124457 - cell [ref=e347]: - link "Storeroom Innsbruck" [ref=e348] [cursor=pointer]: - /url: /discounts/951124457 - cell [ref=e350]: - link "6% off once" [ref=e351] [cursor=pointer]: - /url: /discounts/951124457 - cell [ref=e353]: - link "REUSEDPLAN" [ref=e354] [cursor=pointer]: - /url: /discounts/951124457 - cell [ref=e356]: - link "0" [ref=e357] [cursor=pointer]: - /url: /discounts/951124457 - cell [ref=e359]: - link "-" [ref=e360] [cursor=pointer]: - /url: /discounts/951124457 - row [ref=e362]: - cell [ref=e363]: - link "Modern Sale zovIAz" [ref=e364] [cursor=pointer]: - /url: /discounts/816673366 - cell [ref=e366]: - link "Storeroom Innsbruck" [ref=e367] [cursor=pointer]: - /url: /discounts/816673366 - cell [ref=e369]: - link "38% off once" [ref=e370] [cursor=pointer]: - /url: /discounts/816673366 - cell [ref=e372]: - link "REUSEDPRODUCT" [ref=e373] [cursor=pointer]: - /url: /discounts/816673366 - cell [ref=e375]: - link "0" [ref=e376] [cursor=pointer]: - /url: /discounts/816673366 - cell [ref=e378]: - link "-" [ref=e379] [cursor=pointer]: - /url: /discounts/816673366 - row [ref=e381]: - cell [ref=e382]: - link "Tasty Sale frhmWo" [ref=e383] [cursor=pointer]: - /url: /discounts/1661166278 - cell [ref=e385]: - link "Vienna South" [ref=e386] [cursor=pointer]: - /url: /discounts/1661166278 - cell [ref=e388]: - link "15% off once" [ref=e389] [cursor=pointer]: - /url: /discounts/1661166278 - cell [ref=e391]: - link "-" [ref=e392] [cursor=pointer]: - /url: /discounts/1661166278 - cell [ref=e394]: - link "0" [ref=e395] [cursor=pointer]: - /url: /discounts/1661166278 - cell [ref=e397]: - link "-" [ref=e398] [cursor=pointer]: - /url: /discounts/1661166278 - row [ref=e400]: - cell [ref=e401]: - link "Unbranded Sale dK9eJm" [ref=e402] [cursor=pointer]: - /url: /discounts/21713904 - cell [ref=e404]: - link "Storeroom Innsbruck" [ref=e405] [cursor=pointer]: - /url: /discounts/21713904 - cell [ref=e407]: - link "€5.00 off once" [ref=e408] [cursor=pointer]: - /url: /discounts/21713904 - cell [ref=e410]: - link "FIVER" [ref=e411] [cursor=pointer]: - /url: /discounts/21713904 - cell [ref=e413]: - link "0" [ref=e414] [cursor=pointer]: - /url: /discounts/21713904 - cell [ref=e416]: - link "-" [ref=e417] [cursor=pointer]: - /url: /discounts/21713904 - row [ref=e419]: - cell [ref=e420]: - link "Oriental Sale pjFRYu" [ref=e421] [cursor=pointer]: - /url: /discounts/1931953252 - cell [ref=e423]: - link "Vienna South" [ref=e424] [cursor=pointer]: - /url: /discounts/1931953252 - cell [ref=e426]: - link "30% off once" [ref=e427] [cursor=pointer]: - /url: /discounts/1931953252 - cell [ref=e429]: - link "-" [ref=e430] [cursor=pointer]: - /url: /discounts/1931953252 - cell [ref=e432]: - link "0/100" [ref=e433] [cursor=pointer]: - /url: /discounts/1931953252 - cell [ref=e435]: - link "30 Nov 2026, 00:19" [ref=e436] [cursor=pointer]: - /url: /discounts/1931953252 - row [ref=e438]: - cell [ref=e439]: - link "Tasty Sale rom8LR" [ref=e440] [cursor=pointer]: - /url: /discounts/781333704 - cell [ref=e442]: - link "Vienna South" [ref=e443] [cursor=pointer]: - /url: /discounts/781333704 - cell [ref=e445]: - link "€10.00 off once" [ref=e446] [cursor=pointer]: - /url: /discounts/781333704 - cell [ref=e448]: - link "-" [ref=e449] [cursor=pointer]: - /url: /discounts/781333704 - cell [ref=e451]: - link "0" [ref=e452] [cursor=pointer]: - /url: /discounts/781333704 - cell [ref=e454]: - link "-" [ref=e455] [cursor=pointer]: - /url: /discounts/781333704 - generic [ref=e459]: - generic [ref=e460]: - generic [ref=e461]: "Items per page:" - combobox [ref=e464]: - generic [ref=e466] [cursor=pointer]: - generic [ref=e467]: "10" - combobox "Items per page:": "10" - generic [ref=e469]: 󰍝 - generic [ref=e471]: 1-10 of 67 - generic [ref=e472]: - button [disabled]: - generic: 󰘀 - button [disabled]: - generic: 󰅁 - button [ref=e473] [cursor=pointer]: - generic [ref=e474]: 󰅂 - button [ref=e476] [cursor=pointer]: - generic [ref=e477]: 󰘁 - 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 ``` # Test source ```ts 1 | import { BaseDialog } from '@/manager/shared/base/BaseDialog'; 2 | import { DiscountBillingPlanCard } from '@/manager/modules/discount/components/DiscountBillingPlanCard'; 3 | import { DiscountCreateCodeFieldSet } from '@/manager/modules/discount/components/DiscountCreateCodeFieldSet'; 4 | import { DiscountCreateDurationFieldSet } from '@/manager/modules/discount/components/DiscountCreateDurationFieldSet'; 5 | import { DiscountCreateGeneralFieldSet } from '@/manager/modules/discount/components/DiscountCreateGeneralFieldSet'; 6 | import { DiscountProductCard } from '@/manager/modules/discount/components/DiscountProductCard'; 7 | import { DiscountCreateRestrictionsFieldSet } from '@/manager/modules/discount/components/DiscountCreateRestrictionsFieldSet'; 8 | import { DiscountCreateTypeFieldSet } from '@/manager/modules/discount/components/DiscountCreateTypeFieldSet'; 9 | import { DiscountCreateData } from '@/manager/modules/discount/discount-types'; 10 | import { DiscountDetailsPage } from '@/manager/modules/discount/views/DiscountDetailsPage'; 11 | import { getDialogErrorsHost, getSnackbarHost } from '@/manager/shared/utils/locator-utils'; 12 | import { getDetailsPageRegExpUrl } from '@/manager/shared/utils/url-utils'; 13 | import { Page } from '@playwright/test'; 14 | 15 | export class DiscountCreateDialog extends BaseDialog { 16 | readonly generalFieldSet = new DiscountCreateGeneralFieldSet(this.main); 17 | readonly productCard = new DiscountProductCard(this.main); 18 | readonly billingPlanCard = new DiscountBillingPlanCard(this.main); 19 | readonly typeFieldSet = new DiscountCreateTypeFieldSet(this.main); 20 | readonly durationFieldSet = new DiscountCreateDurationFieldSet(this.main); 21 | readonly restrictionsFieldSet = new DiscountCreateRestrictionsFieldSet(this.main); 22 | readonly codeFieldSet = new DiscountCreateCodeFieldSet(this.main); 23 | readonly errors = getDialogErrorsHost(this.main); 24 | readonly snackbar = getSnackbarHost(this.host, 'Discount created successfully'); 25 | 26 | constructor(host: Page) { 27 | super(host, 'discount-create-dialog'); 28 | } 29 | 30 | async goto(): Promise { 31 | await this.host.goto('/discounts/create'); 32 | } 33 | 34 | async create(data: DiscountCreateData): Promise { 35 | await this.fill(data); 36 | await Promise.all([ 37 | this.snackbar.waitFor(), > 38 | this.host.waitForURL(getDetailsPageRegExpUrl('discounts')), | ^ Error: page.waitForURL: Test timeout of 90000ms exceeded. 39 | this.submit(), 40 | ]); 41 | return new DiscountDetailsPage(this.host); 42 | } 43 | 44 | async fill(data: DiscountCreateData): Promise { 45 | await this.generalFieldSet.nameTextField.fill(data.name); 46 | await this.generalFieldSet.locationAutocomplete.fill(data.location.name); 47 | 48 | const products = data.products ?? []; 49 | const deposits = data.deposits ?? []; 50 | 51 | if (products.length > 0 || deposits.length > 0) { 52 | const productDialog = await this.productCard.openDiscountEditProductsDialog(false); 53 | await productDialog.select({ products, deposits }); 54 | } 55 | 56 | if (data.billingPlans && data.billingPlans.length > 0) { 57 | const billingPlanDialog = await this.billingPlanCard.openDiscountEditBillingPlansDialog(false); 58 | await billingPlanDialog.select(data.billingPlans); 59 | } 60 | 61 | await this.typeFieldSet.typeRadioGroup.check(data.type); 62 | await this.typeFieldSet.valueNumberField.fill(data.value); 63 | 64 | await this.durationFieldSet.durationRadioGroup.check(data.duration.option); 65 | 66 | if (data.duration.option === 'multiple_months' && data.duration.amount != null) { 67 | await this.durationFieldSet.multipleMonthsDurationNumberField.fill(data.duration.amount); 68 | } 69 | 70 | if (data.expirationDate) { 71 | await this.restrictionsFieldSet.expiryDateCheckbox.set(true); 72 | await this.restrictionsFieldSet.expiryDateTimePicker.fill(data.expirationDate); 73 | } 74 | 75 | if (data.usageLimit != null) { 76 | await this.restrictionsFieldSet.usageLimitCheckbox.set(true); 77 | await this.restrictionsFieldSet.usageLimitNumberField.fill(data.usageLimit); 78 | } 79 | 80 | if (data.code.active && data.code.value) { 81 | await this.codeFieldSet.codeSection.codeSwitch.set(data.code.active); 82 | await this.codeFieldSet.codeSection.codeTextField.fill(data.code.value); 83 | } 84 | } 85 | 86 | async submit(): Promise { 87 | await this.submitButton.click(); 88 | } 89 | } 90 | ```