import React from 'react'; import '@testing-library/jest-dom'; import { render, screen, waitFor, fireEvent } from '@testing-library/react'; import App from './App'; import { describe, it, expect, vi, beforeEach } from 'vitest'; describe('App', () => { beforeEach(() => { vi.resetAllMocks(); global.fetch = vi.fn(); }); it('renders login on initial load (unauthenticated)', async () => { vi.mocked(global.fetch).mockResolvedValueOnce({ ok: false, } as Response); window.history.pushState({}, 'Test page', '/v2/login'); render(); expect(screen.getByRole('button', { name: /login/i })).toBeInTheDocument(); }); it('renders dashboard when authenticated', async () => { vi.mocked(global.fetch).mockImplementation((url) => { const urlStr = url.toString(); if (urlStr.includes('/api/auth')) return Promise.resolve({ ok: true } as Response); if (urlStr.includes('/api/feed/')) return Promise.resolve({ ok: true, json: async () => [] } as Response); if (urlStr.includes('/api/tag')) return Promise.resolve({ ok: true, json: async () => [] } as Response); return Promise.resolve({ ok: true } as Response); // Fallback }); window.history.pushState({}, 'Test page', '/v2/'); render(); await waitFor(() => { expect(screen.getByText('🐱')).toBeInTheDocument(); }); // Test Logout const logoutBtn = screen.getByText(/logout/i); expect(logoutBtn).toBeInTheDocument(); // Mock window.location Object.defineProperty(window, 'location', { configurable: true, value: { href: '' }, }); vi.mocked(global.fetch).mockResolvedValueOnce({ ok: true } as Response); fireEvent.click(logoutBtn); await waitFor(() => { expect(global.fetch).toHaveBeenCalledWith( '/api/logout', expect.objectContaining({ method: 'POST' }) ); expect(window.location.href).toBe('/v2/login'); }); }); });