ac47fc001d
* test: adapt e2e medication flows to all package profiles * fix(frontend): resolve frontend build lint blockers
156 lines
5.9 KiB
TypeScript
156 lines
5.9 KiB
TypeScript
import { expect, type Page } from "@playwright/test";
|
|
import { authFile, navigateTo, test } from "./fixtures";
|
|
|
|
/**
|
|
* Medications Page E2E Tests
|
|
*
|
|
* Verifies the medication list, add/edit form, CRUD operations,
|
|
* and form validation.
|
|
*/
|
|
test.describe("Medications Page", () => {
|
|
test.use({ storageState: authFile });
|
|
|
|
const visibleMedForm = (page: Page) => page.locator("form.form-grid:visible").first();
|
|
|
|
async function openMedicationForm(page: Page) {
|
|
await navigateTo(page, "/medications");
|
|
const nameField = visibleMedForm(page).getByLabel(/(Commercial Name|form\.commercialName)/i);
|
|
if (await nameField.isVisible().catch(() => false)) return;
|
|
|
|
const newEntryButton = page.getByRole("button", { name: /(new (entry|medication)|form\.newEntry)/i });
|
|
if (await newEntryButton.isVisible().catch(() => false)) {
|
|
await newEntryButton.click();
|
|
await expect(nameField).toBeVisible({ timeout: 5000 });
|
|
}
|
|
}
|
|
|
|
test("should display medications page", async ({ page }) => {
|
|
await navigateTo(page, "/medications");
|
|
|
|
// Medications tab should be active
|
|
await expect(page.locator('button.pill.primary:has-text("Medications")')).toBeVisible();
|
|
});
|
|
|
|
test("should show medication list or empty state", async ({ page }) => {
|
|
await navigateTo(page, "/medications");
|
|
|
|
// Should show either medication entries or the new medication form
|
|
const listTitle = page.locator("h2").filter({ hasText: /(Medication list|form\.medicationList)/i });
|
|
const formTitle = page.locator("h2").filter({ hasText: /(New (entry|medication)|form\.newEntry)/i });
|
|
|
|
const hasList = await listTitle.isVisible().catch(() => false);
|
|
const hasForm = await formTitle.isVisible().catch(() => false);
|
|
|
|
expect(hasList || hasForm).toBeTruthy();
|
|
});
|
|
|
|
test("should display the medication form with required fields", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
|
|
const commercialName = form.getByLabel(/(Commercial Name|form\.commercialName)/i);
|
|
await expect(commercialName).toBeVisible();
|
|
|
|
// Package type selector should exist
|
|
await expect(form.getByText(/(Package Type|form\.packageType)/i)).toBeVisible();
|
|
|
|
// Tabbed form should expose navigation to Package/Schedule sections
|
|
await expect(page.getByRole("tab", { name: /Package/i })).toBeVisible();
|
|
await expect(page.getByRole("tab", { name: /Schedule/i })).toBeVisible();
|
|
});
|
|
|
|
test("should fill in medication details", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
|
|
const nameField = form.getByLabel(/(Commercial Name|form\.commercialName)/i);
|
|
await nameField.fill("Test Aspirin");
|
|
await expect(nameField).toHaveValue("Test Aspirin");
|
|
|
|
const genericField = form.getByLabel(/(Generic Name|form\.genericName)/i);
|
|
await genericField.fill("Acetylsalicylic acid");
|
|
await expect(genericField).toHaveValue("Acetylsalicylic acid");
|
|
});
|
|
|
|
test("should have stock inventory fields", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
await page.getByRole("tab", { name: /Package/i }).click();
|
|
|
|
// Package tab should expose stock-related fields for at least one package mode.
|
|
const packsField = form.getByLabel(/(^Packs$|form\.packs)/i).first();
|
|
const totalField = form.getByText(/(Total \(pills\)|Total Capacity|form\.totalCapacity)/i).first();
|
|
|
|
const hasPacks = await packsField.isVisible().catch(() => false);
|
|
const hasTotal = await totalField.isVisible().catch(() => false);
|
|
|
|
expect(hasPacks || hasTotal).toBeTruthy();
|
|
});
|
|
|
|
test("should expose all supported package type options", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
const packageSelect = form.locator("select.package-type-select");
|
|
await expect(packageSelect).toBeVisible();
|
|
|
|
const optionValues = await packageSelect
|
|
.locator("option")
|
|
.evaluateAll((options) => options.map((option) => (option as HTMLOptionElement).value));
|
|
|
|
expect(optionValues).toEqual(expect.arrayContaining(["blister", "bottle", "tube", "liquid_container"]));
|
|
});
|
|
|
|
test("should have intake schedule with add button", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
await page.getByRole("tab", { name: /Schedule/i }).click();
|
|
|
|
// Intake schedule section
|
|
await expect(page.getByRole("tab", { name: /Schedule/i, selected: true })).toBeVisible();
|
|
|
|
// Should have at least one intake entry
|
|
await expect(
|
|
form.getByText(/(Usage \(pills\)|Every \(days\)|form\.blisters\.usage|form\.blisters\.everyDays)/i).first()
|
|
).toBeVisible();
|
|
|
|
// Should have an add intake button
|
|
const addIntake = form.getByRole("button", { name: /(Intake|form\.blisters\.addIntake)/i });
|
|
await expect(addIntake).toBeVisible();
|
|
});
|
|
|
|
test("should have save and cancel buttons", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
|
|
// Fill in a name to make the form dirty
|
|
await form.getByLabel(/(Commercial Name|form\.commercialName)/i).fill("Test");
|
|
|
|
// Save button
|
|
const saveButton = page.getByRole("button", { name: /Save|Add Medication/i });
|
|
await expect(saveButton).toBeVisible();
|
|
});
|
|
|
|
test("should prevent navigation with unsaved changes", async ({ page }) => {
|
|
await openMedicationForm(page);
|
|
const form = visibleMedForm(page);
|
|
|
|
// Fill in the form to create unsaved changes
|
|
await form.getByLabel(/(Commercial Name|form\.commercialName)/i).fill("Unsaved Medication");
|
|
|
|
// Try to navigate away
|
|
await page.locator('button.pill:has-text("Dashboard")').click();
|
|
|
|
// Should show unsaved changes warning modal
|
|
const modal = page.locator(".confirm-modal-overlay, .modal-overlay");
|
|
const hasWarning = await modal.isVisible().catch(() => false);
|
|
|
|
if (hasWarning) {
|
|
// Cancel to stay on page
|
|
const cancelBtn = page.getByRole("button", { name: /Cancel|Stay/i });
|
|
if (await cancelBtn.isVisible().catch(() => false)) {
|
|
await cancelBtn.click();
|
|
}
|
|
}
|
|
});
|
|
});
|