feat: v0.3.0 版本 - SSH终端、SFTP、端口转发功能实现
核心功能: - SSH终端: 密码/密钥认证、XTerm.js终端、多主题配色、IP高亮 - SFTP管理: 双栏文件管理、上传下载、传输队列 - 端口转发: 本地/远程转发、SOCKS5动态代理、规则管理 架构改进: - 拆分大型组件 (SFTPView/TabBar/Sidebar) - 添加统一日志和错误处理 - 修复React严格模式下的终端黑屏问题 UI更新: - 新增端口转发视图 - 更新UI预览文档 - 左侧栏右键菜单支持SFTP快捷打开
This commit is contained in:
1 parent
cf1c054381
commit
484d850abd
105 files changed
+25330
-64
No files matched your search
+114
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Vitest Setup - 测试环境配置
|
||||
*/
|
||||
|
||||
import '@testing-library/jest-dom'
|
||||
import { vi } from 'vitest'
|
||||
|
||||
// Mock Electron API
|
||||
const mockElectronAPI = {
|
||||
// SSH
|
||||
sshConnect: vi.fn().mockResolvedValue({ success: true, connectionId: 'test-conn-1' }),
|
||||
sshDisconnect: vi.fn().mockResolvedValue({ success: true }),
|
||||
sshExec: vi.fn().mockResolvedValue({ success: true, stdout: '', stderr: '' }),
|
||||
sshCreateShell: vi.fn().mockResolvedValue({ success: true, shellId: 'test-shell-1' }),
|
||||
sshShellWrite: vi.fn().mockResolvedValue({ success: true }),
|
||||
sshShellResize: vi.fn().mockResolvedValue({ success: true }),
|
||||
sshForwardLocal: vi.fn().mockResolvedValue({ success: true }),
|
||||
sshForwardRemote: vi.fn().mockResolvedValue({ success: true }),
|
||||
|
||||
// SFTP
|
||||
sftpConnect: vi.fn().mockResolvedValue({ success: true, sftpId: 'test-sftp-1' }),
|
||||
sftpListDirectory: vi.fn().mockResolvedValue({ success: true, files: [] }),
|
||||
sftpUpload: vi.fn().mockResolvedValue({ success: true }),
|
||||
sftpDownload: vi.fn().mockResolvedValue({ success: true }),
|
||||
sftpRename: vi.fn().mockResolvedValue({ success: true }),
|
||||
sftpDelete: vi.fn().mockResolvedValue({ success: true }),
|
||||
sftpMkdir: vi.fn().mockResolvedValue({ success: true }),
|
||||
onSFTPProgress: vi.fn(),
|
||||
|
||||
// Session
|
||||
getSessions: vi.fn().mockResolvedValue({ success: true, sessions: [] }),
|
||||
getSession: vi.fn().mockResolvedValue({ success: true, session: null }),
|
||||
createSession: vi.fn().mockResolvedValue({ success: true, id: 'test-session-1' }),
|
||||
updateSession: vi.fn().mockResolvedValue({ success: true }),
|
||||
deleteSession: vi.fn().mockResolvedValue({ success: true }),
|
||||
|
||||
// Settings
|
||||
getSettings: vi.fn().mockResolvedValue({ success: true, settings: {} }),
|
||||
setSettings: vi.fn().mockResolvedValue({ success: true }),
|
||||
|
||||
// Dialog
|
||||
showSaveDialog: vi.fn().mockResolvedValue({ success: true, canceled: false, filePath: '/tmp/test' }),
|
||||
showOpenDialog: vi.fn().mockResolvedValue({ success: true, canceled: false, filePaths: ['/tmp/test'] }),
|
||||
|
||||
// File
|
||||
localReadDir: vi.fn().mockResolvedValue({ success: true, files: [] }),
|
||||
localReadFile: vi.fn().mockResolvedValue({ success: true, content: '' }),
|
||||
localWriteFile: vi.fn().mockResolvedValue({ success: true }),
|
||||
localRename: vi.fn().mockResolvedValue({ success: true }),
|
||||
localDelete: vi.fn().mockResolvedValue({ success: true }),
|
||||
localMkdir: vi.fn().mockResolvedValue({ success: true }),
|
||||
getHomePath: vi.fn().mockResolvedValue({ success: true, path: '/Users/test' }),
|
||||
getDownloadsPath: vi.fn().mockResolvedValue({ success: true, path: '/Users/test/Downloads' }),
|
||||
|
||||
// Zmodem
|
||||
onZmodemSend: vi.fn(),
|
||||
|
||||
// App
|
||||
getVersion: vi.fn().mockResolvedValue('1.0.0'),
|
||||
getPlatform: vi.fn().mockReturnValue('darwin'),
|
||||
|
||||
// Event listeners
|
||||
onShellData: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
}
|
||||
|
||||
window.electronAPI = mockElectronAPI as any
|
||||
|
||||
// Mock navigator
|
||||
Object.defineProperty(window, 'navigator', {
|
||||
value: { platform: 'MacIntel' },
|
||||
writable: true
|
||||
})
|
||||
|
||||
// Mock ResizeObserver
|
||||
class ResizeObserverMock {
|
||||
observe() {}
|
||||
unobserve() {}
|
||||
disconnect() {}
|
||||
}
|
||||
window.ResizeObserver = ResizeObserverMock
|
||||
|
||||
// Mock matchMedia
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
value: vi.fn().mockImplementation(query => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
dispatchEvent: vi.fn(),
|
||||
})),
|
||||
})
|
||||
|
||||
// Suppress console errors in tests
|
||||
const originalError = console.error
|
||||
beforeAll(() => {
|
||||
console.error = (...args: any[]) => {
|
||||
if (
|
||||
typeof args[0] === 'string' &&
|
||||
(args[0].includes('Warning:') || args[0].includes('ReactDOM.render'))
|
||||
) {
|
||||
return
|
||||
}
|
||||
originalError.call(console, ...args)
|
||||
}
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
console.error = originalError
|
||||
})
|
||||
Reference in new issue
Block a user