03a4410272
主要工作是共享同一套“画布内核与通用 UI 源码”,网站和 Tauri 只分别实现宿主适配层。 --------- Co-authored-by: 段舒康 <kdletters@qq.com> Co-authored-by: kdletters <kdletters@qq.com> Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/136 Co-authored-by: menghao <mh18530625731@163.com> Co-committed-by: menghao <mh18530625731@163.com>
169 lines
5.4 KiB
TypeScript
169 lines
5.4 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { render, screen, within } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { createRef, type RefObject } from 'react';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
import { ImageCanvasBottomToolbarView } from './ImageCanvasBottomToolbarView';
|
|
|
|
describe('ImageCanvasBottomToolbarView', () => {
|
|
function renderToolbar(
|
|
overrides: Partial<Parameters<typeof ImageCanvasBottomToolbarView>[0]> = {},
|
|
) {
|
|
const switchTool = vi.fn();
|
|
const specToolWrapRef = createRef<HTMLSpanElement>();
|
|
const musicToolWrapRef = createRef<HTMLSpanElement>();
|
|
const publicationToolWrapRef = createRef<HTMLSpanElement>();
|
|
const view = render(
|
|
<ImageCanvasBottomToolbarView
|
|
specToolWrapRef={specToolWrapRef}
|
|
musicToolWrapRef={musicToolWrapRef}
|
|
publicationToolWrapRef={publicationToolWrapRef}
|
|
effectiveTool="generate"
|
|
onSwitchTool={switchTool}
|
|
onOpenToolOptions={vi.fn()}
|
|
onCloseToolOptions={vi.fn()}
|
|
{...overrides}
|
|
/>,
|
|
);
|
|
|
|
return {
|
|
...view,
|
|
toolbar: screen.getByRole('toolbar', { name: 'AI画布工具栏' }),
|
|
switchTool,
|
|
refs: {
|
|
specToolWrapRef,
|
|
musicToolWrapRef,
|
|
publicationToolWrapRef,
|
|
},
|
|
};
|
|
}
|
|
|
|
function renderToolbarView(
|
|
effectiveTool: Parameters<
|
|
typeof ImageCanvasBottomToolbarView
|
|
>[0]['effectiveTool'],
|
|
refs: {
|
|
specToolWrapRef: RefObject<HTMLSpanElement | null>;
|
|
musicToolWrapRef: RefObject<HTMLSpanElement | null>;
|
|
publicationToolWrapRef: RefObject<HTMLSpanElement | null>;
|
|
},
|
|
) {
|
|
return (
|
|
<ImageCanvasBottomToolbarView
|
|
specToolWrapRef={refs.specToolWrapRef}
|
|
musicToolWrapRef={refs.musicToolWrapRef}
|
|
publicationToolWrapRef={refs.publicationToolWrapRef}
|
|
effectiveTool={effectiveTool}
|
|
onSwitchTool={vi.fn()}
|
|
onOpenToolOptions={vi.fn()}
|
|
onCloseToolOptions={vi.fn()}
|
|
/>
|
|
);
|
|
}
|
|
|
|
it('renders the expected canvas tools and forwards user selections', async () => {
|
|
const user = userEvent.setup();
|
|
const { toolbar, switchTool } = renderToolbar();
|
|
|
|
expect(toolbar.className).toContain('genarrative-image-canvas__toolbar');
|
|
expect(toolbar.className).toContain(
|
|
'genarrative-image-canvas__toolbar--floating',
|
|
);
|
|
expect(
|
|
toolbar.querySelectorAll('.genarrative-image-canvas__toolbar-group'),
|
|
).toHaveLength(12);
|
|
expect(
|
|
toolbar.querySelectorAll('.genarrative-image-canvas__toolbar-divider'),
|
|
).toHaveLength(2);
|
|
|
|
const toolExpectations = [
|
|
['选择工具', 'select'],
|
|
['抓手工具', 'hand'],
|
|
['上传工具', 'upload'],
|
|
['生成图片', 'generate'],
|
|
['生成视频', 'video'],
|
|
['生成音乐', 'music'],
|
|
['生成规范', 'spec'],
|
|
['生成角色形象', 'character'],
|
|
['生成图标素材', 'icon'],
|
|
['生成UI设计图', 'ui-design'],
|
|
['宣发素材', 'publication'],
|
|
['生成游戏场景', 'scene'],
|
|
] as const;
|
|
|
|
for (const [label, tool] of toolExpectations) {
|
|
await user.click(within(toolbar).getByRole('button', { name: label }));
|
|
expect(switchTool).toHaveBeenLastCalledWith(tool);
|
|
}
|
|
|
|
expect(switchTool).toHaveBeenCalledTimes(toolExpectations.length);
|
|
});
|
|
|
|
it('only exposes persistent pressed state for navigation tools', () => {
|
|
const { toolbar, rerender, refs } = renderToolbar({
|
|
effectiveTool: 'select',
|
|
});
|
|
|
|
expect(
|
|
within(toolbar)
|
|
.getByRole('button', { name: '选择工具' })
|
|
.getAttribute('aria-pressed'),
|
|
).toBe('true');
|
|
expect(
|
|
within(toolbar)
|
|
.getByRole('button', { name: '生成图片' })
|
|
.getAttribute('aria-pressed'),
|
|
).toBe('false');
|
|
|
|
rerender(renderToolbarView('hand', refs));
|
|
|
|
expect(
|
|
within(toolbar)
|
|
.getByRole('button', { name: '抓手工具' })
|
|
.getAttribute('aria-pressed'),
|
|
).toBe('true');
|
|
|
|
rerender(renderToolbarView('music', refs));
|
|
|
|
expect(
|
|
within(toolbar)
|
|
.getByRole('button', { name: '生成音乐' })
|
|
.getAttribute('aria-pressed'),
|
|
).toBe('false');
|
|
});
|
|
|
|
it('opens and closes bottom option tools on pointer and keyboard focus', async () => {
|
|
const user = userEvent.setup();
|
|
const openToolOptions = vi.fn();
|
|
const closeToolOptions = vi.fn();
|
|
const { toolbar, refs } = renderToolbar({
|
|
onOpenToolOptions: openToolOptions,
|
|
onCloseToolOptions: closeToolOptions,
|
|
});
|
|
|
|
await user.hover(within(toolbar).getByRole('button', { name: '生成规范' }));
|
|
await user.unhover(
|
|
within(toolbar).getByRole('button', { name: '生成规范' }),
|
|
);
|
|
await user.hover(within(toolbar).getByRole('button', { name: '生成音乐' }));
|
|
await user.unhover(
|
|
within(toolbar).getByRole('button', { name: '生成音乐' }),
|
|
);
|
|
|
|
const publicationTool = within(toolbar).getByRole('button', {
|
|
name: '宣发素材',
|
|
});
|
|
publicationTool.focus();
|
|
publicationTool.blur();
|
|
|
|
expect(openToolOptions).toHaveBeenCalledWith('spec');
|
|
expect(closeToolOptions).toHaveBeenCalledWith('spec');
|
|
expect(openToolOptions).toHaveBeenCalledWith('music');
|
|
expect(closeToolOptions).toHaveBeenCalledWith('music');
|
|
expect(openToolOptions).toHaveBeenCalledWith('publication');
|
|
expect(closeToolOptions).toHaveBeenCalledWith('publication');
|
|
});
|
|
});
|