diff --git a/package-lock.json b/package-lock.json
index 143b7b9..56b51fa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"@tailwindcss/vite": "^4.2.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
+ "@testing-library/user-event": "^14.6.1",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.7.0",
@@ -1797,6 +1798,20 @@
}
}
},
+ "node_modules/@testing-library/user-event": {
+ "version": "14.6.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz",
+ "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": ">=7.21.4"
+ }
+ },
"node_modules/@types/aria-query": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
diff --git a/package.json b/package.json
index e501e66..2f907db 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"@tailwindcss/vite": "^4.2.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
+ "@testing-library/user-event": "^14.6.1",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.7.0",
diff --git a/src/components/wizard/RemoteConfigStep.test.tsx b/src/components/wizard/RemoteConfigStep.test.tsx
index e549f9c..bbc18c9 100644
--- a/src/components/wizard/RemoteConfigStep.test.tsx
+++ b/src/components/wizard/RemoteConfigStep.test.tsx
@@ -3,43 +3,117 @@
// Covers BACK-02: Amazon S3 config form — access_key_id, secret_access_key, region
// Covers BACK-03: S3-Compatible config form — same as S3 plus endpoint field
import { describe, it, expect } from 'vitest';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { useEffect } from 'react';
+import { WizardProvider } from '../../store/context';
+import { useWizard } from '../../store/context';
+import type { BackendType } from '../../schemas/registry';
+import { RemoteConfigStep } from './RemoteConfigStep';
+
+function renderWithBackend(backendType: BackendType) {
+ function Setup() {
+ const { dispatch } = useWizard();
+ useEffect(() => {
+ dispatch({ type: 'SET_BACKEND_TYPE', payload: backendType });
+ dispatch({ type: 'SET_STEP', payload: 1 });
+ }, []);
+ return ;
+ }
+ return render(
+
+
+
+ );
+}
describe('RemoteConfigStep', () => {
describe('BACK-01: Azure Blob form', () => {
- it('renders Storage Account Name field', () => {
- expect.fail('not yet implemented');
+ it('renders Storage Account Name field', async () => {
+ renderWithBackend('azureblob');
+ await waitFor(() => {
+ expect(screen.getByLabelText(/storage account name/i)).toBeInTheDocument();
+ });
});
- it('shows SAS URL field by default (default auth method)', () => {
- expect.fail('not yet implemented');
+ it('shows SAS URL field by default (default auth method)', async () => {
+ renderWithBackend('azureblob');
+ await waitFor(() => {
+ expect(screen.getByLabelText(/sas url/i)).toBeInTheDocument();
+ });
});
- it('switching auth toggle to Access Key shows key field and hides SAS URL', () => {
- expect.fail('not yet implemented');
+ it('switching auth toggle to Access Key shows key field and hides SAS URL', async () => {
+ renderWithBackend('azureblob');
+ await waitFor(() => {
+ expect(screen.getByText(/access key/i, { selector: 'button' })).toBeInTheDocument();
+ });
+ fireEvent.click(screen.getByText(/access key/i, { selector: 'button' }));
+ await waitFor(() => {
+ const sasWrapper = screen.getByLabelText(/sas url/i).closest('div.hidden, div[class*="hidden"]');
+ const keyWrapper = screen.getByLabelText(/access key/i).closest('div.block, div[class*="block"]');
+ expect(sasWrapper).toBeTruthy();
+ expect(keyWrapper).toBeTruthy();
+ });
});
- it('switching auth toggle does not clear the hidden field value', () => {
- expect.fail('not yet implemented');
+ it('switching auth toggle does not clear the hidden field value', async () => {
+ const user = userEvent.setup();
+ renderWithBackend('azureblob');
+
+ // Wait for form to render
+ await waitFor(() => {
+ expect(screen.getByLabelText(/sas url/i)).toBeInTheDocument();
+ });
+
+ // Type a value into the SAS URL field
+ const sasInput = screen.getByLabelText(/sas url/i);
+ await user.type(sasInput, 'https://mystorage.blob.core.windows.net/?sv=test');
+
+ // Switch to Access Key
+ fireEvent.click(screen.getByText(/access key/i, { selector: 'button' }));
+
+ // Switch back to SAS URL
+ fireEvent.click(screen.getByText(/sas url/i, { selector: 'button' }));
+
+ // The value should still be there
+ await waitFor(() => {
+ expect(screen.getByLabelText(/sas url/i)).toHaveValue('https://mystorage.blob.core.windows.net/?sv=test');
+ });
});
});
describe('BACK-02: Amazon S3 form', () => {
- it('renders access_key_id field', () => {
- expect.fail('not yet implemented');
+ it('renders access_key_id field', async () => {
+ renderWithBackend('s3');
+ await waitFor(() => {
+ expect(screen.getByLabelText(/access key id/i)).toBeInTheDocument();
+ });
});
- it('renders secret_access_key field', () => {
- expect.fail('not yet implemented');
+ it('renders secret_access_key field', async () => {
+ renderWithBackend('s3');
+ await waitFor(() => {
+ expect(screen.getByLabelText(/secret access key/i)).toBeInTheDocument();
+ });
});
- it('renders region field', () => {
- expect.fail('not yet implemented');
+ it('renders region field', async () => {
+ renderWithBackend('s3');
+ await waitFor(() => {
+ expect(screen.getByLabelText(/region/i)).toBeInTheDocument();
+ });
});
});
describe('BACK-03: S3-Compatible form', () => {
- it('renders endpoint field in addition to S3 fields', () => {
- expect.fail('not yet implemented');
+ it('renders endpoint field in addition to S3 fields', async () => {
+ renderWithBackend('s3-compatible');
+ await waitFor(() => {
+ expect(screen.getByLabelText(/endpoint url/i)).toBeInTheDocument();
+ expect(screen.getByLabelText(/access key id/i)).toBeInTheDocument();
+ expect(screen.getByLabelText(/secret access key/i)).toBeInTheDocument();
+ });
});
});
});