feat(chat): simplify teacher pane and color follow-up cards
This commit is contained in:
@@ -1796,7 +1796,8 @@ test('project consultations preserve student drafts and switch between work and
|
||||
await page.getByRole('button',{name:'与朋友聊天',exact:true}).click();
|
||||
const teacher=page.getByTestId('teacher-chat-panel');
|
||||
await expect(page.getByTestId('teacher-introduction')).toHaveCount(0);
|
||||
await expect(teacher.locator('header').getByRole('button')).toHaveCount(0);
|
||||
await expect(teacher).toHaveAccessibleName('朋友咨询');
|
||||
await expect(teacher.locator('header')).toHaveCount(0);
|
||||
await expect(teacher.getByText('陪你听听玩家的想法,让作品更有趣。')).toHaveCount(0);
|
||||
await expect(page.getByRole('tab',{name:'作品',exact:true})).toHaveAttribute('aria-selected','true');
|
||||
await expect(page.getByRole('tabpanel',{name:'作品',exact:true})).toBeVisible();
|
||||
@@ -1833,7 +1834,7 @@ test('project consultations preserve student drafts and switch between work and
|
||||
await expect(teacher).toHaveCount(0);
|
||||
await expect(page.getByRole('button',{name:'与朋友聊天',exact:true})).toBeFocused();
|
||||
await page.getByRole('button', { name: '与代码智能体聊天' }).click();
|
||||
await expect(teacher.getByRole('heading', { name: '代码智能体' })).toBeVisible();
|
||||
await expect(teacher).toHaveAccessibleName('代码智能体咨询');
|
||||
await expect(teacher.getByRole('textbox', { name: '向智能体提问' })).toHaveValue('');
|
||||
await teacher.getByRole('textbox', { name: '向智能体提问' }).fill('另一个智能体的草稿');
|
||||
await page.getByRole('button',{name:'与朋友聊天',exact:true}).click();
|
||||
@@ -1849,7 +1850,7 @@ test('project consultations preserve student drafts and switch between work and
|
||||
const consultationRequests=requests.filter(item=>item.path.endsWith('/messages')&&item.method==='POST');
|
||||
expect(consultationRequests).toHaveLength(3);
|
||||
expect(requests.find(item => item.path.endsWith('/agent-topics') && item.method === 'POST')?.body?.teacherVersion).toBe(9);
|
||||
await expect(teacher.getByRole('heading', { name: '朋友', exact: true })).toBeVisible();
|
||||
await expect(teacher).toHaveAccessibleName('朋友咨询');
|
||||
expect(consultationRequests[0].body).toMatchObject({intent:'suggestions',text:'帮我看看'});
|
||||
expect(consultationRequests[1].body).toMatchObject({text:'怎样观察别人玩游戏?'});
|
||||
expect(consultationRequests[1].body?.intent).toBeUndefined();
|
||||
|
||||
@@ -297,7 +297,8 @@ describe('CodingChatPanel first Conversation', () => {
|
||||
expect(operationInput).toHaveValue('我想先自己试一试');
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '智能体', exact: true }));
|
||||
const teacherInput = await screen.findByRole('textbox', { name: '向智能体提问' });
|
||||
const teacherPanel = await screen.findByRole('complementary', { name: '智能体咨询' });
|
||||
const teacherInput = within(teacherPanel).getByRole('textbox', { name: '向智能体提问' });
|
||||
expect(workTab).toHaveAttribute('aria-selected', 'true');
|
||||
expect(operationInput).not.toBeVisible();
|
||||
expect(operationInput).toHaveValue('我想先自己试一试');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { TeacherChatPanel } from '@/pages/Chat/TeacherChatPanel';
|
||||
import type { TeacherDefinition, TeacherRequest, TeacherSend, TeacherTopic } from '../../shared/coding-teacher';
|
||||
@@ -96,31 +96,30 @@ async function ready() {
|
||||
await waitFor(() => expect(streams.has('first')).toBe(true));
|
||||
}
|
||||
describe('teacher side chat', () => {
|
||||
it('keeps the panel header focused on identity and puts new topics inside expanded history', 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 header = screen.getByTestId('teacher-chat-panel').querySelector('header')!;
|
||||
expect(within(header).getByRole('heading', { name: '智能体' })).toBeVisible();
|
||||
expect(within(header).queryByRole('button')).not.toBeInTheDocument();
|
||||
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('新话题');
|
||||
expect(header.contains(newTopic)).toBe(false);
|
||||
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 in the header and assistant messages', async () => {
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -311,9 +310,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 });
|
||||
const panel = await screen.findByRole('complementary', { name: `${name}咨询`, exact: true });
|
||||
expect(screen.queryByText('这是运营发布的简介')).not.toBeInTheDocument();
|
||||
expect(within(screen.getByTestId('teacher-chat-panel').querySelector('header')!).queryByRole('button')).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');
|
||||
@@ -705,7 +704,7 @@ describe('merged cloud teacher classroom', () => {
|
||||
await screen.findByText('先看看玩家会做什么。');
|
||||
expect(api.create).toHaveBeenCalledWith('p/agent-topics', undefined, undefined, 9);
|
||||
expect(api.send.mock.calls[0][2]).toMatchObject({ 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 () => {
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('teacher presence and periodic guidance', () => {
|
||||
expect(api.checkIn).not.toHaveBeenCalled();
|
||||
await act(async () => fireEvent.click(experience));
|
||||
expect(screen.queryByTestId('teacher-introduction')).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('heading', { name: '体验朋友' })).toBeVisible();
|
||||
expect(screen.getByRole('complementary', { name: '体验朋友咨询' })).toBeVisible();
|
||||
// The first move may arrive only after the click when crossing a tooltip's
|
||||
// grace area. It must not reopen the introduction beneath the pointer.
|
||||
fireEvent.pointerMove(experience, { pointerType: 'mouse' });
|
||||
@@ -145,7 +145,7 @@ describe('teacher presence and periodic guidance', () => {
|
||||
expect(second).toHaveAttribute('src', b.definition.icon_url);
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '与另一个智能体聊天' })));
|
||||
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', b.definition.icon_url);
|
||||
});
|
||||
|
||||
@@ -160,7 +160,7 @@ describe('teacher presence and periodic guidance', () => {
|
||||
expect(screen.getByRole('button', { name: '与体验朋友聊天' })).toBeVisible();
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '与体验朋友聊天' })));
|
||||
expect(screen.queryByLabelText('新话题使用的智能体')).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('heading', { name: '体验朋友' })).toBeVisible();
|
||||
expect(screen.getByRole('complementary', { name: '体验朋友咨询' })).toBeVisible();
|
||||
fireEvent.change(screen.getByLabelText('向智能体提问'), { target: { value: '体验的草稿' } });
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '与方法老师聊天' })));
|
||||
expect(screen.getByLabelText('向智能体提问')).toHaveValue('');
|
||||
@@ -192,13 +192,13 @@ describe('teacher presence and periodic guidance', () => {
|
||||
await mount();
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '与方法老师聊天' })));
|
||||
expect(api.read).toHaveBeenCalledWith('project', oldA.id);
|
||||
expect(screen.getByRole('heading', { name: '方法老师' })).toBeVisible();
|
||||
expect(screen.getByRole('complementary', { name: '方法老师咨询' })).toBeVisible();
|
||||
fireEvent.change(screen.getByLabelText('向智能体提问'), { target: { value: '继续原来的讨论' } });
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '提问', exact: true })));
|
||||
expect(api.send.mock.calls[0][1]).toBe(oldA.id);
|
||||
expect(api.create).not.toHaveBeenCalled();
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '与体验朋友聊天' })));
|
||||
expect(screen.getByRole('heading', { name: '体验朋友' })).toBeVisible();
|
||||
expect(screen.getByRole('complementary', { name: '体验朋友咨询' })).toBeVisible();
|
||||
expect(api.read).toHaveBeenCalledWith('project', oldB.id);
|
||||
});
|
||||
|
||||
@@ -213,7 +213,7 @@ describe('teacher presence and periodic guidance', () => {
|
||||
await mount();
|
||||
await act(async () => fireEvent.click(screen.getByRole('button', { name: '与体验朋友聊天' })));
|
||||
await act(async () => resolve(old));
|
||||
expect(screen.getByRole('heading', { name: '体验朋友' })).toBeVisible();
|
||||
expect(screen.getByRole('complementary', { name: '体验朋友咨询' })).toBeVisible();
|
||||
expect(screen.getByRole('button', { name: '与体验朋友聊天' })).toHaveAttribute('aria-pressed', 'true');
|
||||
expect(api.read).toHaveBeenCalledWith('project', old.id, false);
|
||||
expect(api.send).not.toHaveBeenCalled();
|
||||
|
||||
Reference in New Issue
Block a user