test(13-03): add search filter and category collapse tests

- 6 new test cases covering REMOTE-03 acceptance criteria
- Tests: all 3 category headings render, ftp search shows FTP+SFTP
- Tests: no-match query hides all categories
- Tests: Cloudflare description match finds S3-Compatible
- Tests: all 18 backend cards render without search
- Tests: category heading hidden when all backends filtered out
This commit is contained in:
2026-04-01 16:51:54 +02:00
parent 0a70620fd5
commit aeb1528163
@@ -2,8 +2,9 @@
// Covers WIZD-01: card grid renders Azure Blob, Amazon S3, S3-Compatible (Azure first)
// Covers WIZD-04: remote name field validates alphanumeric/dash/underscore
// Covers POLISH-04: auto-scroll to first errored field on validation failure
// Covers REMOTE-03: category-grouped, searchable backend selection with icons
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { WizardProvider } from '../../store/context';
import { BackendSelectionStep } from './BackendSelectionStep';
@@ -159,4 +160,60 @@ describe('BackendSelectionStep', () => {
});
});
});
describe('REMOTE-03: category grouping and search', () => {
it('renders all three category headings when no search query', () => {
renderStep();
expect(screen.getByText('Cloud Object Storage')).toBeDefined();
expect(screen.getByText('Cloud Drives')).toBeDefined();
expect(screen.getByText('Protocol-based')).toBeDefined();
});
it('typing "ftp" shows FTP and SFTP backends', () => {
renderStep();
const searchInput = screen.getByPlaceholderText('Search backends...');
fireEvent.change(searchInput, { target: { value: 'ftp' } });
expect(screen.getByText('FTP')).toBeDefined();
expect(screen.getByText('SFTP')).toBeDefined();
// Unrelated cloud backends should not be visible
expect(screen.queryByText('Amazon S3')).toBeNull();
expect(screen.queryByText('Google Drive')).toBeNull();
});
it('typing a query with no matches hides all category headings', () => {
renderStep();
const searchInput = screen.getByPlaceholderText('Search backends...');
fireEvent.change(searchInput, { target: { value: 'zzznomatch999' } });
expect(screen.queryByText('Cloud Object Storage')).toBeNull();
expect(screen.queryByText('Cloud Drives')).toBeNull();
expect(screen.queryByText('Protocol-based')).toBeNull();
});
it('searching "Cloudflare" finds S3-Compatible via description match', () => {
renderStep();
const searchInput = screen.getByPlaceholderText('Search backends...');
fireEvent.change(searchInput, { target: { value: 'Cloudflare' } });
expect(screen.getByText('S3-Compatible')).toBeDefined();
});
it('renders all 18 backend cards when no search active', () => {
renderStep();
// Count all backend card buttons (exclude Next button)
const backendContainer = screen.getByTestId('backend-cards');
const cardButtons = backendContainer.querySelectorAll('button');
expect(cardButtons.length).toBe(18);
});
it('hides category heading when all its backends are filtered out', () => {
renderStep();
const searchInput = screen.getByPlaceholderText('Search backends...');
// "ftp" matches only Protocol-based backends (FTP, SFTP)
fireEvent.change(searchInput, { target: { value: 'ftp' } });
// Cloud Object Storage and Cloud Drives should not appear
expect(screen.queryByText('Cloud Object Storage')).toBeNull();
expect(screen.queryByText('Cloud Drives')).toBeNull();
// Protocol-based should still appear
expect(screen.getByText('Protocol-based')).toBeDefined();
});
});
});