From e18c5dde3ef003e3fff831ec0791962ff5ed75d0 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Mon, 30 Oct 2023 03:03:43 +0530 Subject: [PATCH] (feat) O3-2484: The application should revert to default locale on logout (#782) --- .../redirect-logout.component.tsx | 8 ++ .../redirect-logout/redirect-logout.test.tsx | 106 ++++++++++++++++++ .../src/shared-api-objects/current-user.ts | 2 +- packages/framework/esm-framework/docs/API.md | 21 ++++ packages/shell/esm-app-shell/src/index.ejs | 2 +- 5 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 packages/apps/esm-login-app/src/redirect-logout/redirect-logout.test.tsx diff --git a/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.component.tsx b/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.component.tsx index a23c72599..0794d7e80 100644 --- a/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.component.tsx +++ b/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.component.tsx @@ -1,6 +1,7 @@ import React, { useEffect } from "react"; import { navigate, + setUserLanguage, useConfig, useConnectivity, useSession, @@ -19,6 +20,13 @@ const RedirectLogout: React.FC = () => { navigate({ to: "${openmrsSpaBase}/login" }); } else { performLogout().then(() => { + const defaultLang = + document.documentElement.getAttribute("data-default-lang"); + setUserLanguage({ + locale: defaultLang, + authenticated: false, + sessionId: "", + }); if (config.provider.type === "oauth2") { navigate({ to: config.provider.logoutUrl }); } else { diff --git a/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.test.tsx b/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.test.tsx new file mode 100644 index 000000000..5c49a905c --- /dev/null +++ b/packages/apps/esm-login-app/src/redirect-logout/redirect-logout.test.tsx @@ -0,0 +1,106 @@ +import React from "react"; +import { cleanup, render, waitFor } from "@testing-library/react"; +import RedirectLogout from "./redirect-logout.component"; +import { performLogout } from "./logout.resource"; +import { + Session, + clearCurrentUser, + navigate, + openmrsFetch, + refetchCurrentUser, + setUserLanguage, + useConfig, + useConnectivity, + useSession, +} from "@openmrs/esm-framework"; +import { mutate } from "swr"; + +jest.mock("@openmrs/esm-framework", () => ({ + navigate: jest.fn(), + setUserLanguage: jest.fn(), + useConfig: jest.fn(), + useConnectivity: jest.fn(), + useSession: jest.fn(), + clearCurrentUser: jest.fn(), + openmrsFetch: jest.fn(), + refetchCurrentUser: jest.fn(), +})); + +jest.mock("swr", () => ({ + mutate: jest.fn(), +})); + +Object.defineProperty(document, "documentElement", { + value: { + getAttribute: jest.fn().mockReturnValue("km"), + }, +}); + +describe("Testing Logout", () => { + beforeEach(() => { + cleanup(); + jest.clearAllMocks(); + (useConnectivity as jest.Mock).mockReturnValue(true); + (openmrsFetch as jest.Mock).mockResolvedValue({}); + (useSession as jest.Mock).mockReturnValue({ + authenticated: true, + sessionId: "xyz", + } as Session); + (useConfig as jest.Mock).mockReturnValue({ + provider: { + type: "", + }, + }); + }); + it("should render Logout and redirect to login page", async () => { + render(); + expect(openmrsFetch).toBeCalledWith("/ws/rest/v1/session", { + method: "DELETE", + }); + await waitFor(() => expect(mutate).toBeCalled()); + expect(clearCurrentUser).toBeCalled(); + expect(refetchCurrentUser).toBeCalled(); + expect(setUserLanguage).toBeCalledWith({ + locale: "km", + authenticated: false, + sessionId: "", + }); + expect(navigate).toBeCalledWith({ to: "${openmrsSpaBase}/login" }); + }); + + it("should render Logout and redirect to provider.logoutUrl if provider.type === oauth2", async () => { + (useConfig as jest.Mock).mockReturnValue({ + provider: { + type: "oauth2", + logoutUrl: "/oauth/logout", + }, + }); + render(); + expect(openmrsFetch).toBeCalledWith("/ws/rest/v1/session", { + method: "DELETE", + }); + await waitFor(() => expect(mutate).toBeCalled()); + expect(clearCurrentUser).toBeCalled(); + expect(refetchCurrentUser).toBeCalled(); + expect(setUserLanguage).toBeCalledWith({ + locale: "km", + authenticated: false, + sessionId: "", + }); + expect(navigate).toBeCalledWith({ to: "/oauth/logout" }); + }); + + it("should redirect to login if the session is already unauthenticated", async () => { + (useSession as jest.Mock).mockReturnValue({ + authenticated: false, + } as Session); + render(); + expect(navigate).toBeCalledWith({ to: "${openmrsSpaBase}/login" }); + }); + + it("should redirect to login if the application is Offline", async () => { + (useConnectivity as jest.Mock).mockReturnValue(false); + render(); + expect(navigate).toBeCalledWith({ to: "${openmrsSpaBase}/login" }); + }); +}); diff --git a/packages/framework/esm-api/src/shared-api-objects/current-user.ts b/packages/framework/esm-api/src/shared-api-objects/current-user.ts index 72880dba6..ce0865015 100644 --- a/packages/framework/esm-api/src/shared-api-objects/current-user.ts +++ b/packages/framework/esm-api/src/shared-api-objects/current-user.ts @@ -128,7 +128,7 @@ function isValidLocale(locale: unknown): locale is string { return true; } -function setUserLanguage(data: Session) { +export function setUserLanguage(data: Session) { const locale = data?.user?.userProperties?.defaultLocale ?? data.locale; const htmlLang = document.documentElement.getAttribute("lang"); diff --git a/packages/framework/esm-framework/docs/API.md b/packages/framework/esm-framework/docs/API.md index fb1c4206e..ed900dceb 100644 --- a/packages/framework/esm-framework/docs/API.md +++ b/packages/framework/esm-framework/docs/API.md @@ -23,6 +23,7 @@ - [saveVisit](API.md#savevisit) - [setCurrentVisit](API.md#setcurrentvisit) - [setSessionLocation](API.md#setsessionlocation) +- [setUserLanguage](API.md#setuserlanguage) - [toLocationObject](API.md#tolocationobject) - [toVisitTypeObject](API.md#tovisittypeobject) - [updateVisit](API.md#updatevisit) @@ -1360,6 +1361,26 @@ ___ ___ +### setUserLanguage + +▸ **setUserLanguage**(`data`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `data` | [`Session`](interfaces/Session.md) | + +#### Returns + +`void` + +#### Defined in + +[packages/framework/esm-api/src/shared-api-objects/current-user.ts:131](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-api/src/shared-api-objects/current-user.ts#L131) + +___ + ### toLocationObject ▸ **toLocationObject**(`openmrsRestForm`): [`Location`](interfaces/Location.md) diff --git a/packages/shell/esm-app-shell/src/index.ejs b/packages/shell/esm-app-shell/src/index.ejs index 7acc8c1bf..195827ca2 100644 --- a/packages/shell/esm-app-shell/src/index.ejs +++ b/packages/shell/esm-app-shell/src/index.ejs @@ -1,5 +1,5 @@ - +