收口前端平台组件库能力
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
This commit is contained in:
225
src/components/common/PlatformUploadPreviewCard.test.tsx
Normal file
225
src/components/common/PlatformUploadPreviewCard.test.tsx
Normal file
@@ -0,0 +1,225 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { PlatformUploadPreviewCard } from './PlatformUploadPreviewCard';
|
||||
|
||||
vi.mock('../ResolvedAssetImage', () => ({
|
||||
ResolvedAssetImage: ({
|
||||
src,
|
||||
alt,
|
||||
className,
|
||||
}: {
|
||||
src?: string | null;
|
||||
alt?: string;
|
||||
className?: string;
|
||||
}) => <img src={src ?? ''} alt={alt} className={className} />,
|
||||
}));
|
||||
|
||||
test('renders uploaded image preview with shared chrome', () => {
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="data:image/png;base64,abc"
|
||||
imageAlt="反馈凭证预览"
|
||||
removeLabel="移除上传凭证"
|
||||
onRemove={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
const image = screen.getByRole('img', { name: '反馈凭证预览' });
|
||||
const removeButton = screen.getByRole('button', { name: '移除上传凭证' });
|
||||
|
||||
expect(image.getAttribute('src')).toBe('data:image/png;base64,abc');
|
||||
expect(image.className).toContain('object-cover');
|
||||
expect(removeButton.getAttribute('type')).toBe('button');
|
||||
expect(removeButton.className).toContain('bg-black/55');
|
||||
});
|
||||
|
||||
test('calls remove handler from preview action', () => {
|
||||
const onRemove = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="/preview.png"
|
||||
imageAlt="上传图片预览"
|
||||
removeLabel="移除图片"
|
||||
onRemove={onRemove}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '移除图片' }));
|
||||
|
||||
expect(onRemove).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('supports preview action with resolved asset image', () => {
|
||||
const onPreview = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="/generated/reference.png"
|
||||
imageAlt="参考图"
|
||||
previewLabel="预览参考图 1"
|
||||
removeLabel="移除参考图"
|
||||
onPreview={onPreview}
|
||||
resolveAsset
|
||||
/>,
|
||||
);
|
||||
|
||||
const previewButton = screen.getByRole('button', { name: '预览参考图 1' });
|
||||
fireEvent.click(previewButton);
|
||||
|
||||
expect(screen.getByRole('img', { name: '参考图' }).getAttribute('src')).toBe(
|
||||
'/generated/reference.png',
|
||||
);
|
||||
expect(onPreview).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('can render preview-only cards without remove action', () => {
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="/preview.png"
|
||||
imageAlt="上传图片预览"
|
||||
removeLabel="移除图片"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole('img', { name: '上传图片预览' })).toBeTruthy();
|
||||
expect(screen.queryByRole('button', { name: '移除图片' })).toBeNull();
|
||||
});
|
||||
|
||||
test('supports captioned preview cards for reference images', () => {
|
||||
const onPreview = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="/reference.png"
|
||||
imageAlt=""
|
||||
caption="草莓"
|
||||
previewLabel="预览参考图 草莓"
|
||||
removeLabel="移除参考图 草莓"
|
||||
onPreview={onPreview}
|
||||
onRemove={vi.fn()}
|
||||
className="w-full rounded-[1rem]"
|
||||
imageShellClassName="ring-1"
|
||||
captionClassName="pr-9"
|
||||
/>,
|
||||
);
|
||||
|
||||
const previewButton = screen.getByRole('button', {
|
||||
name: '预览参考图 草莓',
|
||||
});
|
||||
|
||||
fireEvent.click(previewButton);
|
||||
|
||||
const previewImage = previewButton.querySelector('img');
|
||||
|
||||
expect(screen.getByText('草莓').className).toContain('pr-9');
|
||||
expect(previewImage?.parentElement?.className).toContain('ring-1');
|
||||
expect(onPreview).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('supports inline selected upload preview rows', () => {
|
||||
const onRemove = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
layout="inline"
|
||||
imageSrc="/reference.png"
|
||||
imageAlt="创作参考图"
|
||||
caption="森林参考图.png"
|
||||
removeLabel="移除参考图"
|
||||
onRemove={onRemove}
|
||||
className="mt-3"
|
||||
removeButtonProps={{ title: '移除参考图' }}
|
||||
/>,
|
||||
);
|
||||
|
||||
const image = screen.getByRole('img', { name: '创作参考图' });
|
||||
const row = image.closest('div')?.parentElement;
|
||||
const removeButton = screen.getByRole('button', { name: '移除参考图' });
|
||||
|
||||
expect(row?.className).toContain('flex items-center gap-3');
|
||||
expect(row?.className).toContain('bg-white/68');
|
||||
expect(row?.className).toContain('px-3');
|
||||
expect(row?.className).toContain('py-2');
|
||||
expect(row?.className).toContain('mt-3');
|
||||
expect(screen.getByText('森林参考图.png').className).toContain('truncate');
|
||||
expect(removeButton.className).toContain('platform-icon-button');
|
||||
expect(removeButton.getAttribute('title')).toBe('移除参考图');
|
||||
|
||||
fireEvent.click(removeButton);
|
||||
|
||||
expect(onRemove).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('supports editor dark inline selected upload preview rows', () => {
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
layout="inline"
|
||||
surface="editorDark"
|
||||
imageSrc="/reference.png"
|
||||
imageAlt="封面参考图"
|
||||
caption="已载入封面参考图"
|
||||
removeLabel="移除封面参考图"
|
||||
onRemove={vi.fn()}
|
||||
imageShellClassName="!h-16 !w-24 rounded-xl"
|
||||
/>,
|
||||
);
|
||||
|
||||
const image = screen.getByRole('img', { name: '封面参考图' });
|
||||
const imageShell = image.parentElement;
|
||||
const row = imageShell?.parentElement;
|
||||
const caption = screen.getByText('已载入封面参考图');
|
||||
const removeButton = screen.getByRole('button', { name: '移除封面参考图' });
|
||||
|
||||
expect(row?.className).toContain('border-white/10');
|
||||
expect(row?.className).toContain('bg-black/25');
|
||||
expect(imageShell?.className).toContain('bg-black/30');
|
||||
expect(imageShell?.className).toContain('!w-24');
|
||||
expect(caption.className).toContain('text-zinc-300');
|
||||
expect(removeButton.className).toContain('bg-black/55');
|
||||
});
|
||||
|
||||
test('keeps disabled remove action inert', () => {
|
||||
const onRemove = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="/preview.png"
|
||||
imageAlt="上传图片预览"
|
||||
removeLabel="移除图片"
|
||||
onRemove={onRemove}
|
||||
disabled
|
||||
/>,
|
||||
);
|
||||
|
||||
const removeButton = screen.getByRole('button', { name: '移除图片' });
|
||||
fireEvent.click(removeButton);
|
||||
|
||||
expect(removeButton).toHaveProperty('disabled', true);
|
||||
expect(removeButton.className).toContain('disabled:cursor-not-allowed');
|
||||
expect(onRemove).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('supports local size, image and remove button classes', () => {
|
||||
render(
|
||||
<PlatformUploadPreviewCard
|
||||
imageSrc="/preview.png"
|
||||
imageAlt="上传图片预览"
|
||||
removeLabel="移除图片"
|
||||
onRemove={vi.fn()}
|
||||
className="h-20 w-20"
|
||||
imageClassName="object-top"
|
||||
removeButtonProps={{ className: 'right-2 top-2' }}
|
||||
/>,
|
||||
);
|
||||
|
||||
const image = screen.getByRole('img', { name: '上传图片预览' });
|
||||
const removeButton = screen.getByRole('button', { name: '移除图片' });
|
||||
|
||||
expect(image.parentElement?.className).toContain('h-20');
|
||||
expect(image.className).toContain('object-top');
|
||||
expect(removeButton.className).toContain('right-2');
|
||||
});
|
||||
Reference in New Issue
Block a user