import { describe, it, expect, mock, beforeEach } from 'bun:test'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import EditTournamentForm from '@/components/EditTournamentForm'
// Mock next/navigation
mock.module('next/navigation', () => ({
useRouter: () => ({
push: mock(() => {}),
}),
}))
// Mock next/link
mock.module('next/link', () => ({
default: ({ children, href }: { children: React.ReactNode; href: string }) => (
{children}
),
}))
// Mock fetch
const mockFetch = mock(async () => new Response())
global.fetch = mockFetch as any
const mockTournament = {
id: 1,
event_id: null,
name: 'Test Tournament',
description: 'A test tournament',
eventDate: new Date('2024-01-15'),
eventType: 'tournament',
tournamentType: 'individual',
format: 'round_robin',
status: 'planned',
maxParticipants: 16,
ownerId: null,
targetScore: null,
allowTies: false,
createdAt: new Date(),
updatedAt: new Date(),
teamDurability: 'permanent',
partnerRotation: 'none',
allowByes: true,
teamConfiguration: null,
maxRosterChanges: null,
requireAdminVerify: false,
}
describe('EditTournamentForm', () => {
beforeEach(() => {
// Only clear the specific mocks we create, not global module mocks
mockFetch.mockClear()
})
it('renders form with initial values', () => {
render()
expect(screen.getByLabelText('Tournament Name')).toHaveValue('Test Tournament')
expect(screen.getByLabelText('Description')).toHaveValue('A test tournament')
expect(screen.getByLabelText('Date')).toHaveValue('2024-01-15')
expect(screen.getByLabelText('Event Type')).toHaveValue('tournament')
expect(screen.getByLabelText('Format')).toHaveValue('round_robin')
expect(screen.getByLabelText('Status')).toHaveValue('planned')
expect(screen.getByLabelText('Max Participants (optional)')).toHaveValue(16)
})
it('updates form values on change', async () => {
const user = userEvent.setup()
render()
const nameInput = screen.getByLabelText('Tournament Name')
await user.clear(nameInput)
await user.type(nameInput, 'Updated Tournament')
expect(nameInput).toHaveValue('Updated Tournament')
})
it('submits form with updated data', async () => {
const user = userEvent.setup()
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({ success: true }),
} as Response)
render()
const nameInput = screen.getByLabelText('Tournament Name')
await user.clear(nameInput)
await user.type(nameInput, 'Updated Tournament')
const submitButton = screen.getByText('Save Changes')
await user.click(submitButton)
await waitFor(() => {
expect(mockFetch).toHaveBeenCalledWith(
'/api/tournaments/1',
expect.objectContaining({
method: 'PUT',
body: expect.stringContaining('Updated Tournament'),
})
)
})
})
it('shows error message on failed submission', async () => {
const user = userEvent.setup()
mockFetch.mockResolvedValueOnce({
ok: false,
json: async () => ({ error: 'Failed to update tournament' }),
} as Response)
render()
const submitButton = screen.getByText('Save Changes')
await user.click(submitButton)
await waitFor(() => {
expect(screen.getByText('Failed to update tournament')).toBeInTheDocument()
})
})
it('disables submit button while loading', async () => {
const user = userEvent.setup()
mockFetch.mockImplementation(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve({
ok: true,
json: async () => ({ success: true }),
} as Response)
}, 100)
})
)
render()
const submitButton = screen.getByText('Save Changes')
await user.click(submitButton)
expect(submitButton).toBeDisabled()
expect(submitButton).toHaveTextContent('Saving...')
})
})