diff --git a/src/__tests__/_/api-handlers/index.ts b/src/__tests__/_/api-handlers/index.ts index d53e3496a..4e65c728c 100644 --- a/src/__tests__/_/api-handlers/index.ts +++ b/src/__tests__/_/api-handlers/index.ts @@ -10,6 +10,7 @@ import { integrationsApiHandlers } from "./integrations"; import { versionApiHandlers } from "./versions"; import { portalApiHandlers } from "./portal"; import { menuApiHandlers } from "./menu"; +import { userPreferencesApiHandlers } from "./user-preferences"; export const apiHandlers = [ ...setupApiHandlers, @@ -24,4 +25,5 @@ export const apiHandlers = [ ...versionApiHandlers, ...portalApiHandlers, ...menuApiHandlers, + ...userPreferencesApiHandlers, ]; diff --git a/src/__tests__/_/api-handlers/user-preferences.ts b/src/__tests__/_/api-handlers/user-preferences.ts new file mode 100644 index 000000000..f35993672 --- /dev/null +++ b/src/__tests__/_/api-handlers/user-preferences.ts @@ -0,0 +1,24 @@ +import { rest } from "msw"; +import { BASE_TEST_URL } from "./_utils"; + +const USER_PREFERENCES = { + theme: "dark", +}; + +export const userPreferencesApiHandlers = [ + rest.get( + BASE_TEST_URL("/api/user-preferences/:key"), + async (req, res, ctx) => { + return res( + ctx.json({ data: USER_PREFERENCES[req.params.key as string] }) + ); + } + ), + rest.put( + BASE_TEST_URL("/api/user-preferences/:key"), + async (req, res, ctx) => { + USER_PREFERENCES[req.params.key as string] = (await req.json()).data; + return res(ctx.status(201)); + } + ), +]; diff --git a/src/__tests__/account/password.spec.tsx b/src/__tests__/account/password.spec.tsx index 364663d0b..c841d7250 100644 --- a/src/__tests__/account/password.spec.tsx +++ b/src/__tests__/account/password.spec.tsx @@ -56,6 +56,8 @@ describe("pages/account/password", () => { ); + await userEvent.click(screen.getByRole("button", { name: "Close Toast" })); + await userEvent.type( await screen.findByLabelText("Old Password"), "Old Password" @@ -70,7 +72,7 @@ describe("pages/account/password", () => { screen.getByRole("button", { name: "Update Password" }) ); - expect((await screen.findAllByRole("status"))[0]).toHaveTextContent( + expect(await screen.findByRole("status")).toHaveTextContent( "Password will not be changed on demo account" ); }); diff --git a/src/__tests__/account/preferences.spec.tsx b/src/__tests__/account/preferences.spec.tsx index a63612ff5..411136af7 100644 --- a/src/__tests__/account/preferences.spec.tsx +++ b/src/__tests__/account/preferences.spec.tsx @@ -42,7 +42,7 @@ describe("pages/account/preferences", () => { ); expect(await screen.findByRole("status")).toHaveTextContent( - "Account Preferences Saved Successfully" + "Theme Preference Saved Successfully" ); }); diff --git a/src/__tests__/admin/[entity]/config/presentation.spec.tsx b/src/__tests__/admin/[entity]/config/presentation.spec.tsx index 59856f40b..a8f069719 100644 --- a/src/__tests__/admin/[entity]/config/presentation.spec.tsx +++ b/src/__tests__/admin/[entity]/config/presentation.spec.tsx @@ -75,6 +75,8 @@ describe("pages/admin/[entity]/config/presentation", () => { ); + await userEvent.click(screen.getByRole("button", { name: "Close Toast" })); + await userEvent.type(screen.getByLabelText("Script"), "invalid"); await userEvent.click( @@ -82,7 +84,7 @@ describe("pages/admin/[entity]/config/presentation", () => { name: "Save Presentation Scripts", }) ); - expect((await screen.findAllByRole("status"))[0]).toHaveTextContent( + expect(await screen.findByRole("status")).toHaveTextContent( "Expression: •JS-Error: SyntaxError: Unexpected identifier" ); }); @@ -108,6 +110,8 @@ describe("pages/admin/[entity]/config/presentation", () => { ); + await userEvent.click(screen.getByRole("button", { name: "Close Toast" })); + await userEvent.clear(screen.getByLabelText("Script")); await userEvent.click( @@ -115,7 +119,7 @@ describe("pages/admin/[entity]/config/presentation", () => { name: "Save Presentation Scripts", }) ); - expect((await screen.findAllByRole("status"))[0]).toHaveTextContent( + expect(await screen.findByRole("status")).toHaveTextContent( "Presentation Scripts Saved Successfully" ); }); diff --git a/src/__tests__/admin/settings/theme.spec.tsx b/src/__tests__/admin/settings/theme.spec.tsx index 8b25dcbde..ea6238e97 100644 --- a/src/__tests__/admin/settings/theme.spec.tsx +++ b/src/__tests__/admin/settings/theme.spec.tsx @@ -47,7 +47,7 @@ describe("pages/admin/settings/theme", () => { ); expect((await screen.findAllByRole("status"))[1]).toHaveTextContent( - "Theme Settings Saved Successfully" + "Theme Preference Saved Successfully" ); }); @@ -95,11 +95,11 @@ describe("pages/admin/settings/theme", () => { ); expect((await screen.findAllByRole("status"))[2]).toHaveTextContent( - "Account Preferences Saved Successfully" + "Theme Settings Saved Successfully" ); expect((await screen.findAllByRole("status"))[3]).toHaveTextContent( - "Theme Settings Saved Successfully" + "Theme Preference Saved Successfully" ); }); diff --git a/src/__tests__/dashboard/[dashboardId]/widget/[widgetId]/index.spec.tsx b/src/__tests__/dashboard/[dashboardId]/widget/[widgetId]/index.spec.tsx index 47ec660f5..3c33eff2f 100644 --- a/src/__tests__/dashboard/[dashboardId]/widget/[widgetId]/index.spec.tsx +++ b/src/__tests__/dashboard/[dashboardId]/widget/[widgetId]/index.spec.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { render, screen } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import { ApplicationRoot } from "frontend/components/ApplicationRoot"; import UpdateDashboardWidget from "pages/dashboard/[dashboardId]/widget/[widgetId]/index"; @@ -110,7 +110,9 @@ describe("pages/dashboard/[dashboardId]/widget/[widgetId]/index", () => { screen.getByRole("button", { name: "Update Dashboard Widget" }) ); - expect(await screen.findAllByRole("status")).toHaveLength(2); + await waitFor(async () => { + expect(await screen.findAllByRole("status")).toHaveLength(2); + }); }); it("should render error when widget is not present", async () => { diff --git a/src/__tests__/dashboard/[dashboardId]/widget/create.spec.tsx b/src/__tests__/dashboard/[dashboardId]/widget/create.spec.tsx index b6cd82633..e29966605 100644 --- a/src/__tests__/dashboard/[dashboardId]/widget/create.spec.tsx +++ b/src/__tests__/dashboard/[dashboardId]/widget/create.spec.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { render, screen } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import { ApplicationRoot } from "frontend/components/ApplicationRoot"; import CreateDashboardWidget from "pages/dashboard/[dashboardId]/widget/create"; @@ -114,6 +114,8 @@ describe("pages/dashboard/[dashboardId]/widget/create", () => { screen.getByRole("button", { name: "Create Dashboard Widget" }) ); - expect(await screen.findAllByRole("status")).toHaveLength(2); + await waitFor(async () => { + expect(await screen.findAllByRole("status")).toHaveLength(2); + }); }); }); diff --git a/src/__tests__/dashboard/manage__actions.spec.tsx b/src/__tests__/dashboard/manage__actions.spec.tsx index 14366b012..b8d59eca0 100644 --- a/src/__tests__/dashboard/manage__actions.spec.tsx +++ b/src/__tests__/dashboard/manage__actions.spec.tsx @@ -85,7 +85,7 @@ describe("pages/admin/settings/dashboard", () => { await within(confirmBox).findByRole("button", { name: "Confirm" }) ); - expect((await screen.findAllByRole("status"))[0]).toHaveTextContent( + expect(await screen.findByRole("status")).toHaveTextContent( "Widget Deleted Successfully" ); diff --git a/src/__tests__/integrations/variables__constants.spec.tsx b/src/__tests__/integrations/variables__constants.spec.tsx index 1e648a5c5..d2193f046 100644 --- a/src/__tests__/integrations/variables__constants.spec.tsx +++ b/src/__tests__/integrations/variables__constants.spec.tsx @@ -107,6 +107,10 @@ describe("pages/integrations/variables => constants", () => { ); + await userEvent.click( + screen.getByRole("button", { name: "Close Toast" }) + ); + const table = screen.getByRole("table"); const tableRows = await within(table).findAllByRole("row"); @@ -129,7 +133,7 @@ describe("pages/integrations/variables => constants", () => { within(dialog).getByRole("button", { name: "Update Constant" }) ); - expect((await screen.findAllByRole("status"))[0]).toHaveTextContent( + expect(await screen.findByRole("status")).toHaveTextContent( "Constant Saved Successfully" ); }); @@ -159,6 +163,10 @@ describe("pages/integrations/variables => constants", () => { ); + await userEvent.click( + screen.getByRole("button", { name: "Close Toast" }) + ); + const table = screen.getByRole("table"); const tableRows = await within(table).findAllByRole("row"); @@ -181,7 +189,7 @@ describe("pages/integrations/variables => constants", () => { expect(await within(table).findAllByRole("row")).toHaveLength(4); - expect((await screen.findAllByRole("status"))[0]).toHaveTextContent( + expect(await screen.findByRole("status")).toHaveTextContent( "Constant Deleted Successfully" ); }); diff --git a/src/backend/data/data-access/_Base.ts b/src/backend/data/data-access/_Base.ts index 804393938..8fa5cfb80 100644 --- a/src/backend/data/data-access/_Base.ts +++ b/src/backend/data/data-access/_Base.ts @@ -56,7 +56,6 @@ export abstract class BaseDataAccessService { return query; } - // :eyes if (operator !== FilterOperators.IS_NULL && !value) { return query; } diff --git a/src/frontend/hooks/auth/preferences.store.ts b/src/frontend/hooks/auth/preferences.store.ts index ab6f42f7f..24ba4c5bd 100644 --- a/src/frontend/hooks/auth/preferences.store.ts +++ b/src/frontend/hooks/auth/preferences.store.ts @@ -17,8 +17,8 @@ const userPrefrencesApiPath = (key: UserPreferencesKeys) => { export const MAKE_USER_PREFERENCE_CRUD_CONFIG = (key: UserPreferencesKeys) => { return MAKE_CRUD_CONFIG({ path: "N/A", - plural: USER_PREFERENCES_CONFIG[key].label, - singular: USER_PREFERENCES_CONFIG[key].label, + plural: `${USER_PREFERENCES_CONFIG[key].label} Preference `, + singular: `${USER_PREFERENCES_CONFIG[key].label} Preference `, }); }; diff --git a/src/frontend/hooks/configuration/configuration.store.ts b/src/frontend/hooks/configuration/configuration.store.ts index aa1866016..b01dbde3b 100644 --- a/src/frontend/hooks/configuration/configuration.store.ts +++ b/src/frontend/hooks/configuration/configuration.store.ts @@ -10,7 +10,6 @@ import { AppStorage } from "frontend/lib/storage/app"; import { isRouterParamEnabled } from ".."; import { MAKE_APP_CONFIGURATION_CRUD_CONFIG } from "./configuration.constant"; -// :eyes export const configurationApiPath = ( key: AppConfigurationKeys, entity?: string, diff --git a/src/frontend/lib/toast/index.tsx b/src/frontend/lib/toast/index.tsx index c69d2013b..289ffbc23 100644 --- a/src/frontend/lib/toast/index.tsx +++ b/src/frontend/lib/toast/index.tsx @@ -1,6 +1,6 @@ import React from "react"; -import toast from "react-hot-toast"; - +import toast, { Toast } from "react-hot-toast"; +import { X } from "react-feather"; import { getBestErrorMessage } from "./utils"; const COLORS = { @@ -14,6 +14,31 @@ const toastStyle = (color: keyof typeof COLORS) => ({ maxWidth: "550px", }); +function ToastMessage({ message, toastT }: { message: string; toastT: Toast }) { + return ( + + {message} + { + toast.dismiss(toastT.id); + }} + /> + + ); +} + export const ToastService = { success: ( message: @@ -21,8 +46,9 @@ export const ToastService = { | { message: string; action: { label: string; action: () => void } } ) => { if (typeof message === "string") { - toast.success(message as string, { + toast.success((t) => , { style: toastStyle("success"), + duration: 7000, }); return; } @@ -30,13 +56,11 @@ export const ToastService = { toast.success( (t) => (
- {message.message} -
+