diff --git a/containers/ecr-viewer/e2e/ecr-library.spec.ts b/containers/ecr-viewer/e2e/ecr-library.spec.ts index 9768fce74..f23366b60 100644 --- a/containers/ecr-viewer/e2e/ecr-library.spec.ts +++ b/containers/ecr-viewer/e2e/ecr-library.spec.ts @@ -36,6 +36,55 @@ test.describe("eCR Library Filtering", () => { ); }); + test("Filtering should persist when clicking into and returning from an eCR", async ({ + page, + }) => { + await page.goto("/ecr-viewer"); + + //Mock session storage + await page.evaluate(() => { + Object.defineProperty(window, "sessionStorage", { + value: { + storage: {}, + setItem(key, value) { + this.storage[key] = value; + }, + getItem(key) { + return this.storage[key] || null; + }, + removeItem(key) { + delete this.storage[key]; + }, + clear() { + this.storage = {}; + }, + }, + writable: true, + }); + }); + + await page.waitForURL("/ecr-viewer?columnId=date_created&direction=DESC"); + await expect(page.getByTestId("filter-tag")).toContainText( + totalNumOfConditions, + ); + + await page.getByLabel("Filter by reportable condition").click(); + // Add delay since conditions rerenders shortly after opening + await page.getByText("Deselect all").click({ delay: 200 }); + await page.getByRole("group").getByText("Anthrax (disorder)").click(); + await page.getByLabel("Apply Filter").click(); + + //Click into the first eCR + await page.locator("table tr:first-child td:first-child a").click(); + //Return to the eCR Library + await page.getByText("Back to eCR Library").click({ delay: 200 }); + + await expect(page.getByText("Showing 1-16")).toBeVisible(); + expect((await page.locator("tbody > tr").allTextContents()).length).toEqual( + 16, + ); + }); + test("Search should filter results ", async ({ page }) => { await page.goto("/ecr-viewer"); await page.waitForURL("/ecr-viewer?columnId=date_created&direction=DESC"); diff --git a/containers/ecr-viewer/src/app/components/EcrTableClient.tsx b/containers/ecr-viewer/src/app/components/EcrTableClient.tsx index d19d531fb..5732c0a59 100644 --- a/containers/ecr-viewer/src/app/components/EcrTableClient.tsx +++ b/containers/ecr-viewer/src/app/components/EcrTableClient.tsx @@ -8,6 +8,7 @@ import { usePathname, useSearchParams, useRouter } from "next/navigation"; import { range } from "../view-data/utils/utils"; import classNames from "classnames"; import Link from "next/link"; +import { saveToSessionStorage } from "./utils"; type EcrTableClientProps = { data: EcrDisplay[]; @@ -66,7 +67,7 @@ const initialHeaders = [ { id: "reportable_condition", value: "Reportable Condition", - className: "library-condition-colum", + className: "library-condition-column", dataSortable: false, sortDirection: "", }, @@ -283,6 +284,8 @@ const DataRow = ({ item }: { item: EcrDisplay }) => { const patientReportDate = formatDate(patientReportDateObj); const patientReportTime = formatTime(patientReportDateObj); + const searchParams = useSearchParams(); + const conditionsList = ( ); + const saveUrl = () => { + saveToSessionStorage("urlParams", searchParams.toString()); + }; return ( - + {patient_first_name} {patient_last_name}
diff --git a/containers/ecr-viewer/src/app/components/utils.ts b/containers/ecr-viewer/src/app/components/utils.ts new file mode 100644 index 000000000..dd51e6800 --- /dev/null +++ b/containers/ecr-viewer/src/app/components/utils.ts @@ -0,0 +1,34 @@ +/** + * Saves a key-value pair to session storage. + * @param key - The key under which the value will be stored. + * @param value - The value to be stored. Can be a string or any serializable object. + */ +export const saveToSessionStorage = ( + key: string, + value: string | object, +): void => { + const serializedValue = JSON.stringify(value); + + if (typeof window !== "undefined" && window.sessionStorage) { + sessionStorage.setItem(key, serializedValue); + } else { + console.warn("sessionStorage is not available"); + } +}; + +/** + * Retrieves a key-value pair from session storage. + * @param key - The key under which the value was stored. + * @returns string or null - The stored value from session storage or null if it finds nothing + */ +export const retrieveFromSessionStorage = ( + key: string, +): string | object | null => { + if (typeof window !== "undefined" && window.sessionStorage) { + const storedValue = sessionStorage.getItem(key); + return JSON.parse(storedValue); + } else { + console.warn("sessionStorage is not available"); + return null; + } +}; diff --git a/containers/ecr-viewer/src/app/tests/components/Utils.test.tsx b/containers/ecr-viewer/src/app/tests/components/Utils.test.tsx new file mode 100644 index 000000000..5886ea266 --- /dev/null +++ b/containers/ecr-viewer/src/app/tests/components/Utils.test.tsx @@ -0,0 +1,62 @@ +import { + saveToSessionStorage, + retrieveFromSessionStorage, +} from "../../components/utils.ts"; + +describe("Session Storage saving utils", () => { + beforeEach(() => { + sessionStorage.clear(); + }); + + describe("saveToSessionStorage", () => { + it("should save a string value to session storage", () => { + const key = "Bread"; + const value = "Baguette"; + saveToSessionStorage(key, value); + + expect(sessionStorage.getItem(key)).toBe(JSON.stringify(value)); + }); + + it("should save an object value to session storage", () => { + const key = "testKey"; + const value = { name: "Heironymous", age: 37 }; + saveToSessionStorage(key, value); + + expect(sessionStorage.getItem(key)).toBe(JSON.stringify(value)); + }); + }); + + describe("retrieveFromSessionStorage", () => { + it("should retrieve a string value from session storage", () => { + const key = "fruit"; + const value = "Apples"; + sessionStorage.setItem(key, JSON.stringify(value)); + + const retrievedValue = retrieveFromSessionStorage(key); + expect(retrievedValue).toBe(value); + }); + + it("should retrieve an object value from session storage", () => { + const key = "patient"; + const value = { name: "Arabelle", age: 22 }; + sessionStorage.setItem(key, JSON.stringify(value)); + + const retrievedValue = retrieveFromSessionStorage(key); + expect(retrievedValue).toEqual(value); + }); + + it("should return null if the key does not exist", () => { + const key = "nonExistentKey"; + const retrievedValue = retrieveFromSessionStorage(key); + + expect(retrievedValue).toBeNull(); + }); + + it("should throw an error for invalid JSON in session storage", () => { + const key = "aKey"; + sessionStorage.setItem(key, "invalid-json"); + + expect(() => retrieveFromSessionStorage(key)).toThrow(SyntaxError); + }); + }); +}); diff --git a/containers/ecr-viewer/src/app/tests/components/__snapshots__/EcrTable.test.tsx.snap b/containers/ecr-viewer/src/app/tests/components/__snapshots__/EcrTable.test.tsx.snap index 472b0718c..72dbb6624 100644 --- a/containers/ecr-viewer/src/app/tests/components/__snapshots__/EcrTable.test.tsx.snap +++ b/containers/ecr-viewer/src/app/tests/components/__snapshots__/EcrTable.test.tsx.snap @@ -74,7 +74,7 @@ exports[`EcrTable Snapshot test for EcrTableLoading should match snapshot 1`] = { const isNonIntegratedViewer = env("NEXT_PUBLIC_NON_INTEGRATED_VIEWER") === "true"; + + const savedUrlParams = retrieveFromSessionStorage("urlParams"); + return ( <> {isNonIntegratedViewer ? (