From aeb1528163c0d32443bb82bb4bd118da3603ffb1 Mon Sep 17 00:00:00 2001 From: Kawa Date: Wed, 1 Apr 2026 16:51:54 +0200 Subject: [PATCH] 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 --- .../wizard/BackendSelectionStep.test.tsx | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/components/wizard/BackendSelectionStep.test.tsx b/src/components/wizard/BackendSelectionStep.test.tsx index e8de7bb..0f99c01 100644 --- a/src/components/wizard/BackendSelectionStep.test.tsx +++ b/src/components/wizard/BackendSelectionStep.test.tsx @@ -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(); + }); + }); });