import { fireEvent, render, screen, waitFor, within } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CharacterScene } from '@/pages/Makelore'; import { useAuthStore } from '@/stores/auth'; import { useOpencodeStore } from '@/stores/opencode'; import { usePartnerProfilesStore } from '@/stores/partner-profiles'; import { useProviderStore } from '@/stores/providers'; const hostApiFetchMock = vi.fn(); vi.mock('@/lib/host-api', () => ({ hostApiFetch: (...args: unknown[]) => hostApiFetchMock(...args), ensureHostApiToken: vi.fn().mockResolvedValue('test-token'), })); vi.mock('@/lib/api-client', () => ({ invokeIpc: vi.fn(), })); describe('Makelore character scene partner profiles', () => { beforeEach(() => { vi.clearAllMocks(); hostApiFetchMock.mockResolvedValue({ skills: [] }); useAuthStore.setState({ initialized: true, loading: false, error: null, accessToken: null, refreshToken: null, tokenType: null, expiresAt: null, user: null, }); useOpencodeStore.setState({ activeProject: null, projects: [], sessions: [], selectedSessionId: null }); usePartnerProfilesStore.setState({ subagents: [], projectRuntimeConfigsByProjectId: {}, profilesById: {} }); useProviderStore.setState({ statuses: [], accounts: [], vendors: [], defaultAccountId: null, loading: false, error: null, }); }); it('starts without partner presets and exposes manual creation', () => { render(); expect(screen.getByTestId('partner-empty-state')).toBeInTheDocument(); expect(screen.getByTestId('partner-create-open')).toBeInTheDocument(); expect(screen.queryByText(/角色预设/)).not.toBeInTheDocument(); }); it('creates and saves a custom partner without calling a default-agent route', async () => { render(); fireEvent.click(screen.getByTestId('partner-create-open')); const drawer = await screen.findByRole('dialog'); fireEvent.change(within(drawer).getByTestId('partner-create-name'), { target: { value: '研究伙伴' } }); fireEvent.change(within(drawer).getByTestId('partner-create-prompt'), { target: { value: '先分析资料,再给出可验证的结论。' } }); fireEvent.click(within(drawer).getByRole('button', { name: '创建伙伴' })); await waitFor(() => expect(usePartnerProfilesStore.getState().subagents).toHaveLength(1)); const [partner] = usePartnerProfilesStore.getState().subagents; expect(partner).toMatchObject({ displayName: '研究伙伴', prompt: '先分析资料,再给出可验证的结论。', templateRoleId: 'custom', }); expect(hostApiFetchMock.mock.calls.some(([path]) => String(path).includes('/api/opencode/agents'))).toBe(false); }); });