286 lines
8.2 KiB
TypeScript
286 lines
8.2 KiB
TypeScript
import { Page } from '@playwright/test';
|
|
|
|
export class AuthHelper {
|
|
constructor(private page: Page) {}
|
|
|
|
async login(email: string = 'admin@px360.sa', password: string = 'admin123') {
|
|
await this.page.goto('/accounts/login/');
|
|
await this.page.waitForSelector('#email');
|
|
await this.page.fill('#email', email);
|
|
await this.page.fill('#password', password);
|
|
await this.page.click('button[type="submit"]');
|
|
}
|
|
|
|
async logout() {
|
|
await this.page.goto('/accounts/logout/');
|
|
await this.page.waitForURL(/\/accounts\/login\/?/, { timeout: 10000 });
|
|
}
|
|
}
|
|
|
|
export class PublicFormHelper {
|
|
constructor(private page: Page) {}
|
|
|
|
async goToPublicLanding() {
|
|
await this.page.goto('/core/public/submit/');
|
|
await this.page.waitForSelector('.selection-card');
|
|
}
|
|
|
|
async selectFormType(type: 'complaint' | 'observation' | 'inquiry') {
|
|
await this.page.click(`.selection-card[data-type="${type}"]`);
|
|
await this.page.waitForSelector('#publicFormContainer.active', { timeout: 10000 });
|
|
}
|
|
|
|
async fillComplaintForm(data: {
|
|
complainantName: string;
|
|
relationToPatient: string;
|
|
mobileNumber: string;
|
|
patientName: string;
|
|
nationalId: string;
|
|
incidentDate: string;
|
|
complaintDetails: string;
|
|
email?: string;
|
|
}) {
|
|
await this.page.fill('#id_complainant_name', data.complainantName);
|
|
await this.page.selectOption('#id_relation_to_patient', data.relationToPatient);
|
|
if (data.email) await this.page.fill('#id_email', data.email);
|
|
await this.page.fill('#id_mobile_number', data.mobileNumber);
|
|
await this.page.fill('#id_patient_name', data.patientName);
|
|
await this.page.fill('#id_national_id', data.nationalId);
|
|
await this.page.fill('#id_incident_date', data.incidentDate);
|
|
await this.page.fill('#id_complaint_details', data.complaintDetails);
|
|
}
|
|
|
|
async submitComplaint() {
|
|
await this.page.click('#submit_btn');
|
|
}
|
|
|
|
async fillInquiryForm(data: {
|
|
name: string;
|
|
email: string;
|
|
phone: string;
|
|
hospital: string;
|
|
category: string;
|
|
subject: string;
|
|
message: string;
|
|
}) {
|
|
await this.page.fill('#inquiry_name', data.name);
|
|
await this.page.fill('#inquiry_email', data.email);
|
|
await this.page.fill('#inquiry_phone', data.phone);
|
|
await this.page.selectOption('#inquiry_hospital', data.hospital);
|
|
await this.page.selectOption('#inquiry_category', data.category);
|
|
await this.page.fill('#inquiry_subject', data.subject);
|
|
await this.page.fill('#inquiry_message', data.message);
|
|
}
|
|
|
|
async submitInquiry() {
|
|
await this.page.click('#inquirySubmitBtn');
|
|
}
|
|
|
|
async fillObservationForm(data: {
|
|
description: string;
|
|
title?: string;
|
|
locationText?: string;
|
|
reporterName?: string;
|
|
reporterPhone?: string;
|
|
reporterEmail?: string;
|
|
}) {
|
|
if (data.title) await this.page.fill('input[name="title"]', data.title);
|
|
await this.page.fill('textarea[name="description"]', data.description);
|
|
if (data.locationText) await this.page.fill('input[name="location_text"]', data.locationText);
|
|
if (data.reporterName) await this.page.fill('input[name="reporter_name"]', data.reporterName);
|
|
if (data.reporterPhone) await this.page.fill('input[name="reporter_phone"]', data.reporterPhone);
|
|
if (data.reporterEmail) await this.page.fill('input[name="reporter_email"]', data.reporterEmail);
|
|
}
|
|
|
|
async submitObservation() {
|
|
await this.page.click('button[type="submit"]');
|
|
}
|
|
|
|
async trackComplaint(referenceNumber: string) {
|
|
await this.page.goto('/complaints/public/track/');
|
|
await this.page.fill('input[name="reference_number"]', referenceNumber);
|
|
await this.page.click('button[type="submit"]');
|
|
}
|
|
|
|
async trackObservation(trackingCode: string) {
|
|
await this.page.goto('/observations/track/');
|
|
await this.page.fill('input[name="tracking_code"]', trackingCode);
|
|
await this.page.click('button[type="submit"]');
|
|
}
|
|
}
|
|
|
|
export class DashboardHelper {
|
|
constructor(private page: Page) {}
|
|
|
|
async goToDashboard() {
|
|
await this.page.goto('/');
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
|
|
async goToCommandCenter() {
|
|
await this.page.goto('/');
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
}
|
|
|
|
export type RoleName =
|
|
| 'px_admin'
|
|
| 'hospital_admin'
|
|
| 'dept_manager'
|
|
| 'px_employee'
|
|
| 'physician'
|
|
| 'nurse'
|
|
| 'staff'
|
|
| 'viewer'
|
|
| 'source_user'
|
|
| 'champion';
|
|
|
|
interface RoleConfig {
|
|
email: string;
|
|
password: string;
|
|
groupName: string;
|
|
hasHospital: boolean;
|
|
canAccessConfig: boolean;
|
|
canAccessAdmin: boolean;
|
|
isSourceUser: boolean;
|
|
}
|
|
|
|
const E2E_PASSWORD = process.env.E2E_PASSWORD || 'Dev@123456';
|
|
|
|
export const ROLES: Record<RoleName, RoleConfig> = {
|
|
px_admin: {
|
|
email: 'e2e-px-admin@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'PX Admin',
|
|
hasHospital: false,
|
|
canAccessConfig: true,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
hospital_admin: {
|
|
email: 'e2e-hospital-admin@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Hospital Admin',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
dept_manager: {
|
|
email: 'e2e-dept-manager@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Department Manager',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
px_employee: {
|
|
email: 'e2e-px-employee@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'PX Employee',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
physician: {
|
|
email: 'e2e-physician@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Physician',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
nurse: {
|
|
email: 'e2e-nurse@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Nurse',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
staff: {
|
|
email: 'e2e-staff@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Staff',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
viewer: {
|
|
email: 'e2e-viewer@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Viewer',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
source_user: {
|
|
email: 'e2e-source-user@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'PX Source User',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: true,
|
|
},
|
|
champion: {
|
|
email: 'e2e-champion@px360.test',
|
|
password: E2E_PASSWORD,
|
|
groupName: 'Champion',
|
|
hasHospital: true,
|
|
canAccessConfig: false,
|
|
canAccessAdmin: false,
|
|
isSourceUser: false,
|
|
},
|
|
};
|
|
|
|
export class RoleAuthHelper {
|
|
constructor(private page: Page) {}
|
|
|
|
async login(role: RoleName) {
|
|
const config = ROLES[role];
|
|
await this.page.goto('/accounts/login/');
|
|
await this.page.waitForSelector('#email');
|
|
await this.page.fill('#email', config.email);
|
|
await this.page.fill('#password', config.password);
|
|
await this.page.click('button[type="submit"]');
|
|
await this.page.waitForURL(/\/(?!accounts\/login)/, { timeout: 15000 });
|
|
await this.page.waitForLoadState('domcontentloaded');
|
|
}
|
|
|
|
async loginAs(role: RoleName) {
|
|
return this.login(role);
|
|
}
|
|
|
|
async logout() {
|
|
await this.page.goto('/accounts/logout/');
|
|
await this.page.waitForURL(/\/accounts\/login\/?/, { timeout: 10000 });
|
|
}
|
|
|
|
static config(role: RoleName): RoleConfig {
|
|
return ROLES[role];
|
|
}
|
|
}
|
|
|
|
export async function submitContentForm(page: Page) {
|
|
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
|
await page.waitForTimeout(800);
|
|
const formSelector = 'form:not([action*="logout"]):not([action*="login"])';
|
|
const formEl = page.locator(formSelector).first();
|
|
const count = await formEl.count();
|
|
if (count === 0) {
|
|
const fallback = page.locator('form').last();
|
|
await fallback.evaluate((f: HTMLFormElement) => f.submit());
|
|
} else {
|
|
await formEl.evaluate((f: HTMLFormElement) => f.submit());
|
|
}
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await page.waitForTimeout(3000);
|
|
}
|