195 lines
6.5 KiB
TypeScript
195 lines
6.5 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { RoleAuthHelper } from '../../helpers/helpers';
|
|
import { ApiHelper } from '../../helpers/api-helper';
|
|
|
|
test.describe('RCA Workflow', () => {
|
|
test.describe.configure({ mode: 'serial' });
|
|
|
|
let rcaId: string | null = null;
|
|
|
|
test('RCA list page loads', async ({ page }) => {
|
|
const auth = new RoleAuthHelper(page);
|
|
await auth.login('hospital_admin');
|
|
|
|
await page.goto('/rca/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const bodyText = await page.textContent('body');
|
|
expect(bodyText).toContain('Root Cause Analysis');
|
|
});
|
|
|
|
test('create RCA', async ({ page }) => {
|
|
const auth = new RoleAuthHelper(page);
|
|
await auth.login('hospital_admin');
|
|
|
|
await page.goto('/rca/create/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await page.waitForTimeout(1000);
|
|
|
|
const titleInput = page.locator('#id_title');
|
|
if (!(await titleInput.isVisible().catch(() => false))) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
const rcaTitle = `E2E RCA Test ${Date.now()}`;
|
|
await page.fill('#id_title', rcaTitle);
|
|
await page.fill('#id_description', 'Test RCA description for E2E workflow testing');
|
|
await page.fill('#id_background', 'Background info for test');
|
|
await page.fill('#id_root_cause_summary', 'Initial root cause summary');
|
|
await page.selectOption('#id_severity', 'high');
|
|
await page.selectOption('#id_priority', 'medium');
|
|
await page.click('button[type="submit"]');
|
|
|
|
await page.waitForLoadState('domcontentloaded');
|
|
expect(page.url()).toMatch(/\/rca\/[0-9a-f-]+\//);
|
|
|
|
const urlParts = page.url().split('/');
|
|
rcaId = urlParts[urlParts.length - 2] || urlParts[urlParts.length - 1].replace('/', '');
|
|
|
|
const bodyText = await page.textContent('body');
|
|
expect(bodyText).toContain(rcaTitle);
|
|
});
|
|
|
|
test('add root cause', async ({ page }) => {
|
|
const auth = new RoleAuthHelper(page);
|
|
await auth.login('hospital_admin');
|
|
|
|
await page.goto('/rca/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const listBody = await page.textContent('body');
|
|
if (listBody.includes('No Root Cause Analyses')) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
const firstLink = page.locator('a[href*="/rca/"]').first();
|
|
if (!(await firstLink.isVisible())) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
await firstLink.click();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const modalBtn = page.locator('button[data-bs-target="#rootCauseModal"]');
|
|
if (!(await modalBtn.isVisible().catch(() => false))) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
await modalBtn.click();
|
|
await page.waitForSelector('#rootCauseModal.show', { timeout: 5000 }).catch(() => {});
|
|
await page.waitForTimeout(500);
|
|
|
|
await page.fill('#rootCauseModal textarea[name="description"]', 'E2E test root cause: process gap identified');
|
|
await page.selectOption('#rootCauseModal select[name="category"]', 'process');
|
|
await page.fill('#rootCauseModal input[name="likelihood"]', '3');
|
|
await page.fill('#rootCauseModal input[name="impact"]', '4');
|
|
await page.click('#rootCauseModal button[type="submit"]');
|
|
|
|
await page.waitForLoadState('domcontentloaded');
|
|
const bodyText = await page.textContent('body');
|
|
expect(bodyText).toContain('process gap identified');
|
|
});
|
|
|
|
test('add corrective action', async ({ page }) => {
|
|
const auth = new RoleAuthHelper(page);
|
|
await auth.login('hospital_admin');
|
|
|
|
await page.goto('/rca/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const listBody = await page.textContent('body');
|
|
if (listBody.includes('No Root Cause Analyses')) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
const firstLink = page.locator('a[href*="/rca/"]').first();
|
|
if (!(await firstLink.isVisible())) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
await firstLink.click();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const modalBtn = page.locator('button[data-bs-target="#actionModal"]');
|
|
if (!(await modalBtn.isVisible().catch(() => false))) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
await modalBtn.click();
|
|
await page.waitForSelector('#actionModal.show', { timeout: 5000 }).catch(() => {});
|
|
await page.waitForTimeout(500);
|
|
|
|
await page.fill('#actionModal textarea[name="description"]', 'E2E corrective action: update SOP');
|
|
await page.selectOption('#actionModal select[name="action_type"]', 'corrective');
|
|
await page.selectOption('#actionModal select[name="status"]', 'not_started');
|
|
await page.click('#actionModal button[type="submit"]');
|
|
|
|
await page.waitForLoadState('domcontentloaded');
|
|
const bodyText = await page.textContent('body');
|
|
expect(bodyText).toContain('update SOP');
|
|
});
|
|
|
|
test('status change DRAFT to IN_PROGRESS', async ({ page }) => {
|
|
const auth = new RoleAuthHelper(page);
|
|
await auth.login('hospital_admin');
|
|
|
|
await page.goto('/rca/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const listBody = await page.textContent('body');
|
|
if (listBody.includes('No Root Cause Analyses')) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
const firstLink = page.locator('a[href*="/rca/"]').first();
|
|
if (!(await firstLink.isVisible())) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
await firstLink.click();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
const statusSelect = page.locator('#statusChangeForm select[name="new_status"]');
|
|
if (!(await statusSelect.isVisible().catch(() => false))) {
|
|
test.skip();
|
|
return;
|
|
}
|
|
|
|
await statusSelect.selectOption('in_progress');
|
|
await page.click('#statusChangeForm button[type="submit"]');
|
|
|
|
await page.waitForLoadState('domcontentloaded');
|
|
const bodyText = await page.textContent('body');
|
|
expect(bodyText).toContain('In Progress');
|
|
});
|
|
|
|
test('cross-hospital RCA isolation via API', async ({ page }) => {
|
|
const api = new ApiHelper(page);
|
|
await api.authenticate('hospital_admin');
|
|
|
|
const resp = await api.get('/api/v1/complaints/');
|
|
expect([200, 404]).toContain(resp.status());
|
|
});
|
|
|
|
test('unauthenticated user cannot access RCA', async ({ page }) => {
|
|
await page.goto('/rca/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
expect(page.url()).toContain('/accounts/login/');
|
|
});
|
|
|
|
test('source user cannot access RCA', async ({ page }) => {
|
|
const auth = new RoleAuthHelper(page);
|
|
await auth.login('source_user');
|
|
|
|
await page.goto('/rca/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
expect(page.url()).not.toContain('/rca/');
|
|
});
|
|
});
|