profileShare

rasmusjy / tasteprint

Read-only snapshot

No repository description.

main default branch 169 files Expires Sep 13, 2026, 9:06 AM
ProtectedRoute.test.tsx 2,405 bytes
1 import { afterEach, expect, it, vi } from "vitest";
2 import { render, screen, waitFor } from "@testing-library/react";
3 import { MemoryRouter, Route, Routes, useLocation } from "react-router-dom";
4 import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5 import type { ReactNode } from "react";
6 import { AuthProvider } from "../lib/auth";
7 import { ProtectedRoute } from "./ProtectedRoute";
8
9 function LoginLocation() {
10 const location = useLocation();
11 return <div>Sign in at {location.pathname + location.search}</div>;
12 }
13
14 function TestProviders({ children }: { children: ReactNode }) {
15 return <QueryClientProvider client={new QueryClient()}>{children}</QueryClientProvider>;
16 }
17
18 afterEach(() => {
19 localStorage.clear();
20 vi.unstubAllGlobals();
21 });
22
23 it("sends a signed-out visitor to login and keeps the intended route", async () => {
24 render(
25 <TestProviders>
26 <MemoryRouter initialEntries={["/app/trips/123"]}>
27 <AuthProvider>
28 <Routes>
29 <Route path="/login" element={<LoginLocation />} />
30 <Route element={<ProtectedRoute />}>
31 <Route path="/app/trips/:id" element={<div>Private trip</div>} />
32 </Route>
33 </Routes>
34 </AuthProvider>
35 </MemoryRouter>
36 </TestProviders>
37 );
38
39 expect(await screen.findByText("Sign in at /login?next=%2Fapp%2Ftrips%2F123")).toBeInTheDocument();
40 });
41
42 it("opens private content when the stored token resolves to a user", async () => {
43 localStorage.setItem("tasteprint.session", "valid-token");
44 vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response(JSON.stringify({
45 id: "user-1",
46 displayName: "Rasmus",
47 email: "r@example.com",
48 shareSlug: "rasmus-1234",
49 homeCity: "Tallinn",
50 homeCountryCode: "EE",
51 bio: null,
52 avatarUrl: null,
53 profilePublic: true,
54 memberSince: "2026-01-01T00:00:00Z"
55 }), { status: 200, headers: { "Content-Type": "application/json" } })));
56
57 render(
58 <TestProviders>
59 <MemoryRouter initialEntries={["/app"]}>
60 <AuthProvider>
61 <Routes>
62 <Route element={<ProtectedRoute />}>
63 <Route path="/app" element={<div>Private dashboard</div>} />
64 </Route>
65 </Routes>
66 </AuthProvider>
67 </MemoryRouter>
68 </TestProviders>
69 );
70
71 await waitFor(() => expect(screen.getByText("Private dashboard")).toBeInTheDocument());
72 });
73