import { render, screen, waitFor, act } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { BrowserRouter } from 'react-router-dom' import { describe, it, expect, beforeEach } from 'vitest' import App from '../App' import { mockFetchResponse, resetFetchMock, getFetchCalls } from './api-mock' const renderApp = () => { return render( ) } const mockSkills = [ { id: '1', name: 'Go', category: 'Backend', proficiency: 5, icon: 'go', order: 1, created_at: '', updated_at: '' }, { id: '2', name: 'React', category: 'Frontend', proficiency: 4, icon: 'react', order: 2, created_at: '', updated_at: '' }, ] const mockProjects = [ { id: '1', title: 'Test Project', description: 'Desc', short_desc: 'Short', tech_stack: ['Go', 'React'], image_url: '', demo_url: '', repo_url: '', category: 'Full Stack', featured: true, order: 1, created_at: '', updated_at: '' }, ] const mockExperience = [ { id: '1', company: 'Test Co', role: 'Dev', location: 'Remote', start_date: '2020-01-01', end_date: null, current: true, description: 'Test', tech_stack: ['Go'], order: 1, created_at: '', updated_at: '' }, ] const mockServices = [ { id: '1', title: 'Web Dev', description: 'Desc', icon: 'code', features: ['React', 'Go'], order: 1, active: true, created_at: '', updated_at: '' }, ] describe('App Integration Tests', () => { beforeEach(() => { resetFetchMock() }) it('renders all sections without errors', async () => { mockFetchResponse(mockSkills) mockFetchResponse(mockProjects) mockFetchResponse(mockProjects) mockFetchResponse(mockExperience) mockFetchResponse(mockServices) renderApp() await waitFor(() => { expect(screen.getByText('Services & Expertise')).toBeInTheDocument() expect(screen.getByText('Selected Projects')).toBeInTheDocument() expect(screen.getByText('Technical Skills')).toBeInTheDocument() expect(screen.getByText('Experience')).toBeInTheDocument() expect(screen.getByText("Let's Build Something Great")).toBeInTheDocument() }, { timeout: 15000 }) }) it('does not make excessive API calls on initial render', async () => { mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) renderApp() await waitFor(() => { expect(screen.getByText('Services & Expertise')).toBeInTheDocument() }, { timeout: 15000 }) const calls = getFetchCalls() expect(calls.length).toBeLessThanOrEqual(6) }) it('handles API errors gracefully', async () => { ;(globalThis.fetch as unknown as { mockResolvedValueOnce: (value: unknown) => void }).mockResolvedValueOnce({ ok: false, json: () => Promise.resolve({ success: false, error: { code: 'INTERNAL_ERROR', message: 'Server error' } }), }) ;(globalThis.fetch as unknown as { mockResolvedValueOnce: (value: unknown) => void }).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve({ success: true, data: [] }), }) mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) renderApp() await waitFor(() => { expect(screen.getByText('Services & Expertise')).toBeInTheDocument() }, { timeout: 15000 }) expect(screen.getByText('Selected Projects')).toBeInTheDocument() }) it('contact form submission works', async () => { mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse([]) mockFetchResponse({ id: '1', name: 'Test', email: 'test@test.com', subject: 'Test', message: 'Test message', status: 'new', created_at: '', updated_at: '' }) renderApp() await waitFor(() => { expect(screen.getByText("Let's Build Something Great")).toBeInTheDocument() }, { timeout: 15000 }) // Use getByPlaceholderText for more specific targeting const nameInput = screen.getByPlaceholderText('Your name') const emailInput = screen.getByPlaceholderText('your@email.com') const subjectInput = screen.getByPlaceholderText("What's this about?") const messageInput = screen.getByPlaceholderText("Tell us about your project, timeline, budget, or just say hello...") const submitButton = screen.getByRole('button', { name: /send message/i }) await userEvent.type(nameInput, 'John Doe') await userEvent.type(emailInput, 'john@example.com') await userEvent.type(subjectInput, 'Project Inquiry') await userEvent.type(messageInput, 'Hello, I would like to discuss a project.') await act(async () => { await userEvent.click(submitButton) }) await waitFor(() => { expect(screen.getByText('Message Sent!')).toBeInTheDocument() }, { timeout: 15000 }) }) })