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(globalThis.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.getAllByText(/@testuser\.test\.tranquil\.dev/).length) 44 .toBeGreaterThan(0); 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: /account settings/i, href: "#/settings" }, 66 { name: /communication preferences/i, href: "#/comms" }, 67 { name: /repository explorer/i, href: "#/repo" }, 68 ]; 69 for (const { name, href } of navCards) { 70 const card = screen.getByRole("link", { name }); 71 expect(card).toBeInTheDocument(); 72 expect(card).toHaveAttribute("href", href); 73 } 74 }); 75 }); 76 it("displays invite codes card when invites are required and user is admin", async () => { 77 setupAuthenticatedUser({ isAdmin: true }); 78 mockEndpoint( 79 "com.atproto.server.describeServer", 80 () => jsonResponse(mockData.describeServer({ inviteCodeRequired: true })), 81 ); 82 render(Dashboard); 83 await waitFor(() => { 84 const inviteCard = screen.getByRole("link", { name: /invite codes/i }); 85 expect(inviteCard).toBeInTheDocument(); 86 expect(inviteCard).toHaveAttribute("href", "#/invite-codes"); 87 }); 88 }); 89 }); 90 describe("logout functionality", () => { 91 beforeEach(() => { 92 setupAuthenticatedUser(); 93 localStorage.setItem(STORAGE_KEY, JSON.stringify(mockData.session())); 94 mockEndpoint("com.atproto.server.deleteSession", () => jsonResponse({})); 95 }); 96 it("calls deleteSession and navigates to login on logout", async () => { 97 let deleteSessionCalled = false; 98 mockEndpoint("com.atproto.server.deleteSession", () => { 99 deleteSessionCalled = true; 100 return jsonResponse({}); 101 }); 102 render(Dashboard); 103 await waitFor(() => { 104 expect(screen.getByRole("button", { name: /@testuser/i })) 105 .toBeInTheDocument(); 106 }); 107 await fireEvent.click(screen.getByRole("button", { name: /@testuser/i })); 108 await waitFor(() => { 109 expect(screen.getByRole("button", { name: /sign out/i })) 110 .toBeInTheDocument(); 111 }); 112 await fireEvent.click(screen.getByRole("button", { name: /sign out/i })); 113 await waitFor(() => { 114 expect(deleteSessionCalled).toBe(true); 115 expect(globalThis.location.hash).toBe("#/login"); 116 }); 117 }); 118 it("clears session from localStorage after logout", async () => { 119 const storedSession = localStorage.getItem(STORAGE_KEY); 120 expect(storedSession).not.toBeNull(); 121 render(Dashboard); 122 await waitFor(() => { 123 expect(screen.getByRole("button", { name: /@testuser/i })) 124 .toBeInTheDocument(); 125 }); 126 await fireEvent.click(screen.getByRole("button", { name: /@testuser/i })); 127 await waitFor(() => { 128 expect(screen.getByRole("button", { name: /sign out/i })) 129 .toBeInTheDocument(); 130 }); 131 await fireEvent.click(screen.getByRole("button", { name: /sign out/i })); 132 await waitFor(() => { 133 expect(localStorage.getItem(STORAGE_KEY)).toBeNull(); 134 }); 135 }); 136 }); 137});