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);
});
});