// @vitest-environment jsdom import { beforeEach, describe, expect, it, vi } from 'vitest' import { defineComponent, h } from 'vue' import { flushPromises, mount } from '@vue/test-utils' import ArcoVue from '@arco-design/web-vue' const mockMessage = vi.hoisted(() => ({ warning: vi.fn(), success: vi.fn(), error: vi.fn(), })) const mockSettingsStore = vi.hoisted(() => ({ platforms: {} as Record, fetchSettings: vi.fn(async () => { mockSettingsStore.platforms = { telegram: { token: 'telegram-token' }, discord: { token: 'discord-token' }, slack: { token: 'slack-token' }, whatsapp: { enabled: true }, matrix: { token: 'matrix-token' }, weixin: { token: 'weixin-token' }, wecom: { extra: { bot_id: 'wecom-bot' } }, feishu: { extra: { app_id: 'feishu-app' } }, dingtalk: { extra: { client_id: 'dingtalk-client' } }, qqbot: { extra: { app_id: 'qq-app', client_secret: 'qq-secret' } }, } }), })) const mockJobsStore = vi.hoisted(() => ({ createJob: vi.fn(), updateJob: vi.fn(), })) const mockAppStore = vi.hoisted(() => ({ modelGroups: [ { provider: 'openai', label: 'OpenAI', models: ['gpt-4.1', 'gpt-4.1-mini'] }, { provider: 'anthropic', label: 'Anthropic', models: ['claude-sonnet-4'] }, ], loadModels: vi.fn(async () => undefined), displayModelName: vi.fn((model: string) => model), })) const mockFetchSkills = vi.hoisted(() => vi.fn(async () => ({ categories: [ { name: 'local', description: '', skills: [ { name: 'planner', description: 'Plan work' }, { name: 'reviewer', description: 'Review work' }, { name: 'disabled-skill', description: 'Disabled', enabled: false }, ], }, ], archived: [], }))) vi.mock('@/stores/hermes/settings', () => ({ useSettingsStore: () => mockSettingsStore, })) vi.mock('@/stores/hermes/jobs', () => ({ useJobsStore: () => mockJobsStore, })) vi.mock('@/stores/hermes/app', () => ({ useAppStore: () => mockAppStore, })) vi.mock('@/api/hermes/jobs', async () => { const actual = await vi.importActual('@/api/hermes/jobs') return { ...actual, getJob: vi.fn(), } }) vi.mock('@/api/hermes/skills', () => ({ fetchSkills: mockFetchSkills, })) vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (key: string) => key, }), })) // Arco's imperative Message API needs a live DOM, so mock the adapter composable. vi.mock('@/composables/useMessage', () => ({ useMessage: () => mockMessage })) /** * Arco's a-select renders a custom dropdown instead of a native