UNPKG

@auth0/nextjs-auth0

Version:
182 lines (181 loc) 8.82 kB
/** * @vitest-environment jsdom */ import React from "react"; import { usePathname } from "next/navigation.js"; import { render, screen, waitFor } from "@testing-library/react"; import * as swrModule from "swr"; import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { Auth0Provider } from "../providers/auth0-provider.js"; import { withPageAuthRequired } from "./with-page-auth-required.js"; const user = { email: "foo@example.com", email_verified: true, name: "foo", nickname: "foo", picture: "foo.jpg", sub: "1", updated_at: null }; const withAuth0Provider = ({ user } = {}) => { return (props) => (React.createElement(Auth0Provider, { ...props, user: user })); }; const mockUseUserUnauthenticated = () => ({ data: undefined, error: undefined, isLoading: false, isValidating: false, mutate: vi.fn() }); vi.mock("swr", async (importActual) => { const actual = await importActual(); return { ...actual, default: vi.fn(() => ({ data: undefined, error: undefined, isLoading: true, isValidating: false, mutate: vi.fn() })) }; }); vi.mock("next/navigation.js", async (importActual) => { const actual = await importActual(); return { ...actual, usePathname: vi.fn(() => "/") }; }); describe("with-page-auth-required csr", () => { beforeAll(() => { Object.defineProperty(window, "location", { writable: true, value: { assign: vi.fn(), toString: () => "https://example.com" } }); }); afterEach(() => { vi.resetAllMocks(); }); it("should deny access to a CSR page when not authenticated", async () => { vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(window.location.assign).toHaveBeenCalledTimes(1)); await waitFor(() => expect(screen.queryByText("Private")).toBeNull()); }); it("should add user to props of CSR page when authenticated", async () => { vi.mocked(swrModule.default).mockImplementation(() => ({ data: user, error: undefined, isLoading: false, isValidating: false, mutate: vi.fn() })); const ProtectedPage = withPageAuthRequired(({ user }) => React.createElement(React.Fragment, null, user.email)); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider({ user }) }); await waitFor(() => expect(window.location.assign).not.toHaveBeenCalled()); await waitFor(() => expect(screen.getByText("foo@example.com")).not.toBeNull()); }); it("should show an empty element when redirecting", async () => { vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage); const { container } = render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(container.innerHTML).toBe("")); }); it("should show a custom element when redirecting", async () => { vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const OnRedirecting = () => React.createElement(React.Fragment, null, "Redirecting"); const ProtectedPage = withPageAuthRequired(MyPage, { onRedirecting: OnRedirecting }); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(screen.getByText("Redirecting")).not.toBeNull()); }); it("should show an empty fallback in case of error", async () => { vi.mocked(swrModule.default).mockImplementation(() => ({ data: undefined, error: new Error("Unauthorized"), isLoading: false, isValidating: false, mutate: vi.fn() })); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage); const { container } = render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(container.innerHTML).toBe("")); }); it("should show a custom fallback in case of error", async () => { vi.mocked(swrModule.default).mockImplementation(() => ({ data: undefined, error: new Error("Unauthorized"), isLoading: false, isValidating: false, mutate: vi.fn() })); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const OnError = () => React.createElement(React.Fragment, null, "Error"); const ProtectedPage = withPageAuthRequired(MyPage, { onError: OnError }); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(screen.getByText("Error")).not.toBeNull()); }); it("should use a custom login URL", async () => { process.env.NEXT_PUBLIC_LOGIN_ROUTE = "/api/foo"; vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(window.location.assign).toHaveBeenCalledWith(expect.stringContaining("/api/foo"))); delete process.env.NEXT_PUBLIC_LOGIN_ROUTE; }); it("should return to the root path", async () => { window.location.toString = vi.fn(() => "https://example.net"); vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); vi.mocked(usePathname).mockReturnValue("/"); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(window.location.assign).toHaveBeenCalledWith(expect.stringContaining(`?returnTo=${encodeURIComponent("/")}`))); }); it("should return to the current path", async () => { window.location.toString = vi.fn(() => "https://example.net/foo"); vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); vi.mocked(usePathname).mockReturnValue("/foo"); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(window.location.assign).toHaveBeenCalledWith(expect.stringContaining(`?returnTo=${encodeURIComponent("/foo")}`))); }); it("should accept a custom returnTo URL", async () => { vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage, { returnTo: "/foo" }); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => expect(window.location.assign).toHaveBeenCalledWith(expect.stringContaining(`?returnTo=${encodeURIComponent("/foo")}`))); }); it("should preserve multiple query params in the returnTo URL", async () => { vi.mocked(swrModule.default).mockImplementation(mockUseUserUnauthenticated); const MyPage = () => React.createElement(React.Fragment, null, "Private"); const ProtectedPage = withPageAuthRequired(MyPage, { returnTo: "/foo?bar=baz&qux=quux" }); render(React.createElement(ProtectedPage, null), { wrapper: withAuth0Provider() }); await waitFor(() => { expect(window.location.assign).toHaveBeenCalled(); }); const url = new URL(window.location.assign.mock.calls[0][0], "https://example.com"); expect(url.searchParams.get("returnTo")).toEqual("/foo?bar=baz&qux=quux"); }); });