🧪 Add unit tests for Challonge-related functionality
This commit is contained in:
@@ -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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user