Files
hoopscout-v3/frontend/src/app/app.component.spec.ts
T

151 lines
4.4 KiB
TypeScript

import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { of } from 'rxjs';
import { AppComponent } from './app.component';
import { PlayerApiService } from './api/player-api.service';
describe('AppComponent', () => {
const samplePlayers = [
{
id: 1,
name: 'Luca Marini',
position: 'PG',
role: 'Primary ball handler',
birth_year: 2001,
height_cm: 190,
weight_kg: 86,
nationality: 'Italy',
league: { name: 'Lega Basket Serie A', code: 'LBA', region: 'Europe', country: 'Italy' },
team: { name: 'Milano', country: 'Italy' },
stats: {
games_played: 28,
minutes_per_game: '29.40',
points_per_game: '16.80',
assists_per_game: '6.20',
rebounds_per_game: '3.80',
efficiency_rating: '20.50',
true_shooting_percentage: '59.20',
usage_percentage: '25.00',
},
},
{
id: 2,
name: 'Mateo Santos',
position: 'SF',
role: '3 and D wing',
birth_year: 1999,
height_cm: 201,
weight_kg: 96,
nationality: 'Spain',
league: { name: 'Liga Endesa', code: 'ACB', region: 'Europe', country: 'Spain' },
team: { name: 'Madrid', country: 'Spain' },
stats: {
games_played: 25,
minutes_per_game: '24.10',
points_per_game: '11.20',
assists_per_game: '2.10',
rebounds_per_game: '5.50',
efficiency_rating: '13.70',
true_shooting_percentage: '55.80',
usage_percentage: '17.50',
},
},
];
it('loads players through the API service', () => {
const api = {
searchPlayers: () =>
of({
count: samplePlayers.length,
results: samplePlayers,
}),
} as unknown as PlayerApiService;
const component = new AppComponent(api);
component.search();
assert.equal(component.players.length, 2);
assert.equal(component.players[0].name, 'Luca Marini');
assert.equal(component.resultCount, 2);
assert.equal(component.averagePoints, '14.00');
assert.equal(component.topEfficiencyPlayer?.name, 'Luca Marini');
assert.equal(component.selectedPlayer, null);
});
it('reacts to filter changes without requiring the search button', () => {
let calls = 0;
const api = {
searchPlayers: () => {
calls += 1;
return of({ count: 0, results: [] });
},
} as unknown as PlayerApiService;
const component = new AppComponent(api);
component.onFilterChange();
component.flushPendingSearch();
assert.equal(calls, 1);
});
it('exposes role options and sends the selected role as a filter', () => {
let requestedRole = '';
const api = {
searchPlayers: (filters: { role: string }) => {
requestedRole = filters.role;
return of({ count: 0, results: [] });
},
} as unknown as PlayerApiService;
const component = new AppComponent(api);
assert.ok(component.roles.includes('3 and D wing'));
component.filters.role = '3 and D wing';
component.search();
assert.equal(requestedRole, '3 and D wing');
});
it('shows the loading placeholder only before results exist', () => {
const api = {
searchPlayers: () => of({ count: samplePlayers.length, results: samplePlayers }),
} as unknown as PlayerApiService;
const component = new AppComponent(api);
component.loading = true;
assert.equal(component.showLoadingPlaceholder, true);
component.players = samplePlayers;
assert.equal(component.showLoadingPlaceholder, false);
});
it('sorts the visible scouting board by selected stat', () => {
const api = {
searchPlayers: () => of({ count: samplePlayers.length, results: samplePlayers }),
} as unknown as PlayerApiService;
const component = new AppComponent(api);
component.search();
component.sortBy('rebounds_per_game');
assert.equal(component.players[0].name, 'Mateo Santos');
});
it('opens and closes a player profile without losing the filtered list', () => {
const api = {
searchPlayers: () => of({ count: samplePlayers.length, results: samplePlayers }),
} as unknown as PlayerApiService;
const component = new AppComponent(api);
component.search();
component.selectPlayer(samplePlayers[0]);
component.returnToResults();
assert.equal(component.selectedPlayer, null);
assert.equal(component.players.length, 2);
assert.equal(component.resultCount, 2);
});
});