🧪 Add unit tests for Challonge-related functionality

This commit is contained in:
2026-01-29 05:11:56 +00:00
parent 0b465d82c1
commit df888ddfd7

View File

@@ -0,0 +1,268 @@
/**
* Challonge Tests Composable
*
* Manages tournament testing operations including:
* - Loading tournament lists with pagination
* - Tournament detail fetching
* - Search/filtering
* - Helper utilities for tournament data access
*
* @example
* ```js
* const {
* tournaments,
* loading,
* error,
* testListTournaments,
* loadMoreTournaments,
* toggleTournamentDetails
* } = useChallongeTests(client, apiVersion, tournamentScope);
*
* await testListTournaments();
* ```
*/
import { ref, computed } from 'vue';
import { useAsyncState } from './useAsyncState.js';
import { queryAllTournaments } from '../utilities/tournament-query.js';
export function useChallongeTests(client, apiVersion, tournamentScope) {
// Async state management
const tournamentListState = useAsyncState();
const loadMoreState = useAsyncState();
const tournamentDetailsState = useAsyncState();
// Destructure for easier access
const { data: tournaments, isLoading: loading, error } = tournamentListState;
const { isLoading: loadingMore } = loadMoreState;
// Search and filter
const searchQuery = ref('');
const expandedTournamentId = ref(null);
// Pagination state
const currentPage = ref(1);
const perPage = ref(100);
const totalTournaments = ref(0);
const hasNextPage = ref(false);
/**
* Pagination info string
*/
const paginationInfo = computed(() => {
if (!tournaments.value) return '';
const start = (currentPage.value - 1) * perPage.value + 1;
const end = Math.min(
start + tournaments.value.length - 1,
totalTournaments.value || tournaments.value.length
);
const total = totalTournaments.value || tournaments.value.length;
return `Showing ${start}-${end} of ${total}`;
});
/**
* Filtered tournaments based on search query
*/
const filteredTournaments = computed(() => {
if (!tournaments.value) return null;
if (!searchQuery.value.trim()) return tournaments.value;
const query = searchQuery.value.toLowerCase();
return tournaments.value.filter(t => {
const name = getTournamentName(t).toLowerCase();
return name.includes(query);
});
});
/**
* Tournament details from async state
*/
const tournamentDetails = computed(() => tournamentDetailsState.data.value);
/**
* Helper to get tournament name (handles both v1 and v2.1 structures)
*/
function getTournamentName(tournament) {
return tournament.tournament?.name || tournament.name || '';
}
/**
* Helper to get tournament ID
*/
function getTournamentId(tournament) {
return tournament.tournament?.id || tournament.id;
}
/**
* Helper to get tournament property
*/
function getTournamentProp(tournament, prop) {
return tournament.tournament?.[prop] || tournament[prop];
}
/**
* Test listing tournaments with pagination support
*/
async function testListTournaments(resetPagination = true) {
if (!client.value) {
console.error('No API client available');
return;
}
if (resetPagination) {
currentPage.value = 1;
searchQuery.value = '';
expandedTournamentId.value = null;
tournamentDetailsState.reset();
}
await tournamentListState.execute(async () => {
if (apiVersion.value === 'v1') {
// v1 doesn't support pagination
const result = await client.value.tournaments.list();
totalTournaments.value = result.length;
hasNextPage.value = false;
return result;
} else {
// v2.1 - Query all tournament states in parallel
const result = await queryAllTournaments(client.value, {
page: currentPage.value,
per_page: perPage.value,
scopeType: tournamentScope.value
});
console.log('📊 Tournament API Response:', {
page: currentPage.value,
perPage: perPage.value,
scope: tournamentScope.value,
resultsCount: result.length
});
totalTournaments.value = result.length;
hasNextPage.value = result.length >= perPage.value;
return result;
}
});
}
/**
* Load more tournaments (pagination)
*/
async function loadMoreTournaments() {
if (apiVersion.value === 'v1') return; // v1 doesn't support pagination
if (!client.value) return;
currentPage.value++;
const result = await loadMoreState.execute(async () => {
const newResults = await queryAllTournaments(client.value, {
page: currentPage.value,
per_page: perPage.value,
scopeType: tournamentScope.value
});
hasNextPage.value = newResults.length === perPage.value;
return newResults;
});
if (result) {
// Append new results to existing tournaments
tournaments.value = [...tournaments.value, ...result];
} else {
// Revert page increment on error
currentPage.value--;
}
}
/**
* Change results per page
*/
async function changePerPage(newLimit) {
perPage.value = newLimit;
await testListTournaments(true);
}
/**
* Toggle tournament details view
*/
async function toggleTournamentDetails(tournamentId) {
if (!client.value) return;
if (expandedTournamentId.value === tournamentId) {
expandedTournamentId.value = null;
tournamentDetailsState.reset();
return;
}
expandedTournamentId.value = tournamentId;
await tournamentDetailsState.execute(async () => {
if (apiVersion.value === 'v1') {
return await client.value.tournaments.get(tournamentId, {
includeParticipants: true,
includeMatches: true
});
} else {
// v2.1 get tournament
return await client.value.tournaments.get(tournamentId);
}
});
// Reset expanded state if there was an error
if (tournamentDetailsState.error.value) {
expandedTournamentId.value = null;
}
}
/**
* Reset all test state
*/
function resetState() {
tournamentListState.reset();
loadMoreState.reset();
tournamentDetailsState.reset();
searchQuery.value = '';
expandedTournamentId.value = null;
currentPage.value = 1;
}
/**
* Format date string
*/
function formatDate(dateString) {
if (!dateString) return '';
return new Date(dateString).toLocaleString();
}
return {
// State
tournaments,
loading,
loadingMore,
error,
searchQuery,
expandedTournamentId,
currentPage,
perPage,
totalTournaments,
hasNextPage,
tournamentDetails,
// Computed
paginationInfo,
filteredTournaments,
// Methods
testListTournaments,
loadMoreTournaments,
changePerPage,
toggleTournamentDetails,
resetState,
// Helpers
getTournamentName,
getTournamentId,
getTournamentProp,
formatDate
};
}