diff --git a/client/src/guards/auth-guard.test.tsx b/client/src/guards/auth-guard.test.tsx new file mode 100644 index 0000000..09c4f4a --- /dev/null +++ b/client/src/guards/auth-guard.test.tsx @@ -0,0 +1,62 @@ +import { + createMemoryRouter, + RouteObject, + RouterProvider, +} from "react-router-dom"; +import { describe, it, expect, vi, Mock, beforeAll } from "vitest"; +import { render } from "@testing-library/react"; + +import { useAuthStore } from "@/lib/stores/auth-store"; +import { AppRoutes } from "@/constants/routes"; + +import AuthGuard from "./auth-guard"; + +vi.mock("../lib/stores/auth-store.ts", () => ({ + useAuthStore: vi.fn(), +})); + +const routes: RouteObject[] = [ + { + path: AppRoutes.Root, + element:
Root
, + }, + { + element: , + children: [ + { + path: AppRoutes.SignIn, + element:
Sign In
, + }, + ], + }, +]; + +describe("Auth Guard", () => { + let router: ReturnType; + + beforeAll(() => { + (useAuthStore as unknown as Mock).mockReturnValueOnce({ + authorized: true, + }); + + router = createMemoryRouter(routes, { + initialEntries: [AppRoutes.SignIn], + }); + + render(); + }); + + it("redirects to the root page when authorized", () => { + expect(router.state.location.pathname).toBe(AppRoutes.Root); + }); + + it("renders the outlet when not authorized", () => { + (useAuthStore as unknown as Mock).mockReturnValueOnce({ + authorized: false, + }); + + render(); + + expect(router); + }); +}); diff --git a/client/src/guards/private-guard.test.tsx b/client/src/guards/private-guard.test.tsx new file mode 100644 index 0000000..d95e121 --- /dev/null +++ b/client/src/guards/private-guard.test.tsx @@ -0,0 +1,122 @@ +import { + createMemoryRouter, + RouteObject, + RouterProvider, +} from "react-router-dom"; +import { describe, it, expect, vi, Mock } from "vitest"; +import { useQuery } from "@tanstack/react-query"; +import { render } from "@testing-library/react"; +import "@testing-library/jest-dom"; + +import { useAuthStore } from "@/lib/stores/auth-store"; +import { AppRoutes } from "@/constants/routes"; + +import PrivateGuard from "./private-guard"; + +vi.mock("@/lib/stores/auth-store", () => ({ + useAuthStore: vi.fn().mockReturnValueOnce({ + authorized: false, + setAuthorized: vi.fn(), + }), +})); + +vi.mock("@tanstack/react-query", () => ({ + useQuery: vi.fn().mockReturnValueOnce({ + isLoading: false, + isError: false, + isSuccess: false, + }), +})); + +const routes: RouteObject[] = [ + { + path: AppRoutes.SignIn, + element:
Sign In
, + }, + { + element: , + children: [ + { + path: AppRoutes.Root, + element:
Root
, + }, + ], + }, +]; + +describe("Private Guard", () => { + it("redirects to sign-in page when not authorized", () => { + const router = createMemoryRouter(routes, { + initialEntries: [AppRoutes.Root], + }); + + render(); + + expect(router.state.location.pathname).toEqual(AppRoutes.SignIn); + }); + + it("redirects to sign in page when an error occurs", () => { + const router = createMemoryRouter(routes, { + initialEntries: [AppRoutes.Root], + }); + + (useAuthStore as unknown as Mock).mockReturnValueOnce({ + authenticated: true, + setAuthorized: vi.fn(), + }); + + (useQuery as Mock).mockReturnValueOnce({ + isError: true, + isLoading: false, + isSuccess: false, + }); + + render(); + + expect(router.state.location.pathname).toEqual(AppRoutes.SignIn); + }); + + it("allows access to root page when authorized", () => { + const router = createMemoryRouter(routes, { + initialEntries: [AppRoutes.Root], + }); + + (useAuthStore as unknown as Mock).mockReturnValueOnce({ + authorized: true, + setAuthorized: vi.fn(), + }); + + (useQuery as Mock).mockReturnValueOnce({ + isError: false, + isLoading: false, + isSuccess: true, + }); + + render(); + + expect(router.state.location.pathname).toEqual(AppRoutes.Root); + }); + + it("renders loading component when query is loading", () => { + const router = createMemoryRouter(routes, { + initialEntries: [AppRoutes.Root], + }); + + (useAuthStore as unknown as Mock).mockReturnValueOnce({ + authorized: true, + setAuthorized: vi.fn(), + }); + + (useQuery as Mock).mockReturnValueOnce({ + isError: false, + isLoading: true, + isSuccess: false, + }); + + const { container } = render(); + + const loader = container.querySelector("svg"); + + expect(loader).toBeInTheDocument(); + }); +});