ismail c5f76b3855
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
updates
2026-05-11 14:45:30 +03:00

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 |