18 KiB
18 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/rca-lifecycle.spec.ts >> RCA Workflow >> create RCA
- Location: e2e/tests/workflows/rca-lifecycle.spec.ts:21:7
Error details
Test timeout of 60000ms exceeded.
Error: page.click: Test timeout of 60000ms exceeded.
Call log:
- waiting for locator('button[type="submit"]')
- locator resolved to 2 elements. Proceeding with the first one: <button type="submit" class="w-full flex items-center gap-4 p-4 hover:bg-red-50 rounded-xl transition text-red-500">…</button>
- attempting click action
2 × waiting for element to be visible, enabled and stable
- element is not visible
- retrying click action
- waiting 20ms
2 × waiting for element to be visible, enabled and stable
- element is not visible
- retrying click action
- waiting 100ms
104 × waiting for element to be visible, enabled and stable
- element is not visible
- retrying click action
- waiting 500ms
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=e156]:
- generic [ref=e157]:
- link "RCA" [ref=e158] [cursor=pointer]:
- /url: /rca/
- img [ref=e159]
- generic [ref=e161]: New RCA
- heading "New Root Cause Analysis" [level=1] [ref=e162]:
- img [ref=e164]
- text: New Root Cause Analysis
- generic [ref=e169]:
- generic [ref=e170]:
- generic [ref=e171]:
- generic [ref=e172]: Title *
- textbox "Title *" [ref=e173]: E2E RCA Test 1778178899576
- generic [ref=e174]:
- generic [ref=e175]: Description *
- textbox "Description *" [ref=e176]: Test RCA description for E2E workflow testing
- generic [ref=e177]:
- text: Background
- textbox "Background" [ref=e178]: Background info for test
- generic [ref=e179]:
- text: Root Cause Summary
- textbox "Root Cause Summary" [active] [ref=e180]: Initial root cause summary
- generic [ref=e181]:
- generic [ref=e182]:
- text: Department
- combobox "Department" [ref=e183]:
- option "---------" [selected]
- option "Academic Education and Training Affairs"
- option "Accidents & Emergency"
- option "Anesthesia & OR Department"
- option "Business Development"
- option "Community Engagement"
- option "Contact Center Department"
- option "Continuous Medical Education Managment"
- option "Corporate Administration"
- option "Corporate Communication Department"
- option "Critical Care Department"
- option "Dental Department"
- option "Dermatology Department"
- option "Emergency Department"
- option "Executive Administration"
- option "FAMILY MEDICINE DEPARTMENT"
- option "Facility Management & Maintenance"
- option "Finance Department"
- option "Financial Collection & Claims Department"
- option "Food Services Department"
- option "Housekeeping & Hospitality Department"
- option "Human Resource"
- option "Infection Control"
- option "Information Technology"
- option "Innovation Communication Management"
- option "Inpatient Department"
- option "Internal Audit"
- option "Internal Medicine"
- option "Laboratory and Blood Bank"
- option "Laundry Department"
- option "Legal Affairs Department"
- option "Marketing Department"
- option "Medical Administration"
- option "Medical Ancillary Services"
- option "Medical Approvals Department"
- option "Medical Records Department"
- option "Nursing Department"
- option "OB/Gyne Department"
- option "ONCOLOGY"
- option "Ophthalmology Department"
- option "Outpatient Department"
- option "Patient Affairs Department"
- option "Patient Relations & Patient Experience Department"
- option "Pediatric Department"
- option "Pharmacy Department"
- option "Pharmacy Warehouse AlAziziyah"
- option "Porter Department"
- option "Radiology Department"
- option "Security Department"
- option "Senior Management Offices"
- option "Supply Chain"
- option "Support Services"
- option "Surgeries Department"
- option "TRANSFORMATION AND CHANGE MANAGEMENT"
- option "Talent Acquisition Department"
- option "Transportation Department"
- generic [ref=e184]:
- text: Status
- combobox "Status" [ref=e185]:
- option "Draft" [selected]
- option "In Progress"
- option "Under Review"
- option "Approved"
- option "Closed"
- generic [ref=e186]:
- text: Severity
- combobox "Severity" [ref=e187]:
- option "Low"
- option "Medium"
- option "High" [selected]
- option "Critical"
- generic [ref=e188]:
- text: Priority
- combobox "Priority" [ref=e189]:
- option "Low"
- option "Medium" [selected]
- option "High"
- option "Critical"
- generic [ref=e190]:
- text: Assigned To
- combobox "Assigned To" [ref=e191]:
- option "---------" [selected]
- option "IBRAHIM ABDELAZEEZ I ALSHUWAIER (IBRAHIM.ABDELAZEEZ@gmail.com)"
- option "TURKI ABDULAZIZ M ALKHAMIS (TURKI@hh.med.sa)"
- option "ZEENATH ABBONU KUNHIBI (ZEENATH@hh.med.sa)"
- option "ABEER MOHAMMED DAWII ALGHAMDI (abber@hh.med.sa)"
- option "ابرار الشمري (brr.lshmry@alhammadi.med.sa)"
- option "E2E Champion (e2e-champion@px360.test)"
- option "E2E Dept Manager (e2e-dept-manager@px360.test)"
- option "E2E Hospital Admin (e2e-hospital-admin@px360.test)"
- option "E2E PX Admin (e2e-px-admin@px360.test)"
- option "E2E PX Employee (e2e-px-employee@px360.test)"
- option "E2E Source User (e2e-source-user@px360.test)"
- option "E2E Staff (e2e-staff@px360.test)"
- option "E2E Viewer (e2e-viewer@px360.test)"
- option "هيا الرويلي (hy.lrwyly@alhammadi.med.sa)"
- option "ismail mosa (ismail@tenhal.sa)"
- option "مها الحنيظل (mh.lhnyzl@alhammadi.med.sa)"
- option "امال القحطاني (ml.lqhtny@alhammadi.med.sa)"
- option "منتهى الزغيبي (mnth.lzgyby@alhammadi.med.sa)"
- option "مرام القحطاني (mrm.lqhtny@alhammadi.med.sa)"
- option "مي سليمان الدخيل (my.ldkhyl@alhammadi.med.sa)"
- option "PX Admin (pxadmin@dev.local)"
- option "رهف علي العنزي (rhf.lnzy@alhammadi.med.sa)"
- option "SHAHAD MOSLEH K ALANAZI (sh@gmail.com)"
- option "اشواق الحربي (shwq.lhrby@alhammadi.med.sa)"
- option "أثير القحطاني (thyr.lqhtny@alhammadi.med.sa)"
- generic [ref=e192]:
- text: Target Completion
- textbox "Target Completion" [ref=e193]
- generic [ref=e194]:
- button "Save" [ref=e195] [cursor=pointer]:
- img [ref=e196]
- text: Save
- link "Cancel" [ref=e200] [cursor=pointer]:
- /url: /rca/
- contentinfo [ref=e201]:
- paragraph [ref=e202]:
- text: Powered by
- link "tenhal.sa" [ref=e203] [cursor=pointer]:
- /url: https://tenhal.sa
Test source
1 | import { test, expect } from '@playwright/test';
2 | import { RoleAuthHelper } from '../../helpers/helpers';
3 | import { ApiHelper } from '../../helpers/api-helper';
4 |
5 | test.describe('RCA Workflow', () => {
6 | test.describe.configure({ mode: 'serial' });
7 |
8 | let rcaId: string | null = null;
9 |
10 | test('RCA list page loads', async ({ page }) => {
11 | const auth = new RoleAuthHelper(page);
12 | await auth.login('hospital_admin');
13 |
14 | await page.goto('/rca/');
15 | await page.waitForLoadState('domcontentloaded');
16 |
17 | const bodyText = await page.textContent('body');
18 | expect(bodyText).toContain('Root Cause Analysis');
19 | });
20 |
21 | test('create RCA', async ({ page }) => {
22 | const auth = new RoleAuthHelper(page);
23 | await auth.login('hospital_admin');
24 |
25 | await page.goto('/rca/create/');
26 | await page.waitForLoadState('domcontentloaded');
27 | await page.waitForTimeout(1000);
28 |
29 | const titleInput = page.locator('#id_title');
30 | if (!(await titleInput.isVisible().catch(() => false))) {
31 | test.skip();
32 | return;
33 | }
34 |
35 | const rcaTitle = `E2E RCA Test ${Date.now()}`;
36 | await page.fill('#id_title', rcaTitle);
37 | await page.fill('#id_description', 'Test RCA description for E2E workflow testing');
38 | await page.fill('#id_background', 'Background info for test');
39 | await page.fill('#id_root_cause_summary', 'Initial root cause summary');
40 | await page.selectOption('#id_severity', 'high');
41 | await page.selectOption('#id_priority', 'medium');
> 42 | await page.click('button[type="submit"]');
| ^ Error: page.click: Test timeout of 60000ms exceeded.
43 |
44 | await page.waitForLoadState('domcontentloaded');
45 | expect(page.url()).toMatch(/\/rca\/[0-9a-f-]+\//);
46 |
47 | const urlParts = page.url().split('/');
48 | rcaId = urlParts[urlParts.length - 2] || urlParts[urlParts.length - 1].replace('/', '');
49 |
50 | const bodyText = await page.textContent('body');
51 | expect(bodyText).toContain(rcaTitle);
52 | });
53 |
54 | test('add root cause', async ({ page }) => {
55 | const auth = new RoleAuthHelper(page);
56 | await auth.login('hospital_admin');
57 |
58 | await page.goto('/rca/');
59 | await page.waitForLoadState('domcontentloaded');
60 |
61 | const listBody = await page.textContent('body');
62 | if (listBody.includes('No Root Cause Analyses')) {
63 | test.skip();
64 | return;
65 | }
66 |
67 | const firstLink = page.locator('a[href*="/rca/"]').first();
68 | if (!(await firstLink.isVisible())) {
69 | test.skip();
70 | return;
71 | }
72 | await firstLink.click();
73 | await page.waitForLoadState('domcontentloaded');
74 |
75 | const modalBtn = page.locator('button[data-bs-target="#rootCauseModal"]');
76 | if (!(await modalBtn.isVisible().catch(() => false))) {
77 | test.skip();
78 | return;
79 | }
80 |
81 | await modalBtn.click();
82 | await page.waitForSelector('#rootCauseModal.show', { timeout: 5000 }).catch(() => {});
83 | await page.waitForTimeout(500);
84 |
85 | await page.fill('#rootCauseModal textarea[name="description"]', 'E2E test root cause: process gap identified');
86 | await page.selectOption('#rootCauseModal select[name="category"]', 'process');
87 | await page.fill('#rootCauseModal input[name="likelihood"]', '3');
88 | await page.fill('#rootCauseModal input[name="impact"]', '4');
89 | await page.click('#rootCauseModal button[type="submit"]');
90 |
91 | await page.waitForLoadState('domcontentloaded');
92 | const bodyText = await page.textContent('body');
93 | expect(bodyText).toContain('process gap identified');
94 | });
95 |
96 | test('add corrective action', async ({ page }) => {
97 | const auth = new RoleAuthHelper(page);
98 | await auth.login('hospital_admin');
99 |
100 | await page.goto('/rca/');
101 | await page.waitForLoadState('domcontentloaded');
102 |
103 | const listBody = await page.textContent('body');
104 | if (listBody.includes('No Root Cause Analyses')) {
105 | test.skip();
106 | return;
107 | }
108 |
109 | const firstLink = page.locator('a[href*="/rca/"]').first();
110 | if (!(await firstLink.isVisible())) {
111 | test.skip();
112 | return;
113 | }
114 | await firstLink.click();
115 | await page.waitForLoadState('domcontentloaded');
116 |
117 | const modalBtn = page.locator('button[data-bs-target="#actionModal"]');
118 | if (!(await modalBtn.isVisible().catch(() => false))) {
119 | test.skip();
120 | return;
121 | }
122 |
123 | await modalBtn.click();
124 | await page.waitForSelector('#actionModal.show', { timeout: 5000 }).catch(() => {});
125 | await page.waitForTimeout(500);
126 |
127 | await page.fill('#actionModal textarea[name="description"]', 'E2E corrective action: update SOP');
128 | await page.selectOption('#actionModal select[name="action_type"]', 'corrective');
129 | await page.selectOption('#actionModal select[name="status"]', 'not_started');
130 | await page.click('#actionModal button[type="submit"]');
131 |
132 | await page.waitForLoadState('domcontentloaded');
133 | const bodyText = await page.textContent('body');
134 | expect(bodyText).toContain('update SOP');
135 | });
136 |
137 | test('status change DRAFT to IN_PROGRESS', async ({ page }) => {
138 | const auth = new RoleAuthHelper(page);
139 | await auth.login('hospital_admin');
140 |
141 | await page.goto('/rca/');
142 | await page.waitForLoadState('domcontentloaded');