diff --git a/src/components/wizard/BackendSelectionStep.test.tsx b/src/components/wizard/BackendSelectionStep.test.tsx index c352f33..aa99f3d 100644 --- a/src/components/wizard/BackendSelectionStep.test.tsx +++ b/src/components/wizard/BackendSelectionStep.test.tsx @@ -2,7 +2,8 @@ // Covers WIZD-01: card grid renders Azure Blob, Amazon S3, S3-Compatible (Azure first) // Covers WIZD-04: remote name field validates alphanumeric/dash/underscore import { describe, it, expect } from 'vitest'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { WizardProvider } from '../../store/context'; import { BackendSelectionStep } from './BackendSelectionStep'; @@ -42,16 +43,18 @@ describe('BackendSelectionStep', () => { expect(azureIdx).toBeLessThan(s3Idx); }); - it('clicking a backend card dispatches SET_BACKEND_TYPE and SET_STEP', () => { + it('clicking a backend card dispatches SET_BACKEND_TYPE and SET_STEP', async () => { + const user = userEvent.setup(); renderStep(); // Fill in a valid remote name first const nameInput = screen.getByRole('textbox'); - fireEvent.change(nameInput, { target: { value: 'my-remote' } }); + await user.clear(nameInput); + await user.type(nameInput, 'my-remote'); // Click the Azure card — if navigation dispatches SET_STEP(1), component may unmount // We verify no validation error appears (meaning dispatch proceeded) const azureButton = screen.getAllByRole('button').find(b => b.textContent?.includes('Azure Blob Storage'))!; expect(azureButton).toBeDefined(); - fireEvent.click(azureButton); + await user.click(azureButton); // After successful navigation step fires, no validation alert should be present expect(screen.queryByRole('alert')).toBeNull(); }); @@ -77,10 +80,11 @@ describe('BackendSelectionStep', () => { }); it('shows inline error after first Next attempt with invalid name', async () => { + const user = userEvent.setup(); renderStep(); // Click a card without filling in name — triggers validation const azureButton = screen.getAllByRole('button').find(b => b.textContent?.includes('Azure Blob Storage'))!; - fireEvent.click(azureButton); + await user.click(azureButton); // Error should appear after async validation await waitFor(() => { expect(screen.getByRole('alert')).toBeDefined(); @@ -89,11 +93,13 @@ describe('BackendSelectionStep', () => { }); it('accepts alphanumeric, dashes, and underscores', async () => { + const user = userEvent.setup(); renderStep(); const nameInput = screen.getByRole('textbox'); - fireEvent.change(nameInput, { target: { value: 'my-remote_01' } }); + await user.clear(nameInput); + await user.type(nameInput, 'my-remote_01'); const azureButton = screen.getAllByRole('button').find(b => b.textContent?.includes('Azure Blob Storage'))!; - fireEvent.click(azureButton); + await user.click(azureButton); // Valid name — no alert should appear (wait briefly to confirm no error appears) await waitFor(() => { expect(screen.queryByRole('alert')).toBeNull(); @@ -101,11 +107,13 @@ describe('BackendSelectionStep', () => { }); it('rejects names with spaces or special characters', async () => { + const user = userEvent.setup(); renderStep(); const nameInput = screen.getByRole('textbox'); - fireEvent.change(nameInput, { target: { value: 'my remote!' } }); + await user.clear(nameInput); + await user.type(nameInput, 'my remote!'); const azureButton = screen.getAllByRole('button').find(b => b.textContent?.includes('Azure Blob Storage'))!; - fireEvent.click(azureButton); + await user.click(azureButton); // Invalid name — alert should appear after async validation await waitFor(() => { expect(screen.getByRole('alert')).toBeDefined();