✅ Add unit tests for TournamentDetail component
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
/**
|
||||
* Tests for TournamentDetail Component
|
||||
*
|
||||
* Verifies:
|
||||
* - Conditional rendering based on isExpanded
|
||||
* - Loading state display
|
||||
* - Error state display
|
||||
* - Empty state display
|
||||
* - Details content rendering
|
||||
* - JSON formatting
|
||||
* - Animation and styling
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import TournamentDetail from '@/components/challonge/TournamentDetail.vue';
|
||||
|
||||
describe('TournamentDetail', () => {
|
||||
const mockTournamentDetails = {
|
||||
tournament: {
|
||||
id: 'abc123',
|
||||
name: 'Test Tournament',
|
||||
state: 'pending',
|
||||
url: 'test-tournament',
|
||||
tournament_type: 'single elimination',
|
||||
participants_count: 16,
|
||||
started_at: '2024-01-15T10:00:00Z',
|
||||
completed_at: null,
|
||||
description: 'A test tournament',
|
||||
game_name: 'Chess'
|
||||
}
|
||||
};
|
||||
|
||||
describe('Visibility Control', () => {
|
||||
it('does not render when isExpanded is false', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: false,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.tournament-detail').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders when isExpanded is true', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.tournament-detail').exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Loading State', () => {
|
||||
it('displays loading spinner and message', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.loading').exists()).toBe(true);
|
||||
expect(wrapper.find('.spinner').exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain('Loading tournament details');
|
||||
});
|
||||
|
||||
it('hides details content while loading', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
loading: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-content').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error State', () => {
|
||||
it('displays error message', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
error: 'Failed to load tournament'
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.error').exists()).toBe(true);
|
||||
expect(wrapper.find('.error-icon').exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain('Failed to load tournament');
|
||||
});
|
||||
|
||||
it('hides details content when error exists', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
error: 'Network error',
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-content').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Empty State', () => {
|
||||
it('displays empty message when no details and not loading', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
loading: false,
|
||||
tournamentDetails: null
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.empty').exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain('No details available');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Details Content', () => {
|
||||
it('displays tournament details when available', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-content').exists()).toBe(true);
|
||||
expect(wrapper.find('.detail-header').exists()).toBe(true);
|
||||
expect(wrapper.find('.detail-json').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('displays detail header with title', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
const header = wrapper.find('.detail-header h4');
|
||||
expect(header.exists()).toBe(true);
|
||||
expect(header.text()).toBe('Full Tournament Details');
|
||||
});
|
||||
|
||||
it('formats tournament details as JSON', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
const jsonPre = wrapper.find('.detail-json');
|
||||
expect(jsonPre.exists()).toBe(true);
|
||||
|
||||
const jsonText = jsonPre.text();
|
||||
expect(jsonText).toContain('"tournament"');
|
||||
expect(jsonText).toContain('"id"');
|
||||
expect(jsonText).toContain('"abc123"');
|
||||
expect(jsonText).toContain('"name"');
|
||||
expect(jsonText).toContain('"Test Tournament"');
|
||||
});
|
||||
|
||||
it('pretty-prints JSON with indentation', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
const jsonText = wrapper.find('.detail-json').text();
|
||||
const parsed = JSON.parse(jsonText);
|
||||
|
||||
// Verify it's valid JSON and properly formatted
|
||||
expect(parsed).toEqual(mockTournamentDetails);
|
||||
expect(jsonText).toContain(' '); // Contains indentation
|
||||
});
|
||||
|
||||
it('handles complex nested tournament data', () => {
|
||||
const complexDetails = {
|
||||
tournament: mockTournamentDetails.tournament,
|
||||
participants: [
|
||||
{ id: 1, name: 'Player 1' },
|
||||
{ id: 2, name: 'Player 2' }
|
||||
],
|
||||
matches: [
|
||||
{ id: 'm1', player1_id: 1, player2_id: 2, state: 'pending' }
|
||||
]
|
||||
};
|
||||
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: complexDetails
|
||||
}
|
||||
});
|
||||
|
||||
const jsonText = wrapper.find('.detail-json').text();
|
||||
expect(jsonText).toContain('"participants"');
|
||||
expect(jsonText).toContain('"matches"');
|
||||
expect(jsonText).toContain('"Player 1"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Computed Properties', () => {
|
||||
it('returns empty string when tournamentDetails is null', () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: null
|
||||
}
|
||||
});
|
||||
|
||||
// Component should show empty state, not crash
|
||||
expect(wrapper.find('.detail-status.empty').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('updates formatted details when prop changes', async () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain('Test Tournament');
|
||||
|
||||
const newDetails = {
|
||||
tournament: { ...mockTournamentDetails.tournament, name: 'Updated Tournament' }
|
||||
};
|
||||
|
||||
await wrapper.setProps({ tournamentDetails: newDetails });
|
||||
|
||||
expect(wrapper.text()).toContain('Updated Tournament');
|
||||
expect(wrapper.text()).not.toContain('Test Tournament');
|
||||
});
|
||||
});
|
||||
|
||||
describe('State Transitions', () => {
|
||||
it('transitions from loading to content', async () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.loading').exists()).toBe(true);
|
||||
|
||||
await wrapper.setProps({
|
||||
loading: false,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.loading').exists()).toBe(false);
|
||||
expect(wrapper.find('.detail-content').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('transitions from loading to error', async () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.loading').exists()).toBe(true);
|
||||
|
||||
await wrapper.setProps({
|
||||
loading: false,
|
||||
error: 'Network timeout'
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-status.loading').exists()).toBe(false);
|
||||
expect(wrapper.find('.detail-status.error').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('transitions from content to hidden when collapsed', async () => {
|
||||
const wrapper = mount(TournamentDetail, {
|
||||
props: {
|
||||
isExpanded: true,
|
||||
tournamentDetails: mockTournamentDetails
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.detail-content').exists()).toBe(true);
|
||||
|
||||
await wrapper.setProps({ isExpanded: false });
|
||||
|
||||
expect(wrapper.find('.tournament-detail').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user