/** * Tests for TournamentGrid Component * * Verifies: * - Loading state display * - Error state display * - Empty state display * - Tournament list rendering * - Search input functionality * - Tournament card details * - State badges rendering * - Toggle details button * - Load more pagination (v2.1) * - Event emissions */ import { describe, it, expect } from 'vitest'; import { mount } from '@vue/test-utils'; import TournamentGrid from '@/components/challonge/TournamentGrid.vue'; describe('TournamentGrid', () => { const mockTournaments = [ { id: 'abc123', name: 'Summer Championship', state: 'pending', url: 'summer-championship', tournament_type: 'single elimination', participants_count: 16, started_at: '2024-06-01T10:00:00Z' }, { tournament: { id: 'def456', name: 'Winter Tournament', state: 'in_progress', url: 'winter-tournament', tournament_type: 'double elimination', participants_count: 32, started_at: '2024-12-15T14:00:00Z' } }, { id: 'ghi789', name: 'Spring League', state: 'ended', url: 'spring-league', tournament_type: 'round robin', participants_count: 8, started_at: null } ]; describe('Loading States', () => { it('displays loading state', () => { const wrapper = mount(TournamentGrid, { props: { loading: true, tournaments: null } }); expect(wrapper.find('.status.loading').exists()).toBe(true); expect(wrapper.text()).toContain('Loading tournaments'); }); it('displays error state', () => { const wrapper = mount(TournamentGrid, { props: { loading: false, error: 'Network error', tournaments: null } }); expect(wrapper.find('.status.error').exists()).toBe(true); expect(wrapper.text()).toContain('Network error'); }); it('displays empty state', () => { const wrapper = mount(TournamentGrid, { props: { loading: false, tournaments: [] } }); expect(wrapper.find('.status.empty').exists()).toBe(true); expect(wrapper.text()).toContain('No tournaments found'); expect(wrapper.find('a[href="https://challonge.com"]').exists()).toBe(true); }); }); describe('Tournament List Rendering', () => { it('renders tournament cards', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments } }); const cards = wrapper.findAll('.tournament-card'); expect(cards).toHaveLength(3); }); it('displays tournament names correctly for both v1 and v2.1 formats', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments } }); expect(wrapper.text()).toContain('Summer Championship'); expect(wrapper.text()).toContain('Winter Tournament'); expect(wrapper.text()).toContain('Spring League'); }); it('displays tournament details', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]] } }); expect(wrapper.text()).toContain('summer-championship'); expect(wrapper.text()).toContain('single elimination'); expect(wrapper.text()).toContain('16'); }); it('displays state badges with correct classes', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments } }); expect(wrapper.find('.tournament-state.pending').exists()).toBe(true); expect(wrapper.find('.tournament-state.in_progress').exists()).toBe(true); expect(wrapper.find('.tournament-state.ended').exists()).toBe(true); }); it('formats and displays started_at dates', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]] } }); expect(wrapper.text()).toContain('Started:'); // Date formatting varies by locale, just check that something is displayed const dateText = wrapper.text(); expect(dateText).toMatch(/Started:.*\d/); }); it('hides started date when null', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[2]], filteredTournaments: [mockTournaments[2]] } }); const cardText = wrapper.find('.tournament-card').text(); expect(cardText).not.toContain('Started:'); }); }); describe('Search Functionality', () => { it('renders search input', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments } }); expect(wrapper.find('.search-input').exists()).toBe(true); }); it('displays search query in input', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, searchQuery: 'Summer' } }); expect(wrapper.find('.search-input').element.value).toBe('Summer'); }); it('emits update:searchQuery on input', async () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments } }); const input = wrapper.find('.search-input'); await input.setValue('Winter'); expect(wrapper.emitted('update:searchQuery')).toBeTruthy(); expect(wrapper.emitted('update:searchQuery')[0]).toEqual(['Winter']); }); it('shows search info when query is present', () => { const filtered = [mockTournaments[0]]; const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: filtered, searchQuery: 'Summer' } }); expect(wrapper.find('.search-info').exists()).toBe(true); expect(wrapper.text()).toContain('Showing 1 of 3 tournaments'); }); it('hides search info when query is empty', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, searchQuery: '' } }); expect(wrapper.find('.search-info').exists()).toBe(false); }); }); describe('Tournament Details Toggle', () => { it('renders details toggle button', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]] } }); expect(wrapper.find('.btn-small').exists()).toBe(true); expect(wrapper.text()).toContain('Load Details'); }); it('emits toggle-details event on button click', async () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]] } }); await wrapper.find('.btn-small').trigger('click'); expect(wrapper.emitted('toggle-details')).toBeTruthy(); expect(wrapper.emitted('toggle-details')[0]).toEqual(['abc123']); }); it('shows active state for expanded tournament', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]], expandedTournamentId: 'abc123' } }); const button = wrapper.find('.btn-small'); expect(button.classes()).toContain('btn-active'); expect(button.text()).toBe('Hide Details'); }); it('shows inactive state for non-expanded tournament', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]], expandedTournamentId: 'other-id' } }); const button = wrapper.find('.btn-small'); expect(button.classes()).not.toContain('btn-active'); expect(button.text()).toBe('Load Details'); }); }); describe('Pagination (v2.1)', () => { it('displays load more button for v2.1 with hasNextPage', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, apiVersion: 'v2.1', hasNextPage: true } }); expect(wrapper.find('.load-more-section').exists()).toBe(true); expect(wrapper.find('.btn-secondary').text()).toBe('Load More Tournaments'); }); it('hides load more button when hasNextPage is false', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, apiVersion: 'v2.1', hasNextPage: false } }); expect(wrapper.find('.load-more-section').exists()).toBe(false); }); it('hides load more button for v1', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, apiVersion: 'v1', hasNextPage: true } }); expect(wrapper.find('.load-more-section').exists()).toBe(false); }); it('shows loading state on load more button', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, apiVersion: 'v2.1', hasNextPage: true, loadingMore: true } }); const button = wrapper.find('.btn-secondary'); expect(button.text()).toBe('Loading...'); expect(button.attributes('disabled')).toBeDefined(); }); it('emits load-more event on button click', async () => { const wrapper = mount(TournamentGrid, { props: { tournaments: mockTournaments, filteredTournaments: mockTournaments, apiVersion: 'v2.1', hasNextPage: true } }); await wrapper.find('.btn-secondary').trigger('click'); expect(wrapper.emitted('load-more')).toBeTruthy(); expect(wrapper.emitted('load-more')).toHaveLength(1); }); }); describe('Slots', () => { it('provides tournament-details slot', () => { const wrapper = mount(TournamentGrid, { props: { tournaments: [mockTournaments[0]], filteredTournaments: [mockTournaments[0]], expandedTournamentId: 'abc123' }, slots: { 'tournament-details': '