Replace stale ownership/list labels across pages and components, add lib/collection-vocabulary.js as the single copy source, document the taxonomy in AGENTS.md, and gate retired strings in CI. Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
2.8 KiB
JavaScript
94 lines
2.8 KiB
JavaScript
// @vitest-environment jsdom
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
|
|
|
|
import ScannerDestinationPicker from '../../components/ScannerDestinationPicker.js';
|
|
|
|
const COLLECTIONS = [
|
|
{ id: 1, name: 'Modern Staples', tcg: 'MTG' },
|
|
{ id: 2, name: 'Pokémon Binder', tcg: 'Pokemon' },
|
|
];
|
|
|
|
const DECKS = [
|
|
{ id: 10, name: 'Commander', game: 'mtg' },
|
|
{ id: 11, name: 'Standard', game: 'pokemon' },
|
|
];
|
|
|
|
describe('ScannerDestinationPicker', () => {
|
|
afterEach(() => cleanup());
|
|
|
|
it('shows the active destination type with aria-pressed', () => {
|
|
render(
|
|
<ScannerDestinationPicker
|
|
gameFilter="All"
|
|
onGameFilterChange={vi.fn()}
|
|
destination={{ type: 'owned', id: null, label: 'My Collection' }}
|
|
onDestinationChange={vi.fn()}
|
|
collections={COLLECTIONS}
|
|
decks={DECKS}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByRole('button', { name: /my collection/i }).getAttribute('aria-pressed')).toBe('true');
|
|
expect(screen.getByRole('button', { name: /list/i }).getAttribute('aria-pressed')).toBe('false');
|
|
});
|
|
|
|
it('calls onDestinationChange when switching to a collection', () => {
|
|
const onDestinationChange = vi.fn();
|
|
|
|
render(
|
|
<ScannerDestinationPicker
|
|
gameFilter="All"
|
|
onGameFilterChange={vi.fn()}
|
|
destination={{ type: 'owned', id: null, label: 'My Collection' }}
|
|
onDestinationChange={onDestinationChange}
|
|
collections={COLLECTIONS}
|
|
decks={DECKS}
|
|
/>
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: /^📚 list$/i }));
|
|
|
|
expect(onDestinationChange).toHaveBeenCalledWith({
|
|
type: 'collection',
|
|
id: 1,
|
|
label: 'Modern Staples',
|
|
});
|
|
});
|
|
|
|
it('filters decks by game and disables deck toggle when none match', () => {
|
|
render(
|
|
<ScannerDestinationPicker
|
|
gameFilter="MTG"
|
|
onGameFilterChange={vi.fn()}
|
|
destination={{ type: 'deck', id: 10, label: 'Commander' }}
|
|
onDestinationChange={vi.fn()}
|
|
collections={COLLECTIONS}
|
|
decks={DECKS}
|
|
/>
|
|
);
|
|
|
|
expect(screen.getByRole('button', { name: /deck/i }).disabled).toBe(false);
|
|
expect(screen.queryByText(/Standard/)).toBeNull();
|
|
});
|
|
|
|
it('calls onGameFilterChange when the game select changes', () => {
|
|
const onGameFilterChange = vi.fn();
|
|
|
|
render(
|
|
<ScannerDestinationPicker
|
|
gameFilter="All"
|
|
onGameFilterChange={onGameFilterChange}
|
|
destination={{ type: 'owned', id: null, label: 'My Collection' }}
|
|
onDestinationChange={vi.fn()}
|
|
collections={COLLECTIONS}
|
|
decks={DECKS}
|
|
/>
|
|
);
|
|
|
|
fireEvent.change(screen.getByRole('combobox', { name: /game filter/i }), {
|
|
target: { value: 'Lorcana' },
|
|
});
|
|
expect(onGameFilterChange).toHaveBeenCalledWith('Lorcana');
|
|
});
|
|
});
|