From acb6854742bfa1431adb73fe222bbaafc9561263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chy=C5=82a?= Date: Tue, 26 Nov 2024 12:25:33 +0100 Subject: [PATCH] Add test to store --- .../onboardingContext/OnboardingStorage.ts | 33 ------ .../homeOnboarding/onboardingContext/types.ts | 2 +- .../useOnboardingStorage.test.ts | 112 ++++++++++++++++++ .../onboardingContext/useOnboardingStorage.ts | 6 +- 4 files changed, 115 insertions(+), 38 deletions(-) delete mode 100644 src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts create mode 100644 src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts diff --git a/src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts b/src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts deleted file mode 100644 index 8ae9a06b1c..0000000000 --- a/src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { OnboardingState, StorageService } from "./types"; - -const ONBOARDING_STATE_KEY = "onboardingState"; - -export class OnboardingStorage implements StorageService { - getOnboardingState() { - try { - const onboardingState = localStorage.getItem(ONBOARDING_STATE_KEY); - - if (!onboardingState) { - return undefined; - } - - const parsed = JSON.parse(onboardingState); - - return parsed; - } catch (error) { - // eslint-disable-next-line no-console - console.warn("Could not get onboarding state from localStorage", { error }); - - return undefined; - } - } - - saveOnboardingState(onboardingState: OnboardingState) { - try { - localStorage.setItem(ONBOARDING_STATE_KEY, JSON.stringify(onboardingState)); - } catch (error) { - // eslint-disable-next-line no-console - console.warn("Could not save onboarding state to localStorage"); - } - } -} diff --git a/src/newHome/homeOnboarding/onboardingContext/types.ts b/src/newHome/homeOnboarding/onboardingContext/types.ts index 77745ba06e..fec4a5269a 100644 --- a/src/newHome/homeOnboarding/onboardingContext/types.ts +++ b/src/newHome/homeOnboarding/onboardingContext/types.ts @@ -19,7 +19,7 @@ export type OnboardingState = { export interface StorageService { getOnboardingState(): OnboardingState | undefined; - saveOnboardingState(onboardingState: OnboardingState): void; + saveOnboardingState(onboardingState: OnboardingState): Promise; } export interface OnboardingContextType { diff --git a/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts new file mode 100644 index 0000000000..99815f651f --- /dev/null +++ b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts @@ -0,0 +1,112 @@ +import { useUser } from "@dashboard/auth"; +import { useUpdateMetadataMutation } from "@dashboard/graphql"; +import { act } from "@testing-library/react"; +import { renderHook } from "@testing-library/react-hooks"; + +import { useOnboardingStorage } from "./useOnboardingStorage"; + +jest.mock("@dashboard/auth", () => ({ + __esModule: true, + useUser: jest.fn(), +})); + +jest.mock("@dashboard/graphql"); + +jest.useFakeTimers(); + +jest.mock("lodash/debounce", () => jest.fn(fn => fn)); + +describe("useOnboardingStorage", () => { + describe("getOnboardingState", () => { + it("should return undefined when there is no onboarding in user metadata", () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ + user: { metadata: [{ key1: "value1" }, { key2: "value2" }] }, + })); + (useUpdateMetadataMutation as jest.Mock).mockReturnValue([jest.fn(), {}]); + + const { getOnboardingState } = renderHook(() => useOnboardingStorage()).result.current; + + // Act + const result = getOnboardingState(); + + // Assert + expect(result).toBeUndefined(); + }); + + it("should return onboarding state from user metadata", () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ + user: { + metadata: [ + { + key: "onboarding", + value: JSON.stringify({ steps: [], onboardingExpanded: true }), + }, + ], + }, + })); + (useUpdateMetadataMutation as jest.Mock).mockReturnValue([jest.fn(), {}]); + + const { getOnboardingState } = renderHook(() => useOnboardingStorage()).result.current; + + // Act + const result = getOnboardingState(); + + // Assert + expect(result).toEqual({ steps: [], onboardingExpanded: true }); + }); + }); + + describe("saveOnboardingState", () => { + it("should not save onboarding state when there is no user", async () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ user: null })); + + const updateMetadataMock = jest.fn(); + + (useUpdateMetadataMutation as jest.Mock).mockReturnValue([updateMetadataMock, {}]); + + const { result } = renderHook(() => useOnboardingStorage()); + + // Act + const returnValue = await act(async () => { + return await result.current.saveOnboardingState({ steps: [], onboardingExpanded: true }); + }); + + // Assert + expect(returnValue).toBeUndefined(); + expect(updateMetadataMock).not.toHaveBeenCalled(); + }); + + it("should save onboarding state to user metadata and be called only once", async () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ user: { id: "1", metadata: [] } })); + + const updateMetadataMock = jest.fn(); + + (useUpdateMetadataMutation as jest.Mock).mockReturnValue([updateMetadataMock, {}]); + + const { result } = renderHook(() => useOnboardingStorage()); + + // Act + await act(async () => { + await result.current.saveOnboardingState({ steps: [], onboardingExpanded: true }); + }); + + jest.runAllTimers(); + + // Assert + expect(updateMetadataMock).toHaveBeenCalledTimes(1); + expect(updateMetadataMock).toHaveBeenCalledWith({ + variables: { + id: "1", + input: [ + { key: "onboarding", value: JSON.stringify({ steps: [], onboardingExpanded: true }) }, + ], + keysToDelete: [], + }, + }); + }); + }); +}); diff --git a/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts index b203ef0eba..2d801900de 100644 --- a/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts +++ b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts @@ -21,9 +21,7 @@ export const useOnboardingStorage = (): StorageService => { return undefined; } - const parsed = JSON.parse(metadata.value); - - return parsed; + return JSON.parse(metadata.value); } catch (error) { // eslint-disable-next-line no-console console.warn("Could not get onboarding state from metadata", { error }); @@ -67,7 +65,7 @@ export const useOnboardingStorage = (): StorageService => { const debouncedSaveOnboardingState = useMemo( () => debounce(saveOnboardingState, 1000), [saveOnboardingState], - ); + ) as StorageService["saveOnboardingState"]; return { getOnboardingState,