mirror of
https://github.com/EKKOLearnAI/hermes-web-ui.git
synced 2026-05-25 13:30:14 +00:00
161 lines
4.3 KiB
TypeScript
161 lines
4.3 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { mount } from '@vue/test-utils'
|
|
|
|
const openSessionSearchMock = vi.hoisted(() => vi.fn())
|
|
const mockAppStore = vi.hoisted(() => ({
|
|
sidebarOpen: true,
|
|
sidebarCollapsed: false,
|
|
connected: true,
|
|
serverVersion: 'test',
|
|
latestVersion: '',
|
|
updateAvailable: false,
|
|
clientOutdated: false,
|
|
updating: false,
|
|
toggleSidebar: vi.fn(),
|
|
toggleSidebarCollapsed: vi.fn(),
|
|
closeSidebar: vi.fn(),
|
|
doUpdate: vi.fn(),
|
|
reloadClient: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/composables/useSessionSearch', () => ({
|
|
useSessionSearch: () => ({
|
|
openSessionSearch: openSessionSearchMock,
|
|
}),
|
|
}))
|
|
|
|
vi.mock('@/stores/hermes/app', () => ({
|
|
useAppStore: () => mockAppStore,
|
|
}))
|
|
|
|
vi.mock('vue-router', async (importOriginal) => {
|
|
const actual = await importOriginal<any>()
|
|
return {
|
|
...actual,
|
|
useRoute: () => ({ name: 'hermes.chat' }),
|
|
useRouter: () => ({ push: vi.fn() }),
|
|
}
|
|
})
|
|
|
|
vi.mock('vue-i18n', () => ({
|
|
useI18n: () => ({
|
|
t: (key: string) => key,
|
|
}),
|
|
createI18n: () => ({
|
|
global: { locale: { value: 'en' }, setLocaleMessage: vi.fn() },
|
|
}),
|
|
}))
|
|
|
|
vi.mock('@/composables/useTheme', () => ({
|
|
useTheme: () => ({ isDark: false }),
|
|
}))
|
|
|
|
vi.mock('/logo.png', () => ({
|
|
default: 'logo.png',
|
|
}))
|
|
|
|
vi.mock('naive-ui', async () => {
|
|
const actual = await vi.importActual<any>('naive-ui')
|
|
return {
|
|
...actual,
|
|
useMessage: () => ({
|
|
success: vi.fn(),
|
|
error: vi.fn(),
|
|
}),
|
|
NButton: {
|
|
template: '<button v-bind="$attrs"><slot /></button>',
|
|
},
|
|
NSelect: {
|
|
template: '<div />',
|
|
},
|
|
}
|
|
})
|
|
|
|
import AppSidebar from '@/components/layout/AppSidebar.vue'
|
|
|
|
describe('AppSidebar search entry', () => {
|
|
beforeEach(() => {
|
|
openSessionSearchMock.mockClear()
|
|
mockAppStore.serverVersion = 'test'
|
|
mockAppStore.latestVersion = ''
|
|
mockAppStore.updateAvailable = false
|
|
mockAppStore.clientOutdated = false
|
|
mockAppStore.updating = false
|
|
mockAppStore.sidebarCollapsed = false
|
|
mockAppStore.reloadClient.mockClear()
|
|
})
|
|
|
|
it('opens the session search modal from the sidebar button', async () => {
|
|
const wrapper = mount(AppSidebar, {
|
|
global: {
|
|
stubs: {
|
|
ProfileSelector: true,
|
|
ModelSelector: true,
|
|
LanguageSwitch: true,
|
|
ThemeSwitch: true,
|
|
NButton: true,
|
|
},
|
|
},
|
|
})
|
|
|
|
const buttons = wrapper.findAll('button')
|
|
const searchButton = buttons.find(node => node.text().includes('sidebar.search'))
|
|
expect(searchButton).toBeTruthy()
|
|
|
|
await searchButton!.trigger('click')
|
|
expect(openSessionSearchMock).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('offers a client reload when the server version differs from the loaded bundle', async () => {
|
|
mockAppStore.clientOutdated = true
|
|
mockAppStore.serverVersion = '0.5.17'
|
|
const wrapper = mount(AppSidebar, {
|
|
global: {
|
|
stubs: {
|
|
ProfileSelector: true,
|
|
ModelSelector: true,
|
|
LanguageSwitch: true,
|
|
ThemeSwitch: true,
|
|
},
|
|
},
|
|
})
|
|
|
|
const reloadButton = wrapper.findAll('button')
|
|
.find(node => node.text().includes('sidebar.reloadClientVersion'))
|
|
expect(reloadButton).toBeTruthy()
|
|
|
|
await reloadButton!.trigger('click')
|
|
expect(mockAppStore.reloadClient).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('uses short group labels and keeps group folding active when collapsed', async () => {
|
|
mockAppStore.sidebarCollapsed = true
|
|
const wrapper = mount(AppSidebar, {
|
|
global: {
|
|
stubs: {
|
|
ProfileSelector: true,
|
|
ModelSelector: true,
|
|
LanguageSwitch: true,
|
|
ThemeSwitch: true,
|
|
NButton: true,
|
|
},
|
|
},
|
|
})
|
|
|
|
expect(wrapper.classes()).toContain('collapsed')
|
|
expect(wrapper.findAll('.nav-group-label span').map(node => node.text())).toEqual([
|
|
'sidebar.groupConversationShort',
|
|
'sidebar.groupAgentShort',
|
|
'sidebar.groupMonitoringShort',
|
|
'sidebar.groupSystemShort',
|
|
])
|
|
|
|
const agentGroup = wrapper.findAll('.nav-group')[1]
|
|
expect(agentGroup.find('.nav-group-items').attributes('style')).toBeUndefined()
|
|
|
|
await agentGroup.find('.nav-group-label').trigger('click')
|
|
expect(agentGroup.find('.nav-group-items').attributes('style')).toContain('display: none')
|
|
})
|
|
})
|