feat: release OpsXShell 2.1.0 native Tauri edition
This commit is contained in:
1 parent
e9a0d21758
commit
a3dba0c6ed
311 files changed
+31748
-14897
No files matched your search
@@ -0,0 +1,208 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import SessionDialog from '../../src/components/sessions/SessionDialog'
|
||||
import QuickConnectDialog from '../../src/components/sessions/QuickConnectDialog'
|
||||
import { useSessionStore } from '../../src/stores/sessionStore'
|
||||
import { useTabStore } from '../../src/stores/tabStore'
|
||||
import { mockDesktopApi } from '../setup'
|
||||
|
||||
describe('Session workflow acceptance', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
window.opsxApi = mockDesktopApi
|
||||
useSessionStore.setState({ sessions: [] })
|
||||
useTabStore.setState({
|
||||
tabs: [{ id: 'welcome', title: '欢迎', type: 'welcome', isActive: true }],
|
||||
activeTabId: 'welcome',
|
||||
})
|
||||
})
|
||||
|
||||
it('creates and saves a session in the selected group', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onClose = vi.fn()
|
||||
render(<SessionDialog isOpen onClose={onClose} editSession={null} />)
|
||||
|
||||
await user.type(screen.getByPlaceholderText('自动用 user@host'), 'OpsBase 验收')
|
||||
await user.clear(screen.getByPlaceholderText('root@192.168.1.10'))
|
||||
await user.type(screen.getByPlaceholderText('root@192.168.1.10'), 'root@opsbase.cn:55555')
|
||||
expect(screen.getByLabelText('端口')).toHaveValue(55555)
|
||||
await user.click(screen.getByRole('button', { name: /高级选项/ }))
|
||||
await user.clear(screen.getByPlaceholderText('default'))
|
||||
await user.type(screen.getByPlaceholderText('default'), '验收环境')
|
||||
await user.click(screen.getByRole('button', { name: '创建并保存' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDesktopApi.sessionCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
host: 'opsbase.cn',
|
||||
port: 55555,
|
||||
username: 'root',
|
||||
group: '验收环境',
|
||||
})
|
||||
)
|
||||
})
|
||||
expect(useSessionStore.getState().sessions).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'OpsBase 验收',
|
||||
host: 'opsbase.cn',
|
||||
port: 55555,
|
||||
group: '验收环境',
|
||||
}),
|
||||
])
|
||||
expect(onClose).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('defaults new sessions to port 22 and password authentication', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<SessionDialog isOpen onClose={vi.fn()} editSession={null} />)
|
||||
|
||||
expect(screen.getByLabelText('端口')).toHaveValue(22)
|
||||
expect(screen.getByRole('button', { name: '密码' })).toBeVisible()
|
||||
expect(screen.getByRole('button', { name: '密钥' })).toBeVisible()
|
||||
expect(screen.queryByRole('button', { name: 'Agent' })).not.toBeInTheDocument()
|
||||
|
||||
await user.clear(screen.getByLabelText('目标'))
|
||||
await user.type(screen.getByLabelText('目标'), 'admin@example.com')
|
||||
await user.type(screen.getByLabelText('密码'), 'session-secret')
|
||||
await user.click(screen.getByRole('button', { name: '创建并保存' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDesktopApi.sessionCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
host: 'example.com',
|
||||
port: 22,
|
||||
username: 'admin',
|
||||
authType: 'password',
|
||||
password: 'session-secret',
|
||||
privateKey: undefined,
|
||||
passphrase: undefined,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('saves key authentication without retaining a password', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<SessionDialog isOpen onClose={vi.fn()} editSession={null} />)
|
||||
|
||||
await user.clear(screen.getByLabelText('目标'))
|
||||
await user.type(screen.getByLabelText('目标'), 'root@opsbase.cn')
|
||||
await user.click(screen.getByRole('button', { name: '密钥' }))
|
||||
await user.clear(screen.getByLabelText('私钥路径'))
|
||||
await user.type(screen.getByLabelText('私钥路径'), '~/.ssh/id_ed25519')
|
||||
await user.type(screen.getByLabelText('密钥口令(可选)'), 'key-secret')
|
||||
await user.click(screen.getByRole('button', { name: '创建并保存' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDesktopApi.sessionCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
port: 22,
|
||||
authType: 'key',
|
||||
password: undefined,
|
||||
privateKey: '~/.ssh/id_ed25519',
|
||||
passphrase: 'key-secret',
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('saves a SOCKS5 connection proxy with optional credentials', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<SessionDialog isOpen onClose={vi.fn()} editSession={null} />)
|
||||
|
||||
await user.clear(screen.getByLabelText('目标'))
|
||||
await user.type(screen.getByLabelText('目标'), 'admin@internal.example.com')
|
||||
await user.click(screen.getByRole('button', { name: /高级选项/ }))
|
||||
await user.click(screen.getByRole('button', { name: 'SOCKS5' }))
|
||||
await user.type(screen.getByPlaceholderText('代理地址'), '127.0.0.1')
|
||||
await user.type(screen.getByPlaceholderText('用户名(可选)'), 'proxy-user')
|
||||
await user.type(screen.getByPlaceholderText('密码(可选)'), 'proxy-secret')
|
||||
await user.click(screen.getByRole('button', { name: '创建并保存' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDesktopApi.sessionCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
proxy: {
|
||||
type: 'socks5',
|
||||
host: '127.0.0.1',
|
||||
port: 1080,
|
||||
username: 'proxy-user',
|
||||
password: 'proxy-secret',
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('saves one existing session as a ProxyJump host', async () => {
|
||||
const user = userEvent.setup()
|
||||
useSessionStore.setState({
|
||||
sessions: [
|
||||
{
|
||||
id: 'jump-1',
|
||||
name: 'Bastion',
|
||||
host: 'gateway.example.com',
|
||||
port: 22,
|
||||
username: 'ops',
|
||||
authType: 'agent',
|
||||
},
|
||||
],
|
||||
})
|
||||
render(<SessionDialog isOpen onClose={vi.fn()} editSession={null} />)
|
||||
|
||||
await user.clear(screen.getByLabelText('目标'))
|
||||
await user.type(screen.getByLabelText('目标'), 'root@internal.example.com')
|
||||
await user.click(screen.getByRole('button', { name: /高级选项/ }))
|
||||
await user.selectOptions(screen.getByLabelText('跳板机(可选)'), 'jump-1')
|
||||
await user.click(screen.getByRole('button', { name: '创建并保存' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDesktopApi.sessionCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
jumpSessionId: 'jump-1',
|
||||
jumpSessionIds: ['jump-1'],
|
||||
proxy: undefined,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('creates a quick-connect terminal tab with the parsed target', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onClose = vi.fn()
|
||||
render(<QuickConnectDialog isOpen onClose={onClose} />)
|
||||
|
||||
await user.type(screen.getByPlaceholderText('root@192.168.1.10:22'), 'root@opsbase.cn:55555')
|
||||
await user.click(screen.getByRole('button', { name: '连接' }))
|
||||
|
||||
const terminalTab = useTabStore
|
||||
.getState()
|
||||
.tabs.find((tab) => tab.type === 'terminal' && tab.title === 'root@opsbase.cn')
|
||||
|
||||
expect(terminalTab?.connectionConfig).toEqual({
|
||||
host: 'opsbase.cn',
|
||||
port: 55555,
|
||||
username: 'root',
|
||||
password: undefined,
|
||||
})
|
||||
expect(onClose).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('accepts pasted targets in quick connect and new session inputs', async () => {
|
||||
const user = userEvent.setup()
|
||||
const quick = render(<QuickConnectDialog isOpen onClose={vi.fn()} />)
|
||||
const quickTarget = screen.getByPlaceholderText('root@192.168.1.10:22')
|
||||
await user.click(quickTarget)
|
||||
await user.paste('root@opsbase.cn:55555')
|
||||
expect(quickTarget).toHaveValue('root@opsbase.cn:55555')
|
||||
|
||||
quick.unmount()
|
||||
render(<SessionDialog isOpen onClose={vi.fn()} editSession={null} />)
|
||||
const sessionTarget = screen.getByLabelText('目标')
|
||||
await user.clear(sessionTarget)
|
||||
await user.paste('admin@example.com:2200')
|
||||
expect(sessionTarget).toHaveValue('admin@example.com:2200')
|
||||
expect(screen.getByLabelText('端口')).toHaveValue(2200)
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user