SoundboardView.test.tsx 7.2 Ko
Télécharger le fichier
/* @vitest-environment jsdom */
import { cleanup, fireEvent, render, screen, within } from '@testing-library/react';
import { afterEach, describe, expect, test, vi } from 'vitest';
import { DisplaySoundboardSound } from '../../hooks/soundboard/soundboardPresentation';
import { SoundboardContentView } from './SoundboardView';
vi.mock('@octane/renderer', () => ({
AddLinkEventTracker: vi.fn(),
RemoveLinkEventTracker: vi.fn()
}));
vi.mock('../../api', () => ({
LocalizeText: (key: string, _keys?: string[], values?: string[]) => (({
'soundboard.search': 'Search sounds',
'soundboard.category.all': 'All',
'soundboard.category.recent': 'Recent',
'soundboard.category.favorites': 'Favourites',
'soundboard.pagination.page': 'Page',
'soundboard.empty': 'No sounds available'
} as Record<string, string>)[key] || key) + (values?.length ? ` ${values.join(' ')}` : '')
}));
vi.mock('../../hooks', () => ({ useSoundboard: vi.fn() }));
const sounds: DisplaySoundboardSound[] = Array.from({ length: 11 }, (_, index) => ({
id: index + 1,
name: index === 1 ? 'Applauso' : `Sound ${index + 1}`,
url: `/${index + 1}.mp3`,
classname: '',
categoryId: index < 2 ? 'reactions' : 'effects',
tone: index % 2 ? 'green' : 'blue',
keywords: index === 1 ? ['cláp'] : []
}));
const renderContent = (recentSoundIds = [11, 2], extra: Partial<Parameters<typeof SoundboardContentView>[0]> = {}) => render(
<SoundboardContentView
sounds={sounds}
categories={[{ id: 'reactions', label: 'Reactions' }, { id: 'effects', label: 'Effects' }]}
recentSoundIds={recentSoundIds}
isCoolingDown={false}
onPlay={vi.fn()}
{...extra}
/>
);
const padNames = () => within(screen.getByTestId('soundboard-grid')).getAllByRole('button').map((pad) => pad.getAttribute('aria-label'));
describe('SoundboardContentView', () => {
afterEach(cleanup);
test('says so when only people with rights may play', () => {
renderContent([], { rightsOnly: true });
expect(screen.getByText('soundboard.room.mode.rights')).toBeInTheDocument();
cleanup();
renderContent([]);
expect(screen.queryByText('soundboard.room.mode.rights')).toBeNull();
});
test('puts the favourites on the shelf, or the recent sounds when there are none, and hides it while searching', () => {
renderContent([11, 2]);
expect(within(screen.getByTestId('soundboard-shelf')).getAllByRole('button').map((pad) => pad.getAttribute('aria-label'))).toEqual(['Sound 11', 'Applauso']);
cleanup();
renderContent([11, 2], { favoriteIds: [5, 3] });
expect(within(screen.getByTestId('soundboard-shelf')).getAllByRole('button').map((pad) => pad.getAttribute('aria-label'))).toEqual(['Sound 5', 'Sound 3']);
fireEvent.change(screen.getByRole('searchbox', { name: 'Search sounds' }), { target: { value: 'sound' } });
expect(screen.queryByTestId('soundboard-shelf')).toBeNull();
});
test('plays from the shelf, and not while cooling down', () => {
const onPlay = vi.fn();
renderContent([11], { onPlay });
fireEvent.click(within(screen.getByTestId('soundboard-shelf')).getByRole('button', { name: 'Sound 11' }));
expect(onPlay).toHaveBeenCalledOnce();
cleanup();
const held = vi.fn();
renderContent([11], { onPlay: held, isCoolingDown: true });
fireEvent.click(within(screen.getByTestId('soundboard-shelf')).getByRole('button', { name: 'Sound 11' }));
expect(held).not.toHaveBeenCalled();
});
test('shows ten text pads per page and pagination only when needed', () => {
const { container } = renderContent();
const grid = screen.getByTestId('soundboard-grid');
expect(within(grid).getAllByRole('button')).toHaveLength(10);
expect(screen.getByRole('button', { name: 'Page 2' })).toBeInTheDocument();
expect(container.textContent).not.toContain('Played by');
expect(container.textContent).not.toContain('Pronto');
fireEvent.click(screen.getByRole('button', { name: 'Page 2' }));
expect(within(grid).getAllByRole('button')).toHaveLength(1);
expect(within(grid).getByRole('button', { name: 'Sound 11' })).toBeInTheDocument();
});
test('filters by accent-insensitive search and category', () => {
renderContent();
fireEvent.change(screen.getByRole('searchbox', { name: 'Search sounds' }), { target: { value: 'CLAP' } });
expect(within(screen.getByTestId('soundboard-grid')).getAllByRole('button')).toHaveLength(1);
expect(screen.getByRole('button', { name: 'Applauso' })).toBeInTheDocument();
fireEvent.change(screen.getByRole('searchbox', { name: 'Search sounds' }), { target: { value: '' } });
fireEvent.click(screen.getByRole('button', { name: 'Reactions' }));
expect(within(screen.getByTestId('soundboard-grid')).getAllByRole('button')).toHaveLength(2);
});
test('shows recent sounds in event order', () => {
renderContent();
fireEvent.click(screen.getByRole('button', { name: 'Recent' }));
expect(padNames()).toEqual(['Sound 11', 'Applauso']);
expect(screen.queryByRole('button', { name: 'Page 2' })).not.toBeInTheDocument();
});
test('offers a favourites category only when there are favourites, in pinned order', () => {
renderContent([], { favoriteIds: [5, 3] });
fireEvent.click(screen.getByRole('button', { name: /Favourites/ }));
expect(padNames()).toEqual(['Sound 5', 'Sound 3']);
cleanup();
renderContent([]);
expect(screen.queryByRole('button', { name: /Favourites/ })).not.toBeInTheDocument();
});
test('number keys play the visible pads and arrows change page', () => {
const onPlay = vi.fn();
renderContent([], { onPlay });
fireEvent.keyDown(window, { key: '1' });
fireEvent.keyDown(window, { key: '0' });
expect(onPlay.mock.calls.map(([sound]) => sound.id)).toEqual([1, 10]);
fireEvent.keyDown(window, { key: 'ArrowRight' });
expect(padNames()).toEqual(['Sound 11']);
});
test('keys do nothing while cooling down and the bar shows the time left', () => {
const onPlay = vi.fn();
renderContent([], { onPlay, isCoolingDown: true, cooldownRemainingSeconds: 3, cooldownTotalSeconds: 4 });
fireEvent.keyDown(window, { key: '1' });
expect(onPlay).not.toHaveBeenCalled();
expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '75');
});
test('says how many users are muted and lets the player unmute them all', () => {
const onRestoreSilenced = vi.fn();
renderContent([], { silencedCount: 3, onRestoreSilenced });
expect(screen.getByText('soundboard.silenced.count 3')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'soundboard.silenced.restore' }));
expect(onRestoreSilenced).toHaveBeenCalledOnce();
});
test('shows no muted line while nobody is muted', () => {
renderContent([]);
expect(screen.queryByRole('button', { name: 'soundboard.silenced.restore' })).toBeNull();
});
});
