feat: Update ImportReviewTable and RemoteServerForm components for improved conflict handling and connection testing

This commit is contained in:
Wikid82
2025-11-19 20:10:18 -05:00
parent 04f94d47ff
commit 3c5bdf0a0b
8 changed files with 137 additions and 92 deletions

View File

@@ -22,24 +22,24 @@ describe('ImportReviewTable', () => {
/>
)
expect(screen.getByText('Hosts to Import (1)')).toBeInTheDocument()
expect(screen.getByText('Review Imported Hosts')).toBeInTheDocument()
expect(screen.getByText('test.example.com')).toBeInTheDocument()
})
it('displays conflicts with resolution dropdowns', () => {
const conflicts = ['test.example.com']
render(
<ImportReviewTable
hosts={mockImportPreview.hosts}
conflicts={mockImportPreview.conflicts}
conflicts={conflicts}
errors={[]}
onCommit={mockOnCommit}
onCancel={mockOnCancel}
/>
)
expect(screen.getByText(/Conflicts Detected \(1\)/)).toBeInTheDocument()
expect(screen.getByText('app.local.dev')).toBeInTheDocument()
expect(screen.getByText('-- Choose action --')).toBeInTheDocument()
expect(screen.getByText('test.example.com')).toBeInTheDocument()
expect(screen.getByRole('combobox')).toBeInTheDocument()
})
it('displays errors', () => {
@@ -60,53 +60,19 @@ describe('ImportReviewTable', () => {
expect(screen.getByText('Missing required field')).toBeInTheDocument()
})
it('disables commit button until all conflicts are resolved', () => {
render(
<ImportReviewTable
hosts={mockImportPreview.hosts}
conflicts={mockImportPreview.conflicts}
errors={[]}
onCommit={mockOnCommit}
onCancel={mockOnCancel}
/>
)
const commitButton = screen.getByText('Commit Import')
expect(commitButton).toBeDisabled()
})
it('enables commit button when all conflicts are resolved', async () => {
render(
<ImportReviewTable
hosts={mockImportPreview.hosts}
conflicts={mockImportPreview.conflicts}
errors={[]}
onCommit={mockOnCommit}
onCancel={mockOnCancel}
/>
)
const dropdown = screen.getAllByRole('combobox')[0]
fireEvent.change(dropdown, { target: { value: 'skip' } })
await waitFor(() => {
const commitButton = screen.getByText('Commit Import')
expect(commitButton).not.toBeDisabled()
})
})
it('calls onCommit with resolutions', async () => {
const conflicts = ['test.example.com']
render(
<ImportReviewTable
hosts={mockImportPreview.hosts}
conflicts={mockImportPreview.conflicts}
conflicts={conflicts}
errors={[]}
onCommit={mockOnCommit}
onCancel={mockOnCancel}
/>
)
const dropdown = screen.getAllByRole('combobox')[0]
const dropdown = screen.getByRole('combobox')
fireEvent.change(dropdown, { target: { value: 'overwrite' } })
const commitButton = screen.getByText('Commit Import')
@@ -114,7 +80,7 @@ describe('ImportReviewTable', () => {
await waitFor(() => {
expect(mockOnCommit).toHaveBeenCalledWith({
'app.local.dev': 'overwrite',
'test.example.com': 'overwrite',
})
})
})
@@ -135,26 +101,18 @@ describe('ImportReviewTable', () => {
})
it('shows conflict indicator on conflicting hosts', () => {
const conflicts = ['test.example.com']
render(
<ImportReviewTable
hosts={[
{
domain_names: 'app.local.dev',
forward_scheme: 'http',
forward_host: 'localhost',
forward_port: 3000,
ssl_forced: false,
http2_support: false,
websocket_support: false,
},
]}
conflicts={['app.local.dev']}
hosts={mockImportPreview.hosts}
conflicts={conflicts}
errors={[]}
onCommit={mockOnCommit}
onCancel={mockOnCancel}
/>
)
expect(screen.getByText('Conflict')).toBeInTheDocument()
expect(screen.getByRole('combobox')).toBeInTheDocument()
expect(screen.queryByText('No conflict')).not.toBeInTheDocument()
})
})

View File

@@ -1,5 +1,6 @@
import { describe, it, expect, vi, afterEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import ProxyHostForm from '../ProxyHostForm'
import { mockRemoteServers } from '../../test/mockData'
@@ -10,6 +11,22 @@ vi.mock('../../services/api', () => ({
},
}))
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
})
const renderWithClient = (ui: React.ReactElement) => {
return renderWithClient(
<QueryClientProvider client={queryClient}>
{ui}
</QueryClientProvider>
)
}
describe('ProxyHostForm', () => {
const mockOnSubmit = vi.fn(() => Promise.resolve())
const mockOnCancel = vi.fn()
@@ -19,7 +36,7 @@ describe('ProxyHostForm', () => {
})
it('renders create form with empty fields', async () => {
render(
renderWithClient(
<ProxyHostForm onSubmit={mockOnSubmit} onCancel={mockOnCancel} />
)
@@ -47,7 +64,7 @@ describe('ProxyHostForm', () => {
updated_at: '2025-11-18T10:00:00Z',
}
render(
renderWithClient(
<ProxyHostForm host={mockHost} onSubmit={mockOnSubmit} onCancel={mockOnCancel} />
)
@@ -59,7 +76,7 @@ describe('ProxyHostForm', () => {
})
it('loads remote servers for quick select', async () => {
render(
renderWithClient(
<ProxyHostForm onSubmit={mockOnSubmit} onCancel={mockOnCancel} />
)
@@ -69,7 +86,7 @@ describe('ProxyHostForm', () => {
})
it('calls onCancel when cancel button is clicked', async () => {
render(
renderWithClient(
<ProxyHostForm onSubmit={mockOnSubmit} onCancel={mockOnCancel} />
)
@@ -81,7 +98,7 @@ describe('ProxyHostForm', () => {
})
it('submits form with correct data', async () => {
render(
renderWithClient(
<ProxyHostForm onSubmit={mockOnSubmit} onCancel={mockOnCancel} />
)
@@ -107,7 +124,7 @@ describe('ProxyHostForm', () => {
})
it('handles SSL and WebSocket checkboxes', async () => {
render(
renderWithClient(
<ProxyHostForm onSubmit={mockOnSubmit} onCancel={mockOnCancel} />
)

View File

@@ -92,7 +92,7 @@ describe('RemoteServerForm', () => {
const nameInput = screen.getByPlaceholderText('My Production Server')
const hostInput = screen.getByPlaceholderText('192.168.1.100')
const portInput = screen.getByDisplayValue('80')
const portInput = screen.getByDisplayValue('22')
fireEvent.change(nameInput, { target: { value: 'New Server' } })
fireEvent.change(hostInput, { target: { value: '10.0.0.5' } })