17 KiB
17 KiB
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: workflows/inquiry-lifecycle.spec.ts >> Inquiry Lifecycle >> respond modal opens on inquiry detail
- Location: e2e/tests/workflows/inquiry-lifecycle.spec.ts:135:7
Error details
Error: locator.click: Error: strict mode violation: locator('button[onclick="showRespondModal()"]') resolved to 2 elements:
1) <button onclick="showRespondModal()" class="inline-flex items-center px-6 py-2.5 bg-white text-navy font-medium rounded-xl hover:bg-blue-50 transition text-sm">…</button> aka getByRole('button', { name: 'Respond' })
2) <button onclick="showRespondModal()" class="w-full px-6 py-2.5 bg-navy text-white rounded-xl font-semibold hover:bg-navy/90 transition text-sm inline-flex items-center justify-center gap-2">…</button> aka getByRole('button', { name: 'Send Response' })
Call log:
- waiting for locator('button[onclick="showRespondModal()"]')
Page snapshot
- generic [ref=e2]:
- complementary [ref=e3]:
- generic [ref=e4]:
- img "Al Hammadi" [ref=e6]
- img "Al Hammadi" [ref=e8]
- navigation [ref=e9]:
- link [ref=e10] [cursor=pointer]:
- /url: /analytics/dashboard/
- img [ref=e11]
- link [ref=e16] [cursor=pointer]:
- /url: /
- img [ref=e17]
- button [ref=e20] [cursor=pointer]:
- img [ref=e21]
- link [ref=e22] [cursor=pointer]:
- /url: /complaints/
- img [ref=e23]
- link [ref=e26] [cursor=pointer]:
- /url: /inquiries/
- img [ref=e27]
- link [ref=e30] [cursor=pointer]:
- /url: /observations/
- img [ref=e31]
- button [ref=e35] [cursor=pointer]:
- img [ref=e36]
- link [ref=e40] [cursor=pointer]:
- /url: /appreciation/
- img [ref=e41]
- link [ref=e43] [cursor=pointer]:
- /url: /suggestions/?feedback_type=suggestion
- img [ref=e44]
- button [ref=e47] [cursor=pointer]:
- img [ref=e48]
- button [ref=e52] [cursor=pointer]:
- img [ref=e53]
- link [ref=e58] [cursor=pointer]:
- /url: /organizations/departments/
- img [ref=e59]
- link [ref=e63] [cursor=pointer]:
- /url: /organizations/patients/
- img [ref=e64]
- button [ref=e68] [cursor=pointer]:
- img [ref=e69]
- button [ref=e74] [cursor=pointer]:
- img [ref=e75]
- button [ref=e82] [cursor=pointer]:
- img [ref=e83]
- link [ref=e86] [cursor=pointer]:
- /url: /notifications/send-sms/
- img [ref=e87]
- link [ref=e89] [cursor=pointer]:
- /url: /config/
- img [ref=e90]
- link [ref=e93] [cursor=pointer]:
- /url: /config/deleted/
- img [ref=e94]
- link [ref=e97] [cursor=pointer]:
- /url: /accounts/acknowledgements/my-acknowledgements/
- img [ref=e98]
- button [ref=e104] [cursor=pointer]:
- img [ref=e105]
- button [ref=e108] [cursor=pointer]:
- img [ref=e109]
- button [ref=e114] [cursor=pointer]:
- img [ref=e115]
- generic [ref=e118]:
- link "🇬🇧" [ref=e119] [cursor=pointer]:
- /url: /core/set-language/?language=en
- generic [ref=e120]: 🇬🇧
- link "🇸🇦" [ref=e121] [cursor=pointer]:
- /url: /core/set-language/?language=ar
- generic [ref=e122]: 🇸🇦
- generic [ref=e123]:
- banner [ref=e124]:
- generic [ref=e125]:
- heading "Good morning, E2E! ☀️" [level=2] [ref=e126]
- paragraph [ref=e127]: Welcome to PX360 Patient Experience Management
- generic [ref=e128]:
- generic [ref=e129]:
- img [ref=e130]
- textbox "Search..." [ref=e133]
- button "10" [ref=e135] [cursor=pointer]:
- img [ref=e136]
- generic [ref=e139]: "10"
- generic [ref=e140]:
- link "🇬🇧 English" [ref=e141] [cursor=pointer]:
- /url: /core/set-language/?language=en
- generic [ref=e142]: 🇬🇧
- generic [ref=e143]: English
- link "🇸🇦 Arabic" [ref=e144] [cursor=pointer]:
- /url: /core/set-language/?language=ar
- generic [ref=e145]: 🇸🇦
- generic [ref=e146]: Arabic
- button "E2E Hospital Admin Hospital Admin E" [ref=e148] [cursor=pointer]:
- generic [ref=e149]:
- generic [ref=e150]: E2E Hospital Admin
- generic [ref=e151]: Hospital Admin
- generic [ref=e152]: E
- img [ref=e153]
- main [ref=e155]:
- generic [ref=e157]:
- generic [ref=e158]:
- generic [ref=e159]:
- link "Inquiries" [ref=e160] [cursor=pointer]:
- /url: /inquiries/
- img [ref=e161]
- generic [ref=e163]: Detail
- generic [ref=e164]:
- heading "E2E automated test inquiry 1778178510420" [level=1] [ref=e165]
- generic [ref=e166]: Open
- generic [ref=e167]: Low
- generic [ref=e168]:
- generic [ref=e169]:
- img [ref=e170]
- text: INQ-20260507-2… |
- img [ref=e173]
- text: 2026-05-07
- button "Respond" [ref=e175] [cursor=pointer]:
- img [ref=e176]
- text: Respond
- generic [ref=e178]:
- generic [ref=e179]:
- generic [ref=e180]:
- generic [ref=e181]:
- img [ref=e183]
- heading "Inquiry Details" [level=5] [ref=e186]
- generic [ref=e188]:
- paragraph
- paragraph [ref=e189]: E2E automated test inquiry - please ignore
- paragraph
- generic [ref=e190]:
- generic [ref=e191]:
- img [ref=e193]
- heading "AI Analysis" [level=5] [ref=e196]
- generic [ref=e197]:
- generic [ref=e198]:
- heading "AI Summary (English)" [level=4] [ref=e199]
- paragraph [ref=e200]: This is an automated test inquiry. The sender has explicitly requested that the inquiry be ignored. Therefore, no further action is required.
- generic [ref=e201]:
- heading "AI Summary (Arabic)" [level=4] [ref=e202]
- paragraph [ref=e203]: هذا استفسار اختبار آلي. طلب المرسل صراحةً تجاهل الاستفسار. لذلك، لا يلزم اتخاذ أي إجراء إضافي.
- generic [ref=e204]:
- generic [ref=e205]:
- img [ref=e207]
- heading "Timeline" [level=5] [ref=e211]
- generic [ref=e213]:
- generic [ref=e214]:
- paragraph [ref=e215]: Inquiry Created
- paragraph [ref=e216]: Created by E2E PX Admin
- paragraph [ref=e217]: 2026-05-07 21:28
- generic [ref=e218]:
- paragraph [ref=e219]: Note
- paragraph [ref=e220]: AI analysis complete. Priority and summaries updated.
- paragraph [ref=e221]: 2026-05-07 21:28
- generic [ref=e222]:
- generic [ref=e223]:
- generic [ref=e224]:
- img [ref=e226]
- heading "Actions" [level=5] [ref=e229]
- generic [ref=e230]:
- button "Send Response" [ref=e231] [cursor=pointer]:
- img [ref=e232]
- text: Send Response
- button "Assign" [ref=e234] [cursor=pointer]:
- img [ref=e235]
- text: Assign
- generic [ref=e238]:
- generic [ref=e239]:
- generic [ref=e240]: Update Status
- combobox [ref=e241]:
- option "Open" [selected]
- option "In Progress"
- option "Contacted"
- option "Contacted, No Response"
- option "Resolved"
- option "Closed"
- button "Change Status" [ref=e242] [cursor=pointer]:
- img [ref=e243]
- text: Change Status
- link "Edit Inquiry" [ref=e248] [cursor=pointer]:
- /url: /inquiries/110e0bc6-636b-4dc1-ae52-21b0be9f4748/edit/
- img [ref=e249]
- text: Edit Inquiry
- link "Initiate RCA" [ref=e252] [cursor=pointer]:
- /url: /rca/create/?related_model=inquiry&related_id=110e0bc6-636b-4dc1-ae52-21b0be9f4748
- img [ref=e253]
- text: Initiate RCA
- link "Create QI Project" [ref=e256] [cursor=pointer]:
- /url: /projects/create/?related_model=inquiry&related_id=110e0bc6-636b-4dc1-ae52-21b0be9f4748
- img [ref=e257]
- text: Create QI Project
- generic [ref=e259]:
- paragraph [ref=e260]: Department Actions
- button "Send to Department" [ref=e261] [cursor=pointer]:
- img [ref=e262]
- text: Send to Department
- generic [ref=e265]:
- generic [ref=e266]:
- img [ref=e268]
- heading "Contact Information" [level=5] [ref=e271]
- generic [ref=e272]:
- generic [ref=e273]:
- generic [ref=e274]: Name
- generic [ref=e275]: E2E Test Contact 1778178510420
- generic [ref=e276]:
- generic [ref=e277]: Phone
- generic [ref=e278]: "0500000001"
- generic [ref=e279]:
- generic [ref=e280]: Email
- generic [ref=e281]: e2e-test-1778178510420@test.com
- generic [ref=e282]:
- heading "Status Timeline" [level=3] [ref=e283]:
- img [ref=e284]
- text: Status Timeline
- generic [ref=e288]:
- generic [ref=e290]: May 07, 2026 21:28
- generic [ref=e291]: Created
- generic [ref=e292]:
- generic [ref=e293]:
- img [ref=e295]
- heading "Organization" [level=5] [ref=e299]
- generic [ref=e300]:
- generic [ref=e301]:
- generic [ref=e302]: Hospital
- generic [ref=e303]: NUZHA
- generic [ref=e304]:
- generic [ref=e305]: Department
- generic [ref=e306]: Information Technology
- generic [ref=e307]:
- generic [ref=e308]: Location
- generic [ref=e309]: "-"
- generic [ref=e310]:
- generic [ref=e311]: Category
- generic [ref=e312]: General Information
- generic [ref=e313]:
- generic [ref=e314]: SHCT Taxonomy
- generic [ref=e315]: MANAGEMENT
- generic [ref=e316]:
- generic [ref=e317]: Priority
- generic [ref=e318]: Low
- generic [ref=e319]:
- generic [ref=e320]:
- img [ref=e322]
- heading "Notes" [level=5] [ref=e325]
- generic [ref=e327]:
- generic [ref=e328]:
- text: Staff Notes
- textbox "Add staff notes..." [ref=e329]
- generic [ref=e330]:
- text: Supervisor Notes
- textbox "Add supervisor notes..." [ref=e331]
- button "Save Notes" [ref=e332] [cursor=pointer]
- contentinfo [ref=e333]:
- paragraph [ref=e334]:
- text: Powered by
- link "tenhal.sa" [ref=e335] [cursor=pointer]:
- /url: https://tenhal.sa
Test source
61 | await auth.login('hospital_admin');
62 |
63 | await page.goto('/inquiries/');
64 | await page.waitForLoadState('domcontentloaded');
65 | await page.waitForTimeout(2000);
66 |
67 | if (inquiryReference) {
68 | const searchInput = page.locator('input[name="search"]');
69 | if (await searchInput.count() > 0) {
70 | await searchInput.fill(inquiryReference);
71 | await searchInput.press('Enter');
72 | await page.waitForLoadState('domcontentloaded');
73 | await page.waitForTimeout(1000);
74 | }
75 |
76 | const tableText = await page.locator('table').textContent();
77 | expect(tableText).toContain(inquiryReference);
78 | } else {
79 | const tableText = await page.locator('table').textContent();
80 | expect(tableText).toBeTruthy();
81 | }
82 | });
83 |
84 | test('inquiry list has filter and table', async ({ page }) => {
85 | const auth = new RoleAuthHelper(page);
86 | await auth.login('hospital_admin');
87 |
88 | await page.goto('/inquiries/');
89 | await page.waitForLoadState('domcontentloaded');
90 | await page.waitForTimeout(2000);
91 |
92 | const table = page.locator('table.data-table, table');
93 | expect(await table.count()).toBeGreaterThan(0);
94 |
95 | const filterForm = page.locator('form[method="get"]');
96 | expect(await filterForm.count()).toBeGreaterThan(0);
97 | });
98 |
99 | test('can access inquiry create form (authenticated)', async ({ page }) => {
100 | const auth = new RoleAuthHelper(page);
101 | await auth.login('hospital_admin');
102 |
103 | await page.goto('/inquiries/new/');
104 | await page.waitForLoadState('domcontentloaded');
105 | await page.waitForTimeout(2000);
106 |
107 | const form = page.locator('#inquiryForm, form[action*="inquiry_create"]');
108 | const hasForm = await form.count().then(c => c > 0);
109 | expect(hasForm).toBeTruthy();
110 | });
111 |
112 | test('inquiry detail page loads for open inquiry', async ({ page }) => {
113 | const auth = new RoleAuthHelper(page);
114 | await auth.login('hospital_admin');
115 |
116 | await page.goto('/inquiries/?status=open');
117 | await page.waitForLoadState('domcontentloaded');
118 | await page.waitForTimeout(2000);
119 |
120 | const firstRow = page.locator('table tbody tr').first();
121 | const hasRows = await firstRow.count().then(c => c > 0);
122 | if (!hasRows) {
123 | test.skip();
124 | return;
125 | }
126 |
127 | await firstRow.click();
128 | await page.waitForLoadState('domcontentloaded');
129 | await page.waitForTimeout(1000);
130 |
131 | const pageText = await page.textContent('body');
132 | expect(pageText).toContain('INQ-');
133 | });
134 |
135 | test('respond modal opens on inquiry detail', async ({ page }) => {
136 | const auth = new RoleAuthHelper(page);
137 | await auth.login('hospital_admin');
138 |
139 | await page.goto('/inquiries/?status=open');
140 | await page.waitForLoadState('domcontentloaded');
141 | await page.waitForTimeout(2000);
142 |
143 | const firstRow = page.locator('table tbody tr').first();
144 | const hasRows = await firstRow.count().then(c => c > 0);
145 | if (!hasRows) {
146 | test.skip();
147 | return;
148 | }
149 |
150 | await firstRow.click();
151 | await page.waitForLoadState('domcontentloaded');
152 | await page.waitForTimeout(1000);
153 |
154 | const respondBtn = page.locator('button[onclick="showRespondModal()"]');
155 | const hasRespond = await respondBtn.count().then(c => c > 0);
156 | if (!hasRespond) {
157 | test.skip();
158 | return;
159 | }
160 |
> 161 | await respondBtn.click();
| ^ Error: locator.click: Error: strict mode violation: locator('button[onclick="showRespondModal()"]') resolved to 2 elements:
162 | const modal = page.locator('#respondModal');
163 | await modal.waitFor({ state: 'visible', timeout: 5000 });
164 |
165 | const form = modal.locator('form#respondForm, form[action*="respond"]');
166 | expect(await form.count()).toBeGreaterThan(0);
167 |
168 | const closeBtn = modal.locator('button[onclick="closeRespondModal()"]');
169 | if (await closeBtn.count() > 0) {
170 | await closeBtn.click();
171 | }
172 | });
173 |
174 | test('inquiry list shows status badges', async ({ page }) => {
175 | const auth = new RoleAuthHelper(page);
176 | await auth.login('hospital_admin');
177 |
178 | await page.goto('/inquiries/');
179 | await page.waitForLoadState('domcontentloaded');
180 | await page.waitForTimeout(2000);
181 |
182 | const statusBadges = page.locator('span.rounded-full');
183 | const badgeCount = await statusBadges.count();
184 | expect(badgeCount).toBeGreaterThan(0);
185 | });
186 | });
187 |