feat(agents): 复用 Yuxi 头像上传与展示
This commit is contained in:
1 parent
0ca744fb9b
commit
235af24d6c
16 files changed
+381
-32
No files matched your search
@@ -0,0 +1,56 @@
|
||||
import { useState } from 'react';
|
||||
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
|
||||
import { CloudAvatar, CloudAvatarEditor } from '@/pages/CloudAgents/CloudAvatar';
|
||||
import type { CloudAgentAvatar } from '../../shared/cloud-agents';
|
||||
|
||||
const api = vi.hoisted(() => ({ uploadAvatar: vi.fn() }));
|
||||
vi.mock('@/lib/cloud-agents-api', () => ({ cloudAgentsApi: api }));
|
||||
beforeEach(() => vi.resetAllMocks());
|
||||
afterEach(cleanup);
|
||||
|
||||
function Editor() {
|
||||
const [value, setValue] = useState<CloudAgentAvatar>({ icon: '/old.png', icon_url: 'https://images.test/old.png' });
|
||||
const [uploading, setUploading] = useState(false);
|
||||
return <CloudAvatarEditor name="写作搭档" value={value} disabled={false} uploading={uploading} onUploading={setUploading} onChange={setValue} />;
|
||||
}
|
||||
|
||||
it('shows a default avatar for absent or broken images and recovers when the image changes', () => {
|
||||
const view = render(<CloudAvatar name="写作搭档" />);
|
||||
expect(screen.getByRole('img', { name: '写作搭档默认头像' })).toBeVisible();
|
||||
view.rerender(<CloudAvatar name="写作搭档" src="https://images.test/broken.png" />);
|
||||
fireEvent.error(screen.getByRole('img', { name: '写作搭档头像' }));
|
||||
expect(screen.getByRole('img', { name: '写作搭档默认头像' })).toBeVisible();
|
||||
view.rerender(<CloudAvatar name="写作搭档" src="https://images.test/new.png" />);
|
||||
expect(screen.getByRole('img', { name: '写作搭档头像' })).toHaveAttribute('src', 'https://images.test/new.png');
|
||||
});
|
||||
|
||||
it('retains the avatar after cancellation or failure, then supports replacing and removing it', async () => {
|
||||
api.uploadAvatar.mockResolvedValueOnce(null).mockRejectedValueOnce(new Error('上传失败'))
|
||||
.mockResolvedValueOnce({ icon: '/new.png', icon_url: 'https://images.test/new.png' });
|
||||
render(<Editor />);
|
||||
fireEvent.click(screen.getByRole('button', { name: '更换头像' }));
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: '更换头像' })).toBeEnabled());
|
||||
expect(screen.getByRole('img', { name: '写作搭档头像' })).toHaveAttribute('src', 'https://images.test/old.png');
|
||||
fireEvent.click(screen.getByRole('button', { name: '更换头像' }));
|
||||
expect(await screen.findByRole('alert')).toHaveTextContent('上传失败');
|
||||
expect(screen.getByRole('img', { name: '写作搭档头像' })).toHaveAttribute('src', 'https://images.test/old.png');
|
||||
fireEvent.click(screen.getByRole('button', { name: '更换头像' }));
|
||||
await waitFor(() => expect(screen.getByRole('img', { name: '写作搭档头像' })).toHaveAttribute('src', 'https://images.test/new.png'));
|
||||
fireEvent.click(screen.getByRole('button', { name: '移除头像' }));
|
||||
expect(screen.getByRole('img', { name: '写作搭档默认头像' })).toBeVisible();
|
||||
});
|
||||
|
||||
it('disables edits during upload and drops results after leaving the account or editor', async () => {
|
||||
let resolve!: (value: CloudAgentAvatar) => void;
|
||||
api.uploadAvatar.mockReturnValue(new Promise(r => { resolve = r; }));
|
||||
const changed = vi.fn(), busy = vi.fn();
|
||||
const view = render(<CloudAvatarEditor name="写作搭档" value={{}} disabled={false} uploading={false} onChange={changed} onUploading={busy} />);
|
||||
fireEvent.click(screen.getByRole('button', { name: '上传头像' }));
|
||||
expect(busy).toHaveBeenCalledWith(true);
|
||||
view.rerender(<CloudAvatarEditor name="写作搭档" value={{}} disabled={false} uploading onChange={changed} onUploading={busy} />);
|
||||
expect(screen.getByRole('button', { name: '正在上传…' })).toBeDisabled();
|
||||
view.unmount();
|
||||
await act(async () => resolve({ icon: '/other-account.png', icon_url: 'https://images.test/other.png' }));
|
||||
expect(changed).not.toHaveBeenCalled();
|
||||
});
|
||||
Reference in new issue
Block a user