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
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* TabStore Tests - 标签页状态管理测试
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { useTabStore } from '../../src/stores/tabStore'
|
||||
|
||||
describe('TabStore', () => {
|
||||
beforeEach(() => {
|
||||
// Reset store to initial state
|
||||
useTabStore.setState({
|
||||
tabs: [{ id: 'welcome', title: '欢迎', type: 'welcome', isActive: true }],
|
||||
activeTabId: 'welcome',
|
||||
})
|
||||
})
|
||||
|
||||
describe('初始状态', () => {
|
||||
it('应该包含默认的欢迎标签', () => {
|
||||
const { tabs, activeTabId } = useTabStore.getState()
|
||||
expect(tabs).toHaveLength(1)
|
||||
expect(tabs[0].id).toBe('welcome')
|
||||
expect(tabs[0].type).toBe('welcome')
|
||||
expect(activeTabId).toBe('welcome')
|
||||
})
|
||||
})
|
||||
|
||||
describe('addTab', () => {
|
||||
it('应该添加新的终端标签', () => {
|
||||
const { addTab, tabs } = useTabStore.getState()
|
||||
addTab({ title: 'Terminal', type: 'terminal' })
|
||||
|
||||
const newTabs = useTabStore.getState().tabs
|
||||
expect(newTabs).toHaveLength(tabs.length + 1)
|
||||
expect(newTabs.find(t => t.type === 'terminal')).toBeDefined()
|
||||
})
|
||||
|
||||
it('添加新标签后应该激活它', () => {
|
||||
const { addTab } = useTabStore.getState()
|
||||
addTab({ title: 'Terminal', type: 'terminal' })
|
||||
|
||||
const { activeTabId, tabs } = useTabStore.getState()
|
||||
const activeTab = tabs.find(t => t.id === activeTabId)
|
||||
expect(activeTab?.type).toBe('terminal')
|
||||
})
|
||||
|
||||
it('添加 settings 类型时如果已存在则激活而不是创建新的', () => {
|
||||
const { addTab, tabs } = useTabStore.getState()
|
||||
addTab({ title: 'Settings', type: 'settings' })
|
||||
addTab({ title: 'Settings 2', type: 'settings' })
|
||||
|
||||
const newTabs = useTabStore.getState().tabs
|
||||
expect(newTabs).toHaveLength(2) // welcome + settings
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateTab', () => {
|
||||
it('应该更新指定标签的标题', () => {
|
||||
const { updateTab } = useTabStore.getState()
|
||||
updateTab('welcome', { title: '新的标题' })
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
expect(tabs[0].title).toBe('新的标题')
|
||||
})
|
||||
|
||||
it('应该更新标签的连接状态', () => {
|
||||
const { updateTab } = useTabStore.getState()
|
||||
updateTab('welcome', { connectionStatus: 'connected' })
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
expect(tabs[0].connectionStatus).toBe('connected')
|
||||
})
|
||||
})
|
||||
|
||||
describe('closeTab', () => {
|
||||
it('不应该关闭最后一个标签', () => {
|
||||
const { closeTab } = useTabStore.getState()
|
||||
const closed = closeTab('welcome')
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
expect(tabs).toHaveLength(1)
|
||||
expect(closed).toBeNull()
|
||||
})
|
||||
|
||||
it('关闭标签后应该激活另一个标签', () => {
|
||||
const { addTab, closeTab } = useTabStore.getState()
|
||||
addTab({ title: 'Tab 1', type: 'terminal' })
|
||||
addTab({ title: 'Tab 2', type: 'sftp' })
|
||||
|
||||
const { tabs, activeTabId } = useTabStore.getState()
|
||||
const tabToClose = tabs.find(t => t.title === 'Tab 1')
|
||||
|
||||
if (tabToClose) {
|
||||
closeTab(tabToClose.id)
|
||||
const { tabs: newTabs, activeTabId: newActiveId } = useTabStore.getState()
|
||||
expect(newTabs.find(t => t.isActive)?.title).toBe('Tab 2')
|
||||
}
|
||||
})
|
||||
|
||||
it('应该返回被关闭的标签', () => {
|
||||
const { addTab, closeTab } = useTabStore.getState()
|
||||
addTab({ title: 'Tab 1', type: 'terminal' })
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
const tabToClose = tabs.find(t => t.title === 'Tab 1')
|
||||
|
||||
if (tabToClose) {
|
||||
const closed = closeTab(tabToClose.id)
|
||||
expect(closed?.title).toBe('Tab 1')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('closeOtherTabs', () => {
|
||||
it('应该关闭除指定标签外的所有标签', () => {
|
||||
const { addTab, closeOtherTabs, tabs } = useTabStore.getState()
|
||||
addTab({ title: 'Tab 1', type: 'terminal' })
|
||||
addTab({ title: 'Tab 2', type: 'sftp' })
|
||||
|
||||
const tabToKeep = useTabStore.getState().tabs.find(t => t.title === 'Tab 1')
|
||||
if (tabToKeep) {
|
||||
closeOtherTabs(tabToKeep.id)
|
||||
const { tabs: newTabs } = useTabStore.getState()
|
||||
expect(newTabs).toHaveLength(1)
|
||||
expect(newTabs[0].title).toBe('Tab 1')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('activateTab', () => {
|
||||
it('应该激活指定的标签', () => {
|
||||
const { addTab, activateTab } = useTabStore.getState()
|
||||
addTab({ title: 'Tab 1', type: 'terminal' })
|
||||
addTab({ title: 'Tab 2', type: 'sftp' })
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
const tabToActivate = tabs.find(t => t.title === 'Tab 1')
|
||||
|
||||
if (tabToActivate) {
|
||||
activateTab(tabToActivate.id)
|
||||
const { tabs: newTabs, activeTabId } = useTabStore.getState()
|
||||
const activeTab = newTabs.find(t => t.id === activeTabId)
|
||||
expect(activeTab?.title).toBe('Tab 1')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('getTabById', () => {
|
||||
it('应该返回指定 ID 的标签', () => {
|
||||
const { addTab, getTabById } = useTabStore.getState()
|
||||
addTab({ title: 'Test Tab', type: 'terminal' })
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
const testTab = tabs.find(t => t.title === 'Test Tab')
|
||||
|
||||
if (testTab) {
|
||||
const found = getTabById(testTab.id)
|
||||
expect(found?.title).toBe('Test Tab')
|
||||
}
|
||||
})
|
||||
|
||||
it('找不到时应该返回 undefined', () => {
|
||||
const { getTabById } = useTabStore.getState()
|
||||
const found = getTabById('non-existent-id')
|
||||
expect(found).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateTabTitle', () => {
|
||||
it('应该更新标签标题', () => {
|
||||
const { updateTabTitle } = useTabStore.getState()
|
||||
updateTabTitle('welcome', 'Updated Welcome')
|
||||
|
||||
const { tabs } = useTabStore.getState()
|
||||
expect(tabs[0].title).toBe('Updated Welcome')
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user