diff --git a/react-app/src/components/TimeoutModal/index.tsx b/react-app/src/components/TimeoutModal/index.tsx index 84a86df460..39482232ec 100644 --- a/react-app/src/components/TimeoutModal/index.tsx +++ b/react-app/src/components/TimeoutModal/index.tsx @@ -8,7 +8,7 @@ import { DialogTitle, } from "@/components"; import { Auth } from "aws-amplify"; -import { useIdle } from "@/hooks/useIdle"; +import { useIdle } from "@/hooks"; import { useGetUser } from "@/api"; import { useCountdown } from "@/hooks/useCountdown"; import { intervalToDuration } from "date-fns"; diff --git a/react-app/src/hooks/index.ts b/react-app/src/hooks/index.ts index 13b084f080..ef4ac879d5 100644 --- a/react-app/src/hooks/index.ts +++ b/react-app/src/hooks/index.ts @@ -4,3 +4,5 @@ export * from "./useDebounce"; export * from "./useLabelMappings"; export * from "./useReadOnlyUser"; export * from "./useScrollToTop"; +export * from "./useCountdown"; +export * from "./useIdle"; diff --git a/react-app/src/hooks/useIdle/index.test.ts b/react-app/src/hooks/useIdle/index.test.ts new file mode 100644 index 0000000000..b175ccab62 --- /dev/null +++ b/react-app/src/hooks/useIdle/index.test.ts @@ -0,0 +1,87 @@ +import { act, renderHook } from "@testing-library/react"; +import { beforeEach, describe, expect, test, vi } from "vitest"; +import { useIdle } from "."; + +const IDLE_TIME = 100; + +describe("useIdle", () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + test("Returns correct initial value", () => { + const { result } = renderHook(() => useIdle(IDLE_TIME)); + + expect(result.current).toBe(true); + }); + + test("Returns correct value on mouse event", () => { + const { result } = renderHook(() => useIdle(IDLE_TIME)); + + act(() => { + document.dispatchEvent(new MouseEvent("mousemove")); + }); + + expect(result.current).toBe(false); + }); + + test("Returns correct value on click event", () => { + const { result } = renderHook(() => useIdle(IDLE_TIME)); + + act(() => { + document.dispatchEvent(new MouseEvent("click")); + }); + + expect(result.current).toBe(false); + }); + + test("Returns correct value on scroll event", () => { + const { result } = renderHook(() => useIdle(IDLE_TIME)); + + act(() => { + document.dispatchEvent(new MouseEvent("scroll")); + }); + + expect(result.current).toBe(false); + }); + + test("Returns correct value on touch event", () => { + const { result } = renderHook(() => useIdle(IDLE_TIME)); + + act(() => { + document.dispatchEvent(new MouseEvent("touchmove")); + }); + + expect(result.current).toBe(false); + }); + + test("Returns correct value on keypress event", () => { + const { result } = renderHook(() => useIdle(IDLE_TIME)); + + act(() => { + document.dispatchEvent(new MouseEvent("keypress")); + }); + + expect(result.current).toBe(false); + }); + + test("Returns correct initial value from initialState argument", () => { + const { result } = renderHook(() => + useIdle(IDLE_TIME, { initialState: false }), + ); + + expect(result.current).toBe(false); + }); + + test("Returns correct value when timeout has elapsed", () => { + const { result } = renderHook(() => + useIdle(IDLE_TIME, { initialState: false }), + ); + + act(() => { + vi.advanceTimersByTime(IDLE_TIME); + }); + + expect(result.current).toBe(true); + }); +}); diff --git a/react-app/src/hooks/useIdle.ts b/react-app/src/hooks/useIdle/index.ts similarity index 100% rename from react-app/src/hooks/useIdle.ts rename to react-app/src/hooks/useIdle/index.ts