Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ test.describe("Create Patient Prescription", () => {
test.describe.configure({ mode: "serial" });
let facilityId: string;

// These tests run serially against the same encounter, so every prescription
// they create shows up in one shared table. Pick two distinct medicines so
// the highlighted (non-unit) test and the unit test never land on rows that
// match the same medicine name — otherwise the unit test could match the
// other test's highlighted row and fail intermittently.
const [highlightedMedicine, unitMedicine] = faker.helpers.arrayElements(
medicineNames,
2,
);
Comment thread
nihal467 marked this conversation as resolved.

test.beforeEach(async ({ page }) => {
facilityId = getFacilityId();
const createdDateAfter = format(subDays(new Date(), 90), "yyyy-MM-dd");
Expand All @@ -26,7 +36,7 @@ test.describe("Create Patient Prescription", () => {
});

test("Add medication to patient prescription", async ({ page }) => {
const medicineName = faker.helpers.arrayElement(medicineNames);
const medicineName = highlightedMedicine;
// Use a non-unit dose (value !== 1) so the dosage is highlighted
const dosage = faker.number.int({ min: 2, max: 100 }).toString();
const frequency = faker.helpers.arrayElement(frequencies);
Expand Down Expand Up @@ -119,7 +129,7 @@ test.describe("Create Patient Prescription", () => {
test("Unit dosage is not highlighted in patient prescription", async ({
page,
}) => {
const medicineName = faker.helpers.arrayElement(medicineNames);
const medicineName = unitMedicine;
// Use a unit dose (value === 1) so the dosage is NOT highlighted
const dosage = "1";
const frequency = faker.helpers.arrayElement(frequencies);
Expand Down
95 changes: 53 additions & 42 deletions tests/facility/patient/patientDetails/files/patientFiles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,37 @@ test.describe("Patient Files", () => {
return response;
};

// Opens the preview for a specific uploaded file and closes it again,
// confirming the file is accessible to the current user.
const openFilePreview = async (page: Page, displayName: string) => {
// Scope to the row for this exact file so other files on the shared
// patient (including archived ones, whose "View" opens a different
// dialog) can't be picked up by mistake.
const fileRow = page
.getByRole("row")
.filter({ hasText: displayName })
.first();
await expect(fileRow).toBeVisible({ timeout: 10000 });
await fileRow.getByRole("button", { name: "View", exact: true }).click();

// The file preview dialog (not the archived-file dialog) must open. Filter
// by its title so an upload sheet or other dialog that may still be mounted
// can't cause a strict-mode match on the Close button.
const previewDialog = page
.getByRole("dialog")
.filter({ hasText: "File Preview" });
await expect(previewDialog).toBeVisible({
timeout: 10000,
});

// Close it, scoping to the dialog so page-level toasts named "Close"
// can't cause a strict-mode match.
await previewDialog
.getByRole("button", { name: "Close", exact: true })
.click();
await expect(previewDialog).toBeHidden({ timeout: 10000 });
};

let facilityId: string;

test.beforeEach(async ({ page }) => {
Expand Down Expand Up @@ -166,55 +197,35 @@ test.describe("Patient Files", () => {
page,
browser,
}) => {
const inputFileName1 = faker.system.fileName();
// Unique, extension-free display name so this exact file's row can be
// located reliably among other files on the shared patient.
const uploadedFileName = `access-${faker.string.alphanumeric(10)}`;

// Upload the file as the first user (doctor).
await uploadFile(
page,
`tests/fixtures/images/${fileName}`,
uploadedFileName,
);

// Upload file as first user (doctor)
await uploadFile(page, `tests/fixtures/images/${fileName}`, inputFileName1);
// Capture the stable Files-tab URL to reopen as a different user.
const filesUrl = page.url();

// Wait for the file to appear in the list
await expect(
page.getByRole("button", { name: /view/i }).first(),
).toBeVisible({ timeout: 10000 });
// The uploader can preview the file they just added.
await openFilePreview(page, uploadedFileName);

// View the uploaded file
await page.getByRole("button", { name: /view/i }).first().click();

// Wait for file viewer to load
await expect(
page.getByRole("button", { name: "Close", exact: true }),
).toBeVisible({
timeout: 5000,
});
await page.getByRole("button", { name: "Close", exact: true }).click();

// Save current URL for navigation
const currentUrl = page.url();

// Create a new browser context with nurse authentication
// The same file must be accessible to a different user (nurse).
const nurseContext = await browser.newContext({
storageState: "tests/.auth/nurse.json",
});
const nursePage = await nurseContext.newPage();

// Navigate to the patient files page as nurse
await nursePage.goto(currentUrl);

// Wait for the files tab to load
await expect(
nursePage.getByRole("button", { name: /view/i }).first(),
).toBeVisible({ timeout: 10000 });

// View the file as nurse
await nursePage.getByRole("button", { name: /view/i }).first().click();

// Verify file viewer loaded for nurse
await expect(nursePage.getByRole("button", { name: "Close" })).toBeVisible({
timeout: 5000,
});

// Clean up
await nursePage.close();
await nurseContext.close();
try {
await nursePage.goto(filesUrl);
await openFilePreview(nursePage, uploadedFileName);
} finally {
await nursePage.close();
await nurseContext.close();
}
});

test("Add a new patient file and rename it", async ({ page }) => {
Expand Down
38 changes: 32 additions & 6 deletions tests/facility/settings/devices/deviceServiceHistory.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,38 @@ test.describe("Device Service History", () => {

await expect(page.getByText(notes)).toBeVisible();

// Wait for the Add sheet to fully close before opening Edit; otherwise its
// controls linger in the DOM during the close animation and collide with
// the edit sheet's controls.
await expect(page.getByRole("button", { name: "Save" })).toBeHidden();

await page
.locator('[data-slot="card"]')
.filter({ hasText: notes })
.locator("button:has(.lucide-square-pen)")
.first()
.click();

// With the Add sheet closed, the edit sheet is the only open dialog. Use
// .last() to target the most recently opened dialog so a still-unmounting
// sheet can't reintroduce a strict-mode match.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this still be present since you have added the check on line 78? Not a big deal either ways, but still.

const editSheet = page.getByRole("dialog").last();
await expect(editSheet).toBeVisible({ timeout: 10000 });

const pastYear = new Date().getFullYear() - 1;
await page
await editSheet
.locator('[data-slot="form-item"]')
.filter({ hasText: "Service Date" })
.locator('[data-slot="popover-trigger"]')
.click();
await page.locator(".rdp-years_dropdown").selectOption(pastYear.toString());
await page.locator('[role="gridcell"]:not([data-outside])').first().click();

await page.getByRole("textbox", { name: "Notes *" }).fill(updatedNotes);
await editSheet
.getByRole("textbox", { name: "Notes *" })
.fill(updatedNotes);

await page.getByRole("button", { name: "Update" }).click();
await editSheet.getByRole("button", { name: "Update" }).click();

const updatedCard = page
.locator('[data-slot="card"]')
Expand Down Expand Up @@ -176,21 +189,34 @@ test.describe("Device Service History", () => {

await expect(page.getByText(notes)).toBeVisible();

// Wait for the Add sheet to fully close before opening Edit; otherwise its
// controls linger in the DOM during the close animation and collide with
// the edit sheet's controls.
await expect(page.getByRole("button", { name: "Save" })).toBeHidden();

await page
.locator('[data-slot="card"]')
.filter({ hasText: notes })
.locator("button:has(.lucide-square-pen)")
.first()
.click();

const updateButton = page.getByRole("button", { name: "Update" });
// With the Add sheet closed, the edit sheet is the only open dialog. Use
// .last() to target the most recently opened dialog so a still-unmounting
// sheet can't reintroduce a strict-mode match.
const editSheet = page.getByRole("dialog").last();
await expect(editSheet).toBeVisible({ timeout: 10000 });

const updateButton = editSheet.getByRole("button", { name: "Update" });
await expect(updateButton).toBeDisabled();

await page.getByRole("textbox", { name: "Notes *" }).fill(updatedNotes);
await editSheet
.getByRole("textbox", { name: "Notes *" })
.fill(updatedNotes);

await expect(updateButton).toBeEnabled();

await page.getByRole("textbox", { name: "Notes *" }).fill(notes);
await editSheet.getByRole("textbox", { name: "Notes *" }).fill(notes);

await expect(updateButton).toBeDisabled();
});
Expand Down
Loading