Refine personal Agent cards and configuration

This commit is contained in:
鲨鱼辣椒 committed 2026-10-12 17:45:02 +08:00
1 parent c14d996c05
commit 8b40463a9f
17 files changed
+555 -412

No files matched your search

+74
View File
@@ -27,6 +27,80 @@ it('shows a default avatar for absent or broken images and recovers when the ima
expect(screen.getByRole('img', { name: '写作搭档头像' })).toHaveAttribute('src', 'https://images.test/new.png');
});
it('keeps a new assistant portrait while its name is typed or cleared', () => {
const view = render(<CloudAvatar name="" />);
const portrait = screen.getByRole('img').getAttribute('src');
for (const name of ['学', '学习', '学习 Friend', '学习 Friend 🚀', '']) {
view.rerender(<CloudAvatar name={name} />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
expect(screen.getByRole('img')).toHaveAttribute('alt', `${name}默认头像`);
}
});
it('keeps an assistant portrait across renaming, reopening and a failed custom image', () => {
const view = render(<CloudAvatar identity="english-practice" name="英语陪练" />);
const portrait = screen.getByRole('img').getAttribute('src');
for (const name of ['英', '英语', '英语 Friend', '英语 Friend 🌟']) {
view.rerender(<CloudAvatar identity="english-practice" name={name} />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
}
view.unmount();
const reopened = render(<CloudAvatar identity="english-practice" name="英语 Friend 🌟" src="https://images.test/saved.png" />);
expect(screen.getByRole('img')).toHaveAttribute('src', 'https://images.test/saved.png');
fireEvent.error(screen.getByRole('img'));
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
reopened.rerender(<CloudAvatar identity="english-practice" name="新名字" src="https://images.test/replaced.png" />);
expect(screen.getByRole('img')).toHaveAttribute('src', 'https://images.test/replaced.png');
});
it('uses one default portrait across creation, persisted identities and reopening', () => {
const creation = render(<CloudAvatar name="" />);
const portrait = screen.getByRole('img').getAttribute('src');
creation.rerender(<CloudAvatar name="我的英语陪练" />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
creation.unmount();
const view = render(<CloudAvatar identity="assistant-a" name="同名助手" />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
view.rerender(<CloudAvatar identity="assistant-b" name="同名助手" />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
view.rerender(<CloudAvatar identity="assistant-a" name="改名后的助手" />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
view.unmount();
render(<CloudAvatar identity="assistant-a" name="改名后的助手" />);
expect(screen.getByRole('img')).toHaveAttribute('src', portrait);
});
it('keeps the default selection and chosen portrait stable while the name is edited', async () => {
api.useAvatarPreset.mockResolvedValue({ icon: '/chosen.png', icon_url: 'https://images.test/chosen.png' });
function RenameEditor() {
const [name, setName] = useState('英语陪练');
const [value, setValue] = useState<CloudAgentAvatar>({});
const [uploading, setUploading] = useState(false);
return <><input aria-label="助手名称" value={name} onChange={event => setName(event.target.value)} />
<CloudAvatarEditor identity="english-practice" name={name} value={value} disabled={false} uploading={uploading} onUploading={setUploading} onChange={setValue} /></>;
}
render(<RenameEditor />);
const portraits = () => screen.getAllByRole('button', { name: /^像素伙伴 / });
const initialSelection = portraits().find(button => button.getAttribute('aria-pressed') === 'true')!;
const portrait = screen.getByRole('img', { name: '英语陪练默认头像' }).getAttribute('src');
expect(initialSelection.querySelector('img')).toHaveAttribute('src', portrait);
for (const name of ['英', '英语', '英语 Friend']) {
fireEvent.change(screen.getByRole('textbox', { name: '助手名称' }), { target: { value: name } });
expect(screen.getByRole('img', { name: `${name}默认头像` })).toHaveAttribute('src', portrait);
expect(initialSelection).toHaveAttribute('aria-pressed', 'true');
expect(portraits().filter(button => button.getAttribute('aria-pressed') === 'true')).toHaveLength(1);
}
fireEvent.click(screen.getByRole('button', { name: '像素伙伴 7' }));
await waitFor(() => expect(screen.getByRole('img', { name: '英语 Friend头像' })).toHaveAttribute('src', 'https://images.test/chosen.png'));
fireEvent.change(screen.getByRole('textbox', { name: '助手名称' }), { target: { value: '新的伙伴' } });
expect(screen.getByRole('img', { name: '新的伙伴头像' })).toHaveAttribute('src', 'https://images.test/chosen.png');
expect(screen.getByRole('button', { name: '像素伙伴 7' })).toHaveAttribute('aria-pressed', 'true');
fireEvent.click(screen.getByRole('button', { name: '移除头像' }));
expect(screen.getByRole('img', { name: '新的伙伴默认头像' })).toHaveAttribute('src', portrait);
expect(initialSelection).toHaveAttribute('aria-pressed', 'true');
expect(api.useAvatarPreset).toHaveBeenCalledExactlyOnceWith('avatar-07');
});
it('offers sixteen platform portraits and uses the chosen portrait without a file picker', async () => {
api.useAvatarPreset.mockResolvedValue({ icon: '/chosen.png', icon_url: 'https://images.test/chosen.png' });
render(<Editor />);