this repo has no description
1import { beforeEach, describe, expect, it } from "vitest"; 2import { fireEvent, render, screen, waitFor } from "@testing-library/svelte"; 3import Dashboard from "../routes/Dashboard.svelte"; 4import { 5 clearMocks, 6 jsonResponse, 7 mockData, 8 mockEndpoint, 9 setupAuthenticatedUser, 10 setupFetchMock, 11 setupUnauthenticatedUser, 12} from "./mocks"; 13const STORAGE_KEY = "tranquil_pds_session"; 14describe("Dashboard", () => { 15 beforeEach(() => { 16 clearMocks(); 17 setupFetchMock(); 18 }); 19 describe("authentication guard", () => { 20 it("redirects to login when not authenticated", async () => { 21 setupUnauthenticatedUser(); 22 render(Dashboard); 23 await waitFor(() => { 24 expect(window.location.hash).toBe("#/login"); 25 }); 26 }); 27 it("shows loading state while checking auth", () => { 28 render(Dashboard); 29 expect(screen.getByText(/loading/i)).toBeInTheDocument(); 30 }); 31 }); 32 describe("authenticated view", () => { 33 beforeEach(() => { 34 setupAuthenticatedUser(); 35 }); 36 it("displays user account info and page structure", async () => { 37 render(Dashboard); 38 await waitFor(() => { 39 expect(screen.getByRole("heading", { name: /dashboard/i })) 40 .toBeInTheDocument(); 41 expect(screen.getByRole("heading", { name: /account overview/i })) 42 .toBeInTheDocument(); 43 expect(screen.getByText(/@testuser\.test\.tranquil\.dev/)) 44 .toBeInTheDocument(); 45 expect(screen.getByText(/did:web:test\.tranquil\.dev:u:testuser/)) 46 .toBeInTheDocument(); 47 expect(screen.getByText("test@example.com")).toBeInTheDocument(); 48 expect(screen.getByText("Verified")).toBeInTheDocument(); 49 expect(screen.getByText("Verified")).toHaveClass("badge", "success"); 50 }); 51 }); 52 it("displays unverified badge when email not confirmed", async () => { 53 setupAuthenticatedUser({ emailConfirmed: false }); 54 render(Dashboard); 55 await waitFor(() => { 56 expect(screen.getByText("Unverified")).toBeInTheDocument(); 57 expect(screen.getByText("Unverified")).toHaveClass("badge", "warning"); 58 }); 59 }); 60 it("displays all navigation cards", async () => { 61 render(Dashboard); 62 await waitFor(() => { 63 const navCards = [ 64 { name: /app passwords/i, href: "#/app-passwords" }, 65 { name: /invite codes/i, href: "#/invite-codes" }, 66 { name: /account settings/i, href: "#/settings" }, 67 { name: /communication preferences/i, href: "#/comms" }, 68 { name: /repository explorer/i, href: "#/repo" }, 69 ]; 70 for (const { name, href } of navCards) { 71 const card = screen.getByRole("link", { name }); 72 expect(card).toBeInTheDocument(); 73 expect(card).toHaveAttribute("href", href); 74 } 75 }); 76 }); 77 }); 78 describe("logout functionality", () => { 79 beforeEach(() => { 80 setupAuthenticatedUser(); 81 localStorage.setItem(STORAGE_KEY, JSON.stringify(mockData.session())); 82 mockEndpoint("com.atproto.server.deleteSession", () => jsonResponse({})); 83 }); 84 it("calls deleteSession and navigates to login on logout", async () => { 85 let deleteSessionCalled = false; 86 mockEndpoint("com.atproto.server.deleteSession", () => { 87 deleteSessionCalled = true; 88 return jsonResponse({}); 89 }); 90 render(Dashboard); 91 await waitFor(() => { 92 expect(screen.getByRole("button", { name: /sign out/i })) 93 .toBeInTheDocument(); 94 }); 95 await fireEvent.click(screen.getByRole("button", { name: /sign out/i })); 96 await waitFor(() => { 97 expect(deleteSessionCalled).toBe(true); 98 expect(window.location.hash).toBe("#/login"); 99 }); 100 }); 101 it("clears session from localStorage after logout", async () => { 102 const storedSession = localStorage.getItem(STORAGE_KEY); 103 expect(storedSession).not.toBeNull(); 104 render(Dashboard); 105 await waitFor(() => { 106 expect(screen.getByRole("button", { name: /sign out/i })) 107 .toBeInTheDocument(); 108 }); 109 await fireEvent.click(screen.getByRole("button", { name: /sign out/i })); 110 await waitFor(() => { 111 expect(localStorage.getItem(STORAGE_KEY)).toBeNull(); 112 }); 113 }); 114 }); 115});