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