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.pathname).toBe("/app/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/app-passwords" }, 65 { name: /account settings/i, href: "/app/settings" }, 66 { name: /communication preferences/i, href: "/app/comms" }, 67 { name: /repository explorer/i, href: "/app/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 () => 81 jsonResponse(mockData.describeServer({ inviteCodeRequired: true })), 82 ); 83 render(Dashboard); 84 await waitFor(() => { 85 const inviteCard = screen.getByRole("link", { name: /invite codes/i }); 86 expect(inviteCard).toBeInTheDocument(); 87 expect(inviteCard).toHaveAttribute("href", "/app/invite-codes"); 88 }); 89 }); 90 }); 91 describe("logout functionality", () => { 92 beforeEach(() => { 93 setupAuthenticatedUser(); 94 localStorage.setItem(STORAGE_KEY, JSON.stringify(mockData.session())); 95 mockEndpoint("/oauth/revoke", () => jsonResponse({})); 96 }); 97 it("calls oauth revoke and navigates to login on logout", async () => { 98 let revokeCalled = false; 99 mockEndpoint("/oauth/revoke", () => { 100 revokeCalled = true; 101 return jsonResponse({}); 102 }); 103 render(Dashboard); 104 await waitFor(() => { 105 expect(screen.getByRole("button", { name: /@testuser/i })) 106 .toBeInTheDocument(); 107 }); 108 await fireEvent.click(screen.getByRole("button", { name: /@testuser/i })); 109 await waitFor(() => { 110 expect(screen.getByRole("button", { name: /sign out/i })) 111 .toBeInTheDocument(); 112 }); 113 await fireEvent.click(screen.getByRole("button", { name: /sign out/i })); 114 await waitFor(() => { 115 expect(revokeCalled).toBe(true); 116 expect(globalThis.location.pathname).toBe("/app/login"); 117 }); 118 }); 119 it("clears session from localStorage after logout", async () => { 120 const storedSession = localStorage.getItem(STORAGE_KEY); 121 expect(storedSession).not.toBeNull(); 122 render(Dashboard); 123 await waitFor(() => { 124 expect(screen.getByRole("button", { name: /@testuser/i })) 125 .toBeInTheDocument(); 126 }); 127 await fireEvent.click(screen.getByRole("button", { name: /@testuser/i })); 128 await waitFor(() => { 129 expect(screen.getByRole("button", { name: /sign out/i })) 130 .toBeInTheDocument(); 131 }); 132 await fireEvent.click(screen.getByRole("button", { name: /sign out/i })); 133 await waitFor(() => { 134 expect(localStorage.getItem(STORAGE_KEY)).toBeNull(); 135 }); 136 }); 137 }); 138});