🧪 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