Add vitest specs for user-cards quantity validation, scan upload-image auth/rate-limit/MIME gates, ScannerDestinationPicker, and ScannedCardItem. Suite grows 21 → 37 tests. Co-authored-by: Cursor <cursoragent@cursor.com>
91 lines
2.4 KiB
JavaScript
91 lines
2.4 KiB
JavaScript
// @vitest-environment jsdom
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
|
|
import ScannedCardItem from '../../components/ScannedCardItem.js';
|
|
|
|
const BASE_CARD = {
|
|
id: 'scan-1',
|
|
name: 'Lightning Bolt',
|
|
set: 'Alpha',
|
|
databaseId: 99,
|
|
quantity: 1,
|
|
condition: 'NM',
|
|
isFoil: false,
|
|
image_url: null,
|
|
processed: false,
|
|
};
|
|
|
|
function renderItem(overrides = {}, props = {}) {
|
|
const card = { ...BASE_CARD, ...overrides };
|
|
const defaultProps = {
|
|
card,
|
|
collections: [{ id: 1, name: 'Trade Binder' }],
|
|
decks: [{ id: 2, name: 'Burn', game: 'mtg' }],
|
|
selected: false,
|
|
onToggleSelect: vi.fn(),
|
|
onIncrement: vi.fn(),
|
|
onDecrement: vi.fn(),
|
|
onUpdateMetadata: vi.fn(),
|
|
onMarkOwned: vi.fn(),
|
|
onAddToCollection: vi.fn(),
|
|
onAddToDeck: vi.fn(),
|
|
onRemove: vi.fn(),
|
|
...props,
|
|
};
|
|
|
|
return render(<ScannedCardItem {...defaultProps} />);
|
|
}
|
|
|
|
describe('ScannedCardItem', () => {
|
|
beforeEach(() => {
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn().mockResolvedValue({
|
|
ok: true,
|
|
json: async () => ({ quantity: 2 }),
|
|
})
|
|
);
|
|
});
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it('announces ownership count with role=status', async () => {
|
|
renderItem();
|
|
|
|
const badge = await screen.findByRole('status', {
|
|
name: /you already own 2 copies/i,
|
|
});
|
|
expect(badge.textContent).toContain('You own 2');
|
|
});
|
|
|
|
it('calls onUpdateMetadata when condition changes', () => {
|
|
const onUpdateMetadata = vi.fn();
|
|
renderItem({}, { onUpdateMetadata });
|
|
|
|
fireEvent.change(screen.getByRole('combobox', { name: /condition/i }), {
|
|
target: { value: 'LP' },
|
|
});
|
|
expect(onUpdateMetadata).toHaveBeenCalledWith({ condition: 'LP' });
|
|
});
|
|
|
|
it('calls onUpdateMetadata when foil is toggled', () => {
|
|
const onUpdateMetadata = vi.fn();
|
|
renderItem({}, { onUpdateMetadata });
|
|
|
|
fireEvent.click(screen.getByRole('checkbox', { name: /foil/i }));
|
|
expect(onUpdateMetadata).toHaveBeenCalledWith({ isFoil: true });
|
|
});
|
|
|
|
it('does not fetch ownership when the card is not in the catalog', async () => {
|
|
renderItem({ databaseId: null });
|
|
|
|
await waitFor(() => {
|
|
expect(fetch).not.toHaveBeenCalled();
|
|
});
|
|
expect(screen.queryByRole('status')).toBeNull();
|
|
});
|
|
});
|