// @vitest-environment jsdom import { beforeEach, describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import { createTestingPinia } from '@pinia/testing' import { nextTick } from 'vue' import GroupChatInput from '@/components/hermes/group-chat/GroupChatInput.vue' import { useGroupChatStore } from '@/stores/hermes/group-chat' import { useSettingsStore } from '@/stores/hermes/settings' vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (key: string) => key }), })) vi.mock('naive-ui', () => ({ NButton: { template: '' }, NTooltip: { template: '
' }, NSwitch: { template: '' }, NDropdown: { template: '
' }, })) vi.mock('@/composables/useToolTraceVisibility', () => ({ useToolTraceVisibility: () => ({ toolTraceVisible: { value: true }, toggleToolTraceVisible: vi.fn() }), })) describe('GroupChatInput mentions', () => { beforeEach(() => { localStorage.clear() window.innerWidth = 1024 }) it('updates mention suggestions after the textarea has a custom height', async () => { const pinia = createTestingPinia({ stubActions: false, createSpy: vi.fn }) const settingsStore = useSettingsStore() settingsStore.display = {} const store = useGroupChatStore() store.agents = [{ id: 'agent-1', agentId: 'agent-1', profile: 'worker', name: 'Worker', roomId: 'room-1', description: '', invited: 1 }] store.emitTyping = vi.fn() const wrapper = mount(GroupChatInput, { attachTo: document.body, global: { plugins: [pinia], stubs: { Transition: false } }, }) const textarea = wrapper.get('textarea') const resizeHandle = wrapper.get('.resize-handle') await resizeHandle.trigger('mousedown', { clientY: 100 }) document.dispatchEvent(new MouseEvent('mousemove', { clientY: 50 })) document.dispatchEvent(new MouseEvent('mouseup')) await nextTick() await textarea.setValue('@') await nextTick() expect(wrapper.find('.mention-dropdown').exists()).toBe(true) expect(wrapper.find('.mention-dropdown').text()).toContain('@Worker') }) it('applies the configured desktop input height', async () => { const pinia = createTestingPinia({ stubActions: false, createSpy: vi.fn }) const settingsStore = useSettingsStore() settingsStore.display = { chat_input_height: 168 } const wrapper = mount(GroupChatInput, { global: { plugins: [pinia], stubs: { Transition: false } }, }) await nextTick() expect((wrapper.get('textarea').element as HTMLTextAreaElement).style.height).toBe('168px') expect((wrapper.get('.input-wrapper').element as HTMLElement).style.minHeight).toBe('231px') }) it('applies display setting changes after a manual resize', async () => { const pinia = createTestingPinia({ stubActions: false, createSpy: vi.fn }) const settingsStore = useSettingsStore() settingsStore.display = {} const wrapper = mount(GroupChatInput, { global: { plugins: [pinia], stubs: { Transition: false } }, }) const resizeHandle = wrapper.get('.resize-handle') await resizeHandle.trigger('mousedown', { clientY: 100 }) document.dispatchEvent(new MouseEvent('mousemove', { clientY: 50 })) document.dispatchEvent(new MouseEvent('mouseup')) await nextTick() settingsStore.display.chat_input_height = 216 await nextTick() expect((wrapper.get('textarea').element as HTMLTextAreaElement).style.height).toBe('216px') expect((wrapper.get('.input-wrapper').element as HTMLElement).style.minHeight).toBe('279px') }) it('preserves mobile auto height when a desktop preference is configured', async () => { window.innerWidth = 640 const pinia = createTestingPinia({ stubActions: false, createSpy: vi.fn }) const settingsStore = useSettingsStore() settingsStore.display = { chat_input_height: 168 } const wrapper = mount(GroupChatInput, { global: { plugins: [pinia], stubs: { Transition: false } }, }) await nextTick() expect((wrapper.get('textarea').element as HTMLTextAreaElement).style.height).not.toBe('168px') }) })