Skip to main content

Testing Overview

The TODS Competition Factory provides comprehensive testing utilities and patterns for building reliable tournament management applications. The testing toolkit includes mock data generation, test servers, and best practices for testing tournament scenarios.

Testing Tools

mocksEngine - Primary Testing Tool

The mocksEngine is the primary tool for generating test data. It creates realistic tournaments, participants, draws, match outcomes, and complete tournament scenarios with full TODS schema compliance.

Quick Start:

import { mocksEngine } from 'tods-competition-factory';

const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize: 32 }],
});

Key Capabilities:

Learn More: Getting Started with mocksEngine

factory-server - Test Server

The factory-server provides a lightweight test server for integration testing and development. It simulates backend tournament management without requiring full infrastructure setup.

Testing Approaches

Unit Testing

Test individual factory methods in isolation:

import { tournamentEngine } from 'tods-competition-factory';

test('can add participant to tournament', () => {
const { tournamentRecord } = mocksEngine.generateTournamentRecord();
tournamentEngine.setState(tournamentRecord);

const participant = { participantName: 'Test Player' };
const result = tournamentEngine.addParticipant({ participant });

expect(result.success).toBe(true);
});

Scenario Testing

Test specific tournament scenarios and edge cases:

test('handles BYEs in elimination draw', () => {
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
participantsCount: 13, // Creates 3 BYEs
},
],
});

tournamentEngine.setState(tournamentRecord);
const { upcomingMatchUps } = tournamentEngine.tournamentMatchUps();

// Verify BYE handling
const byeMatchUps = upcomingMatchUps.filter((m) => m.matchUpStatus === 'BYE');
expect(byeMatchUps.length).toBe(3);
});

Test Data Strategies

Minimal Setup

Generate only what you need for each test:

// Minimal tournament for testing participant methods
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
participantsProfile: { participantsCount: 10 },
});

Complete Scenarios

Generate fully populated tournaments for integration tests:

// Complete tournament with multiple events, venues, and scheduling
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{ eventType: 'SINGLES', drawProfiles: [{ drawSize: 32 }] },
{ eventType: 'DOUBLES', drawProfiles: [{ drawSize: 16 }] },
],
venueProfiles: [{ courtsCount: 8, venueName: 'Main Stadium' }],
schedulingProfile: [{ scheduleDate: '2024-06-01', venues: [{ rounds: [{ roundNumber: 1 }] }] }],
});

Progressive Building

Build test data incrementally as needed:

test('can add multiple draws to event', () => {
// Start with minimal tournament
const { tournamentRecord, eventIds } = mocksEngine.generateTournamentRecord({
participantsProfile: { participantsCount: 0 },
eventProfiles: [{ eventName: 'Singles' }],
});

// Add singles draw
mocksEngine.modifyTournamentRecord({
tournamentRecord,
eventProfiles: [{ eventId: eventIds[0], drawProfiles: [{ drawSize: 32, drawName: 'Singles' }] }],
});

// Add doubles draw
mocksEngine.modifyTournamentRecord({
tournamentRecord,
eventProfiles: [
{
drawProfiles: [{ drawSize: 16, drawType: 'DOUBLES', drawName: 'Doubles' }],
},
],
});
});

Testing Best Practices

1. Isolation

Keep tests independent and repeatable:

// Good - each test creates its own data
test('test 1', () => {
const { tournamentRecord } = mocksEngine.generateTournamentRecord();
// ... test logic
});

test('test 2', () => {
const { tournamentRecord } = mocksEngine.generateTournamentRecord();
// ... test logic
});

2. Meaningful Data

Use descriptive names and values for clarity:

const { tournamentRecord } = mocksEngine.generateTournamentRecord({
tournamentName: 'Test Tournament - BYE Handling',
drawProfiles: [
{
drawSize: 16,
participantsCount: 13, // Explicit: creates 3 BYEs
drawName: 'Main Draw',
},
],
});

3. Test Specific Scenarios

Focus each test on a specific behavior:

test('seeded participants placed in correct positions', () => {
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
seedsCount: 4,
},
],
});

tournamentEngine.setState(tournamentRecord);
// Verify only seeding placement, not other aspects
});

4. Use Appropriate Completion

Only complete matchUps necessary for your test:

// Test only needs first round complete
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
outcomes: [{ roundNumber: 1, scoreString: '6-1 6-2', winningSide: 1 }],
},
],
});

Testing Patterns

Setup Helpers

Create reusable setup functions:

function createStandardTournament() {
const { tournamentRecord, drawId } = mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize: 32 }],
});
tournamentEngine.setState(tournamentRecord);
return { tournamentRecord, drawId };
}

test('can get draw positions', () => {
const { drawId } = createStandardTournament();
const { drawPositions } = tournamentEngine.getDrawPositions({ drawId });
expect(drawPositions.length).toBe(32);
});

Parameterized Testing

Test multiple scenarios with the same logic:

test.each([
{ drawSize: 8, expectedRounds: 3 },
{ drawSize: 16, expectedRounds: 4 },
{ drawSize: 32, expectedRounds: 5 },
])('draw size $drawSize has $expectedRounds rounds', ({ drawSize, expectedRounds }) => {
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize }],
});

tournamentEngine.setState(tournamentRecord);
const { matchUps } = tournamentEngine.allTournamentMatchUps();
const rounds = Math.max(...matchUps.map((m) => m.roundNumber));

expect(rounds).toBe(expectedRounds);
});

Resources

Documentation