Merge remote main and reconcile agent refresh with ongoing chats
This commit is contained in:
commit
a21a1f077c
24 files changed
+1122
-165
No files matched your search
@@ -99,13 +99,30 @@ async function ready() {
|
||||
await waitFor(() => expect(streams.has('first')).toBe(true));
|
||||
}
|
||||
describe('teacher side chat', () => {
|
||||
it('renders the pinned topic icon in the header and assistant messages', async () => {
|
||||
it('opens directly into the consultation and puts new topics inside expanded history', async () => {
|
||||
render(<TeacherChatPanel projectId="p" sourceId="c" />);
|
||||
const history = await screen.findByRole('button', { name: '以往讨论' });
|
||||
const panel = screen.getByRole('complementary', { name: '智能体咨询' });
|
||||
expect(panel).toBeVisible();
|
||||
expect(panel.querySelector('header')).toBeNull();
|
||||
expect(screen.queryByText('服务端简介')).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: '智能体新话题' })).not.toBeInTheDocument();
|
||||
fireEvent.click(history);
|
||||
const newTopic = screen.getByRole('button', { name: '智能体新话题' });
|
||||
expect(newTopic).toBeEnabled();
|
||||
expect(newTopic).toHaveTextContent('新话题');
|
||||
fireEvent.click(newTopic);
|
||||
await waitFor(() => expect(api.create).toHaveBeenCalledWith('p/agent-topics', undefined, undefined, 1));
|
||||
expect(api.send).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('renders the pinned topic icon with assistant messages', async () => {
|
||||
const icon = 'https://yuxi.example.test/api/storage/public/images/topic.png';
|
||||
api.read.mockResolvedValue({ ...first, definition: { ...definition, icon_url: icon }, requests: [request({ response: '继续原来的讨论' })] });
|
||||
const view = render(<TeacherChatPanel projectId="p" sourceId="c" />);
|
||||
await ready();
|
||||
const images = view.container.querySelectorAll('[data-testid="teacher-chat-panel"] img');
|
||||
expect(images).toHaveLength(2);
|
||||
expect(images).toHaveLength(1);
|
||||
for (const img of images) expect(img).toHaveAttribute('src', icon);
|
||||
});
|
||||
|
||||
@@ -224,16 +241,15 @@ describe('teacher side chat', () => {
|
||||
expect(screen.getByLabelText('向智能体提问')).toHaveValue('解释代码');
|
||||
fireEvent.click(screen.getByRole('button', { name: '提问', exact: true }));
|
||||
await screen.findByText('教学回答');
|
||||
expect(screen.getByText('服务端简介')).toBeVisible();
|
||||
expect(screen.queryByText('服务端简介')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('较长的上下文已节选,智能体可按需读取原文。')).toBeVisible();
|
||||
expect(api.send.mock.calls[0][2].requestId).toBe(api.send.mock.calls[1][2].requestId);
|
||||
expect(bringBack).not.toHaveBeenCalled();
|
||||
fireEvent.click(screen.getByRole('button', { name: '带回主会话草稿' }));
|
||||
expect(bringBack).toHaveBeenCalledWith('教学回答');
|
||||
});
|
||||
it('ignores an old topic stream after switching and does not cancel when closed', async () => {
|
||||
const closed = vi.fn();
|
||||
const view = render(<TeacherChatPanel projectId="p" sourceId="c" onClose={closed} />);
|
||||
it('ignores an old topic stream after switching and does not cancel when the panel unmounts', async () => {
|
||||
const view = render(<TeacherChatPanel projectId="p" sourceId="c" />);
|
||||
await ready();
|
||||
const old = streams.get('first')!;
|
||||
fireEvent.change(screen.getByRole('combobox', { name: '智能体话题' }), {
|
||||
@@ -248,8 +264,6 @@ describe('teacher side chat', () => {
|
||||
)
|
||||
);
|
||||
expect(screen.getByRole('combobox', { name: '智能体话题' })).toHaveValue('second');
|
||||
fireEvent.click(screen.getByRole('button', { name: '关闭智能体' }));
|
||||
expect(closed).toHaveBeenCalledOnce();
|
||||
view.unmount();
|
||||
expect(api.cancel).not.toHaveBeenCalled();
|
||||
expect(old.close).toHaveBeenCalled();
|
||||
@@ -299,8 +313,9 @@ describe('teacher side chat', () => {
|
||||
api.list.mockResolvedValue({ items: [], lastSelectedTopicId: null });
|
||||
api.catalog.mockResolvedValue({ items: [{ teacher_id: 'published', version: 2, is_default: true, definition: published }] });
|
||||
render(<TeacherChatPanel projectId="p" sourceId="c" />);
|
||||
await screen.findByRole('heading', { name, exact: true });
|
||||
expect(screen.getByText('这是运营发布的简介')).toBeVisible();
|
||||
const panel = await screen.findByRole('complementary', { name: `${name}咨询`, exact: true });
|
||||
expect(screen.queryByText('这是运营发布的简介')).not.toBeInTheDocument();
|
||||
expect(panel.querySelector('header')).toBeNull();
|
||||
expect(screen.getByText('服务端欢迎语')).toBeVisible();
|
||||
expect(screen.getByRole('button', { name: '服务端推荐问题' })).toBeEnabled();
|
||||
expect(screen.getByTestId('teacher-chat-panel').querySelector('img')?.src).toContain('avatar-09.png');
|
||||
@@ -687,13 +702,15 @@ describe('merged cloud teacher classroom', () => {
|
||||
render(<TeacherChatPanel projectId="p" sourceId="c" selectedAgent={{ teacher_id: 'algorithm', version: 9, definition: cloudDefinition, is_default: false }} />);
|
||||
await waitFor(() => expect(screen.getByLabelText('向智能体提问')).toBeEnabled());
|
||||
expect(screen.queryByLabelText('新话题使用的智能体')).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: '以往讨论' })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: '智能体新话题' })).not.toBeInTheDocument();
|
||||
expect(api.create).not.toHaveBeenCalled();
|
||||
fireEvent.change(screen.getByLabelText('向智能体提问'), { target: { value: '我想做一个小游戏' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: '提问', exact: true }));
|
||||
await screen.findByText('先看看玩家会做什么。');
|
||||
expect(api.create).not.toHaveBeenCalled();
|
||||
expect(api.sendConversation).toHaveBeenCalledWith('algorithm', expect.objectContaining({ projectId: 'p', sourceConversationId: 'c', presentation: 'discussion-v1' }));
|
||||
expect(screen.getByRole('heading', { name: '算法智能体' })).toBeVisible();
|
||||
expect(screen.getByRole('complementary', { name: '算法智能体咨询' })).toBeVisible();
|
||||
});
|
||||
|
||||
it('does not enable a disabled cloud topic through another teacher or an Enter shortcut', async () => {
|
||||
|
||||
Reference in new issue
Block a user