Files
Genarrative/src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx
T
JenkenB 0e47a54a91 对齐编辑器生成占位与面板参数
统一画布生成占位图标,按图片、规范、角色、图标、UI、视频、音频、宣发和快速编辑区分。

让图片、规范、宣发和视频新建占位按面板尺寸或固定输出尺寸创建,并在参数变化时同步占位大小。

完善快速编辑、音频生成、宣发素材和生成类面板相关契约与测试。

更新生成类面板 Lovart 改造文档和项目决策记录。
2026-06-19 12:15:57 +08:00

187 lines
6.5 KiB
TypeScript

/* @vitest-environment jsdom */
import { fireEvent, render, screen, within } from '@testing-library/react';
import { createRef } from 'react';
import { describe, expect, it, vi } from 'vitest';
import { ImageCanvasBottomToolbarView } from './ImageCanvasBottomToolbarView';
describe('ImageCanvasBottomToolbarView', () => {
it('renders the canvas tools and forwards tool changes', () => {
const switchTool = vi.fn();
const specToolWrapRef = createRef<HTMLSpanElement>();
const musicToolWrapRef = createRef<HTMLSpanElement>();
const publicationToolWrapRef = createRef<HTMLSpanElement>();
render(
<ImageCanvasBottomToolbarView
specToolWrapRef={specToolWrapRef}
musicToolWrapRef={musicToolWrapRef}
publicationToolWrapRef={publicationToolWrapRef}
effectiveTool="generate"
onSwitchTool={switchTool}
onOpenToolOptions={vi.fn()}
onCloseToolOptions={vi.fn()}
/>,
);
const toolbar = screen.getByRole('toolbar', { name: 'AI画布工具栏' });
expect(
within(toolbar)
.getByRole('button', { name: '生成图片' })
.getAttribute('aria-pressed'),
).toBe('false');
expect(
within(toolbar)
.getByRole('button', { name: '选择工具' })
.getAttribute('aria-pressed'),
).toBe('false');
fireEvent.click(within(toolbar).getByRole('button', { name: '抓手工具' }));
fireEvent.click(within(toolbar).getByRole('button', { name: '生成视频' }));
fireEvent.click(within(toolbar).getByRole('button', { name: '生成规范' }));
fireEvent.click(
within(toolbar).getByRole('button', { name: '生成UI设计图' }),
);
fireEvent.click(within(toolbar).getByRole('button', { name: '生成音乐' }));
fireEvent.click(
within(toolbar).getByRole('button', { name: '生成图标素材' }),
);
fireEvent.click(within(toolbar).getByRole('button', { name: '宣发素材' }));
expect(switchTool).toHaveBeenNthCalledWith(1, 'hand');
expect(switchTool).toHaveBeenNthCalledWith(2, 'video');
expect(switchTool).toHaveBeenNthCalledWith(3, 'spec');
expect(switchTool).toHaveBeenNthCalledWith(4, 'ui-design');
expect(switchTool).toHaveBeenNthCalledWith(5, 'music');
expect(switchTool).toHaveBeenNthCalledWith(6, 'icon');
expect(switchTool).toHaveBeenNthCalledWith(7, 'publication');
});
it('only keeps the select and hand tools visibly pressed', () => {
const specToolWrapRef = createRef<HTMLSpanElement>();
const musicToolWrapRef = createRef<HTMLSpanElement>();
const publicationToolWrapRef = createRef<HTMLSpanElement>();
const renderToolbar = (effectiveTool: Parameters<
typeof ImageCanvasBottomToolbarView
>[0]['effectiveTool']) => (
<ImageCanvasBottomToolbarView
specToolWrapRef={specToolWrapRef}
musicToolWrapRef={musicToolWrapRef}
publicationToolWrapRef={publicationToolWrapRef}
effectiveTool={effectiveTool}
onSwitchTool={vi.fn()}
onOpenToolOptions={vi.fn()}
onCloseToolOptions={vi.fn()}
/>
);
const { rerender } = render(renderToolbar('select'));
const toolbar = screen.getByRole('toolbar', { name: 'AI画布工具栏' });
expect(
within(toolbar)
.getByRole('button', { name: '选择工具' })
.getAttribute('aria-pressed'),
).toBe('true');
rerender(renderToolbar('hand'));
expect(
within(toolbar)
.getByRole('button', { name: '抓手工具' })
.getAttribute('aria-pressed'),
).toBe('true');
for (const tool of [
['upload', '上传工具'],
['generate', '生成图片'],
['video', '生成视频'],
['music', '生成音乐'],
['spec', '生成规范'],
['character', '生成角色形象'],
['icon', '生成图标素材'],
['ui-design', '生成UI设计图'],
['publication', '宣发素材'],
] as const) {
rerender(renderToolbar(tool[0]));
expect(
within(toolbar)
.getByRole('button', { name: tool[1] })
.getAttribute('aria-pressed'),
).toBe('false');
}
});
it('把宣发素材入口放在生成UI设计图右侧', () => {
const specToolWrapRef = createRef<HTMLSpanElement>();
const musicToolWrapRef = createRef<HTMLSpanElement>();
const publicationToolWrapRef = createRef<HTMLSpanElement>();
render(
<ImageCanvasBottomToolbarView
specToolWrapRef={specToolWrapRef}
musicToolWrapRef={musicToolWrapRef}
publicationToolWrapRef={publicationToolWrapRef}
effectiveTool="select"
onSwitchTool={vi.fn()}
onOpenToolOptions={vi.fn()}
onCloseToolOptions={vi.fn()}
/>,
);
const toolNames = within(
screen.getByRole('toolbar', { name: 'AI画布工具栏' }),
)
.getAllByRole('button')
.map((button) => button.getAttribute('aria-label'));
expect(toolNames).toEqual([
'选择工具',
'抓手工具',
'上传工具',
'生成图片',
'生成视频',
'生成音乐',
'生成规范',
'生成角色形象',
'生成图标素材',
'生成UI设计图',
'宣发素材',
]);
});
it('opens and closes bottom option tools on hover', () => {
const openToolOptions = vi.fn();
const closeToolOptions = vi.fn();
const specToolWrapRef = createRef<HTMLSpanElement>();
const musicToolWrapRef = createRef<HTMLSpanElement>();
const publicationToolWrapRef = createRef<HTMLSpanElement>();
render(
<ImageCanvasBottomToolbarView
specToolWrapRef={specToolWrapRef}
musicToolWrapRef={musicToolWrapRef}
publicationToolWrapRef={publicationToolWrapRef}
effectiveTool="select"
onSwitchTool={vi.fn()}
onOpenToolOptions={openToolOptions}
onCloseToolOptions={closeToolOptions}
/>,
);
fireEvent.pointerEnter(specToolWrapRef.current!);
fireEvent.pointerLeave(specToolWrapRef.current!);
fireEvent.pointerEnter(musicToolWrapRef.current!);
fireEvent.pointerLeave(musicToolWrapRef.current!);
fireEvent.pointerEnter(publicationToolWrapRef.current!);
fireEvent.pointerLeave(publicationToolWrapRef.current!);
expect(openToolOptions).toHaveBeenNthCalledWith(1, 'spec');
expect(closeToolOptions).toHaveBeenNthCalledWith(1, 'spec');
expect(openToolOptions).toHaveBeenNthCalledWith(2, 'music');
expect(closeToolOptions).toHaveBeenNthCalledWith(2, 'music');
expect(openToolOptions).toHaveBeenNthCalledWith(3, 'publication');
expect(closeToolOptions).toHaveBeenNthCalledWith(3, 'publication');
});
});