import { describe, it, expect, vi, beforeEach } from 'vitest' import { act, fireEvent, render, screen } from '@testing-library/react' import '@testing-library/jest-dom' import { Settings } from '../pages/Settings' import { useAgentStore } from '../stores/agentStore' import { useSkillStore } from '../stores/skillStore' import { useSettingsStore } from '../stores/settingsStore' import { useSessionStore } from '../stores/sessionStore' import { SETTINGS_TAB_ID, useTabStore } from '../stores/tabStore' import { useUIStore } from '../stores/uiStore' vi.mock('../api/agents', () => ({ agentsApi: { list: vi.fn().mockResolvedValue({ activeAgents: [], allAgents: [] }), }, })) const noopFetch = vi.fn() vi.mock('../stores/providerStore', () => ({ useProviderStore: () => ({ providers: [], activeId: null, presets: [], isLoading: false, isPresetsLoading: false, fetchProviders: vi.fn(), fetchPresets: vi.fn(), deleteProvider: vi.fn(), activateProvider: vi.fn(), activateOfficial: vi.fn(), testProvider: vi.fn(), createProvider: vi.fn(), updateProvider: vi.fn(), testConfig: vi.fn(), }), })) vi.mock('../pages/AdapterSettings', () => ({ AdapterSettings: () =>
{code},
}))
const MOCK_AGENTS = [
{
agentType: 'code-reviewer',
description: 'Reviews code for quality and security',
model: 'claude-sonnet-4-6',
modelDisplay: 'claude-sonnet-4-6',
tools: ['Read', 'Grep', 'Glob'],
systemPrompt: '# Code Reviewer\n\nYou are an expert code reviewer.',
color: 'blue',
source: 'userSettings' as const,
baseDir: '~/.claude/agents',
isActive: true,
},
{
agentType: 'doc-writer',
description: 'Writes technical documentation',
model: 'claude-haiku-4-5',
modelDisplay: 'claude-haiku-4-5',
tools: ['Read'],
systemPrompt: 'You write clear and concise docs.',
color: 'green',
source: 'built-in' as const,
baseDir: 'built-in',
isActive: true,
},
{
agentType: 'plain-agent',
description: undefined,
model: undefined,
modelDisplay: 'inherit',
tools: undefined,
systemPrompt: undefined,
color: undefined,
source: 'projectSettings' as const,
baseDir: '/workspace/project/.claude/agents',
isActive: false,
overriddenBy: 'userSettings' as const,
},
{
agentType: 'telegram:pairing',
description: 'Plugin agent for Telegram pairing flows',
model: 'inherit',
modelDisplay: 'inherit',
tools: ['Read'],
systemPrompt: 'Pair Telegram access for the current workspace.',
color: 'cyan',
source: 'plugin' as const,
baseDir: '/Users/test/.claude/plugins/cache/telegram',
isActive: true,
},
]
const MOCK_SKILL_DETAIL = {
meta: {
name: 'skill-docs',
displayName: 'Skill Docs',
description: 'A rich skill readme',
source: 'user' as const,
userInvocable: true,
contentLength: 200,
hasDirectory: true,
},
tree: [
{ name: 'SKILL.md', path: 'SKILL.md', type: 'file' as const },
{ name: 'helper.ts', path: 'helper.ts', type: 'file' as const },
],
files: [
{
path: 'SKILL.md',
language: 'markdown',
content: '# Heading\n\nParagraph with `inline code`.\n\n## Section\n\n- First item\n- Second item\n\n> Helpful quote',
body: '# Heading\n\nParagraph with `inline code`.\n\n## Section\n\n- First item\n- Second item\n\n> Helpful quote',
isEntry: true,
frontmatter: {
description: 'A rich skill readme',
model: 'sonnet',
},
},
{
path: 'helper.ts',
language: 'typescript',
content: 'export const helper = true',
isEntry: false,
},
],
skillRoot: '/tmp/skill-docs',
}
function switchToAgentsTab() {
fireEvent.click(screen.getByText('Agents'))
}
function switchToSkillsTab() {
fireEvent.click(screen.getByText('Skills'))
}
describe('Settings > Agents tab', () => {
beforeEach(() => {
useSettingsStore.setState({ locale: 'en' })
useTabStore.setState({
activeTabId: 'session-1',
tabs: [{ sessionId: 'session-1', title: 'Test', type: 'session', status: 'idle' }],
})
useUIStore.setState({ pendingSettingsTab: null })
useSessionStore.setState({
sessions: [
{
id: 'session-1',
title: 'Test Session',
createdAt: '',
modifiedAt: '',
messageCount: 0,
projectPath: '/workspace/project',
workDir: '/workspace/project',
workDirExists: true,
},
],
activeSessionId: 'session-1',
isLoading: false,
error: null,
selectedProjects: [],
availableProjects: [],
fetchSessions: noopFetch,
createSession: vi.fn(),
deleteSession: vi.fn(),
renameSession: vi.fn(),
updateSessionTitle: vi.fn(),
setActiveSession: vi.fn(),
setSelectedProjects: vi.fn(),
})
useAgentStore.setState({
activeAgents: [],
allAgents: [],
isLoading: false,
error: null,
selectedAgent: null,
selectedAgentReturnTab: 'agents',
fetchAgents: noopFetch,
selectAgent: (agent) => useAgentStore.setState({ selectedAgent: agent }),
})
useSkillStore.setState({
skills: [],
selectedSkill: null,
isLoading: false,
isDetailLoading: false,
error: null,
fetchSkills: noopFetch,
fetchSkillDetail: noopFetch,
clearSelection: () => useSkillStore.setState({ selectedSkill: null }),
})
})
it('renders the Agents tab button in sidebar', () => {
render(