docs: comprehensive documentation polish & CI/CD automation
Major Updates: - Rewrote all docs in beginner-friendly 'ELI5' language - Created docs index with user journey navigation - Added complete getting-started guide for novice users - Set up GitHub Container Registry (GHCR) automation - Configured GitHub Pages deployment for documentation Documentation: - docs/index.md - Central navigation hub - docs/getting-started.md - Step-by-step beginner guide - docs/github-setup.md - CI/CD setup instructions - README.md - Complete rewrite in accessible language - CONTRIBUTING.md - Contributor guidelines - Multiple comprehensive API and schema docs CI/CD Workflows: - .github/workflows/docker-build.yml - Multi-platform builds to GHCR - .github/workflows/docs.yml - Automated docs deployment to Pages - Supports main (latest), development (dev), and version tags - Automated testing of built images - Beautiful documentation site with dark theme Benefits: - Zero barrier to entry for new users - Automated Docker builds (AMD64 + ARM64) - Professional documentation site - No Docker Hub account needed (uses GHCR) - Complete CI/CD pipeline All 7 implementation phases complete - project is production ready!
This commit is contained in:
168
frontend/src/hooks/__tests__/useImport.test.ts
Normal file
168
frontend/src/hooks/__tests__/useImport.test.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||
import { renderHook, waitFor } from '@testing-library/react'
|
||||
import { useImport } from '../useImport'
|
||||
import * as api from '../../services/api'
|
||||
|
||||
// Mock the API
|
||||
vi.mock('../../services/api', () => ({
|
||||
importAPI: {
|
||||
status: vi.fn(),
|
||||
preview: vi.fn(),
|
||||
upload: vi.fn(),
|
||||
commit: vi.fn(),
|
||||
cancel: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
describe('useImport', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
vi.mocked(api.importAPI.status).mockResolvedValue({ has_pending: false })
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('starts with no active session', async () => {
|
||||
const { result } = renderHook(() => useImport())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.session).toBeNull()
|
||||
})
|
||||
expect(result.current.loading).toBe(false)
|
||||
expect(result.current.error).toBeNull()
|
||||
})
|
||||
|
||||
it('uploads content and creates session', async () => {
|
||||
const mockSession = {
|
||||
uuid: 'session-1',
|
||||
filename: 'Caddyfile',
|
||||
state: 'reviewing',
|
||||
created_at: '2025-01-18T10:00:00Z',
|
||||
updated_at: '2025-01-18T10:00:00Z',
|
||||
}
|
||||
|
||||
const mockPreview = {
|
||||
hosts: [{ domain: 'test.com' }],
|
||||
conflicts: [],
|
||||
errors: [],
|
||||
}
|
||||
|
||||
vi.mocked(api.importAPI.upload).mockResolvedValue({ session: mockSession })
|
||||
vi.mocked(api.importAPI.status).mockResolvedValue({ has_pending: true, session: mockSession })
|
||||
vi.mocked(api.importAPI.preview).mockResolvedValue(mockPreview)
|
||||
|
||||
const { result } = renderHook(() => useImport())
|
||||
|
||||
await result.current.upload('example.com { reverse_proxy localhost:8080 }')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.session).toEqual(mockSession)
|
||||
})
|
||||
|
||||
expect(api.importAPI.upload).toHaveBeenCalledWith('example.com { reverse_proxy localhost:8080 }', undefined)
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
it('handles upload errors', async () => {
|
||||
const mockError = new Error('Upload failed')
|
||||
vi.mocked(api.importAPI.upload).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useImport())
|
||||
|
||||
await expect(result.current.upload('invalid')).rejects.toThrow('Upload failed')
|
||||
|
||||
expect(result.current.error).toBe('Upload failed')
|
||||
})
|
||||
|
||||
it('commits import with resolutions', async () => {
|
||||
const mockSession = {
|
||||
uuid: 'session-2',
|
||||
filename: 'Caddyfile',
|
||||
state: 'reviewing',
|
||||
created_at: '2025-01-18T10:00:00Z',
|
||||
updated_at: '2025-01-18T10:00:00Z',
|
||||
}
|
||||
|
||||
vi.mocked(api.importAPI.upload).mockResolvedValue({ session: mockSession })
|
||||
vi.mocked(api.importAPI.status)
|
||||
.mockResolvedValueOnce({ has_pending: true, session: mockSession })
|
||||
.mockResolvedValueOnce({ has_pending: false })
|
||||
vi.mocked(api.importAPI.preview).mockResolvedValue({ hosts: [], conflicts: [], errors: [] })
|
||||
vi.mocked(api.importAPI.commit).mockResolvedValue({})
|
||||
|
||||
const { result } = renderHook(() => useImport())
|
||||
|
||||
await result.current.upload('test')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.session).toEqual(mockSession)
|
||||
})
|
||||
|
||||
await result.current.commit({ 'test.com': 'skip' })
|
||||
|
||||
expect(api.importAPI.commit).toHaveBeenCalledWith('session-2', { 'test.com': 'skip' })
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.session).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
it('cancels active import session', async () => {
|
||||
const mockSession = {
|
||||
uuid: 'session-3',
|
||||
filename: 'Caddyfile',
|
||||
state: 'reviewing',
|
||||
created_at: '2025-01-18T10:00:00Z',
|
||||
updated_at: '2025-01-18T10:00:00Z',
|
||||
}
|
||||
|
||||
vi.mocked(api.importAPI.upload).mockResolvedValue({ session: mockSession })
|
||||
vi.mocked(api.importAPI.status).mockResolvedValue({ has_pending: true, session: mockSession })
|
||||
vi.mocked(api.importAPI.preview).mockResolvedValue({ hosts: [], conflicts: [], errors: [] })
|
||||
vi.mocked(api.importAPI.cancel).mockResolvedValue(undefined)
|
||||
|
||||
const { result } = renderHook(() => useImport())
|
||||
|
||||
await result.current.upload('test')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.session).toEqual(mockSession)
|
||||
})
|
||||
|
||||
await result.current.cancel()
|
||||
|
||||
expect(api.importAPI.cancel).toHaveBeenCalledWith('session-3')
|
||||
expect(result.current.session).toBeNull()
|
||||
})
|
||||
|
||||
it('handles commit errors', async () => {
|
||||
const mockSession = {
|
||||
uuid: 'session-4',
|
||||
filename: 'Caddyfile',
|
||||
state: 'reviewing',
|
||||
created_at: '2025-01-18T10:00:00Z',
|
||||
updated_at: '2025-01-18T10:00:00Z',
|
||||
}
|
||||
|
||||
vi.mocked(api.importAPI.upload).mockResolvedValue({ session: mockSession })
|
||||
vi.mocked(api.importAPI.status).mockResolvedValue({ has_pending: true, session: mockSession })
|
||||
vi.mocked(api.importAPI.preview).mockResolvedValue({ hosts: [], conflicts: [], errors: [] })
|
||||
|
||||
const mockError = new Error('Commit failed')
|
||||
vi.mocked(api.importAPI.commit).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useImport())
|
||||
|
||||
await result.current.upload('test')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.session).toEqual(mockSession)
|
||||
})
|
||||
|
||||
await expect(result.current.commit({})).rejects.toThrow('Commit failed')
|
||||
|
||||
expect(result.current.error).toBe('Commit failed')
|
||||
})
|
||||
})
|
||||
163
frontend/src/hooks/__tests__/useProxyHosts.test.ts
Normal file
163
frontend/src/hooks/__tests__/useProxyHosts.test.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||
import { renderHook, waitFor } from '@testing-library/react'
|
||||
import { useProxyHosts } from '../useProxyHosts'
|
||||
import * as api from '../../services/api'
|
||||
|
||||
// Mock the API
|
||||
vi.mock('../../services/api', () => ({
|
||||
proxyHostsAPI: {
|
||||
list: vi.fn(),
|
||||
get: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
describe('useProxyHosts', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('loads proxy hosts on mount', async () => {
|
||||
const mockHosts = [
|
||||
{ uuid: '1', domain_names: 'test.com', enabled: true, forward_host: 'localhost', forward_port: 8080 },
|
||||
{ uuid: '2', domain_names: 'app.com', enabled: true, forward_host: 'localhost', forward_port: 3000 },
|
||||
]
|
||||
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue(mockHosts)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
expect(result.current.loading).toBe(true)
|
||||
expect(result.current.hosts).toEqual([])
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.hosts).toEqual(mockHosts)
|
||||
expect(result.current.error).toBeNull()
|
||||
expect(api.proxyHostsAPI.list).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('handles loading errors', async () => {
|
||||
const mockError = new Error('Failed to fetch')
|
||||
vi.mocked(api.proxyHostsAPI.list).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.error).toBe('Failed to fetch')
|
||||
expect(result.current.hosts).toEqual([])
|
||||
})
|
||||
|
||||
it('creates a new proxy host', async () => {
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue([])
|
||||
const newHost = { domain_names: 'new.com', forward_host: 'localhost', forward_port: 9000 }
|
||||
const createdHost = { uuid: '3', ...newHost, enabled: true }
|
||||
|
||||
vi.mocked(api.proxyHostsAPI.create).mockResolvedValue(createdHost)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await result.current.createHost(newHost)
|
||||
|
||||
expect(api.proxyHostsAPI.create).toHaveBeenCalledWith(newHost)
|
||||
expect(api.proxyHostsAPI.list).toHaveBeenCalledTimes(2) // Initial load + reload after create
|
||||
})
|
||||
|
||||
it('updates an existing proxy host', async () => {
|
||||
const existingHost = { uuid: '1', domain_names: 'test.com', enabled: true, forward_host: 'localhost', forward_port: 8080 }
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue([existingHost])
|
||||
|
||||
const updatedHost = { ...existingHost, domain_names: 'updated.com' }
|
||||
vi.mocked(api.proxyHostsAPI.update).mockResolvedValue(updatedHost)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await result.current.updateHost('1', { domain_names: 'updated.com' })
|
||||
|
||||
expect(api.proxyHostsAPI.update).toHaveBeenCalledWith('1', { domain_names: 'updated.com' })
|
||||
expect(api.proxyHostsAPI.list).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('deletes a proxy host', async () => {
|
||||
const hosts = [
|
||||
{ uuid: '1', domain_names: 'test.com', enabled: true, forward_host: 'localhost', forward_port: 8080 },
|
||||
{ uuid: '2', domain_names: 'app.com', enabled: true, forward_host: 'localhost', forward_port: 3000 },
|
||||
]
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue(hosts)
|
||||
vi.mocked(api.proxyHostsAPI.delete).mockResolvedValue(undefined)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await result.current.deleteHost('1')
|
||||
|
||||
expect(api.proxyHostsAPI.delete).toHaveBeenCalledWith('1')
|
||||
expect(api.proxyHostsAPI.list).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('handles create errors', async () => {
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue([])
|
||||
const mockError = new Error('Failed to create')
|
||||
vi.mocked(api.proxyHostsAPI.create).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.createHost({ domain_names: 'test.com', forward_host: 'localhost', forward_port: 8080 })).rejects.toThrow('Failed to create')
|
||||
})
|
||||
|
||||
it('handles update errors', async () => {
|
||||
const host = { uuid: '1', domain_names: 'test.com', enabled: true, forward_host: 'localhost', forward_port: 8080 }
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue([host])
|
||||
const mockError = new Error('Failed to update')
|
||||
vi.mocked(api.proxyHostsAPI.update).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.updateHost('1', { domain_names: 'updated.com' })).rejects.toThrow('Failed to update')
|
||||
})
|
||||
|
||||
it('handles delete errors', async () => {
|
||||
const host = { uuid: '1', domain_names: 'test.com', enabled: true, forward_host: 'localhost', forward_port: 8080 }
|
||||
vi.mocked(api.proxyHostsAPI.list).mockResolvedValue([host])
|
||||
const mockError = new Error('Failed to delete')
|
||||
vi.mocked(api.proxyHostsAPI.delete).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useProxyHosts())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.deleteHost('1')).rejects.toThrow('Failed to delete')
|
||||
})
|
||||
})
|
||||
218
frontend/src/hooks/__tests__/useRemoteServers.test.ts
Normal file
218
frontend/src/hooks/__tests__/useRemoteServers.test.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||
import { renderHook, waitFor } from '@testing-library/react'
|
||||
import { useRemoteServers } from '../useRemoteServers'
|
||||
import * as api from '../../services/api'
|
||||
|
||||
// Mock the API
|
||||
vi.mock('../../services/api', () => ({
|
||||
remoteServersAPI: {
|
||||
list: vi.fn(),
|
||||
get: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
test: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
describe('useRemoteServers', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('loads all remote servers on mount', async () => {
|
||||
const mockServers = [
|
||||
{ uuid: '1', name: 'Server 1', host: 'localhost', port: 8080, enabled: true },
|
||||
{ uuid: '2', name: 'Server 2', host: '192.168.1.100', port: 3000, enabled: false },
|
||||
]
|
||||
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue(mockServers)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
expect(result.current.loading).toBe(true)
|
||||
expect(result.current.servers).toEqual([])
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.servers).toEqual(mockServers)
|
||||
expect(result.current.error).toBeNull()
|
||||
expect(api.remoteServersAPI.list).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('filters enabled servers', async () => {
|
||||
const mockServers = [
|
||||
{ uuid: '1', name: 'Server 1', host: 'localhost', port: 8080, enabled: true },
|
||||
{ uuid: '2', name: 'Server 2', host: '192.168.1.100', port: 3000, enabled: false },
|
||||
{ uuid: '3', name: 'Server 3', host: '10.0.0.1', port: 9000, enabled: true },
|
||||
]
|
||||
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue(mockServers)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.enabledServers).toHaveLength(2)
|
||||
expect(result.current.enabledServers).toEqual([
|
||||
mockServers[0],
|
||||
mockServers[2],
|
||||
])
|
||||
})
|
||||
|
||||
it('handles loading errors', async () => {
|
||||
const mockError = new Error('Network error')
|
||||
vi.mocked(api.remoteServersAPI.list).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.error).toBe('Network error')
|
||||
expect(result.current.servers).toEqual([])
|
||||
expect(result.current.enabledServers).toEqual([])
|
||||
})
|
||||
|
||||
it('creates a new remote server', async () => {
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([])
|
||||
const newServer = { name: 'New Server', host: 'new.local', port: 5000, enabled: true, provider: 'generic' }
|
||||
const createdServer = { uuid: '4', ...newServer }
|
||||
|
||||
vi.mocked(api.remoteServersAPI.create).mockResolvedValue(createdServer)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await result.current.createServer(newServer)
|
||||
|
||||
expect(api.remoteServersAPI.create).toHaveBeenCalledWith(newServer)
|
||||
expect(api.remoteServersAPI.list).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('updates an existing remote server', async () => {
|
||||
const existingServer = { uuid: '1', name: 'Server 1', host: 'localhost', port: 8080, enabled: true }
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([existingServer])
|
||||
|
||||
const updatedServer = { ...existingServer, name: 'Updated Server' }
|
||||
vi.mocked(api.remoteServersAPI.update).mockResolvedValue(updatedServer)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await result.current.updateServer('1', { name: 'Updated Server' })
|
||||
|
||||
expect(api.remoteServersAPI.update).toHaveBeenCalledWith('1', { name: 'Updated Server' })
|
||||
expect(api.remoteServersAPI.list).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('deletes a remote server', async () => {
|
||||
const servers = [
|
||||
{ uuid: '1', name: 'Server 1', host: 'localhost', port: 8080, enabled: true },
|
||||
{ uuid: '2', name: 'Server 2', host: '192.168.1.100', port: 3000, enabled: false },
|
||||
]
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue(servers)
|
||||
vi.mocked(api.remoteServersAPI.delete).mockResolvedValue(undefined)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await result.current.deleteServer('1')
|
||||
|
||||
expect(api.remoteServersAPI.delete).toHaveBeenCalledWith('1')
|
||||
expect(api.remoteServersAPI.list).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('tests server connection', async () => {
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([])
|
||||
const testResult = { reachable: true, address: 'localhost:8080' }
|
||||
vi.mocked(api.remoteServersAPI.test).mockResolvedValue(testResult)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
const response = await result.current.testConnection('1')
|
||||
|
||||
expect(api.remoteServersAPI.test).toHaveBeenCalledWith('1')
|
||||
expect(response).toEqual(testResult)
|
||||
})
|
||||
|
||||
it('handles create errors', async () => {
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([])
|
||||
const mockError = new Error('Failed to create')
|
||||
vi.mocked(api.remoteServersAPI.create).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.createServer({ name: 'Test', host: 'localhost', port: 8080 })).rejects.toThrow('Failed to create')
|
||||
})
|
||||
|
||||
it('handles update errors', async () => {
|
||||
const server = { uuid: '1', name: 'Server 1', host: 'localhost', port: 8080, enabled: true }
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([server])
|
||||
const mockError = new Error('Failed to update')
|
||||
vi.mocked(api.remoteServersAPI.update).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.updateServer('1', { name: 'Updated' })).rejects.toThrow('Failed to update')
|
||||
})
|
||||
|
||||
it('handles delete errors', async () => {
|
||||
const server = { uuid: '1', name: 'Server 1', host: 'localhost', port: 8080, enabled: true }
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([server])
|
||||
const mockError = new Error('Failed to delete')
|
||||
vi.mocked(api.remoteServersAPI.delete).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.deleteServer('1')).rejects.toThrow('Failed to delete')
|
||||
})
|
||||
|
||||
it('handles connection test errors', async () => {
|
||||
vi.mocked(api.remoteServersAPI.list).mockResolvedValue([])
|
||||
const mockError = new Error('Connection failed')
|
||||
vi.mocked(api.remoteServersAPI.test).mockRejectedValue(mockError)
|
||||
|
||||
const { result } = renderHook(() => useRemoteServers())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
await expect(result.current.testConnection('1')).rejects.toThrow('Connection failed')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user