合并 AI 设计图生图客户端交互
This commit is contained in:
@@ -711,11 +711,152 @@ describe('ImageCanvas Workspace-first design experience', () => {
|
||||
expect(sendImageWorkspaceMessageMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('keeps the historical video picker behavior when the brief medium is not decided yet', async () => {
|
||||
fetchImageWorkspaceConversationMock.mockResolvedValueOnce({
|
||||
...conversationFixture(),
|
||||
phase: 'shaping',
|
||||
brief: {
|
||||
version: 2,
|
||||
status: 'draft',
|
||||
medium: null,
|
||||
summary: '',
|
||||
ready: false,
|
||||
missingDecision: '请选择首帧来源',
|
||||
},
|
||||
messages: [
|
||||
...conversationFixture().messages,
|
||||
{
|
||||
id: 'message-undecided-source',
|
||||
role: 'assistant',
|
||||
kind: 'choice',
|
||||
text: '请选择视频首帧来源。',
|
||||
quickReplies: ['从作品列表选择图片'],
|
||||
generationQuote: null,
|
||||
turnRevision: 2,
|
||||
createdAt: '2026-08-12T09:00:00Z',
|
||||
},
|
||||
],
|
||||
turnRevision: 2,
|
||||
} satisfies DesignConversation);
|
||||
render(<MemoryRouter><ImageCanvas /></MemoryRouter>);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: '从作品列表选择图片' }));
|
||||
const picker = screen.getByRole('dialog', { name: '选择视频首帧' });
|
||||
const selectButton = within(picker).getByRole('button', { name: '选择此图片' });
|
||||
await waitFor(() => expect(selectButton).toBeEnabled());
|
||||
fireEvent.click(selectButton);
|
||||
|
||||
await waitFor(() => expect(sendImageWorkspaceMessageMock).toHaveBeenCalledWith(
|
||||
'workspace-cloud',
|
||||
'conversation-cloud',
|
||||
2,
|
||||
'使用作品图片作为视频首帧',
|
||||
expect.stringMatching(/^turn-/),
|
||||
['asset-one'],
|
||||
));
|
||||
expect(screen.queryByRole('dialog', { name: '选择视频首帧' }))
|
||||
.not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens the image reference picker and submits a successful work Asset id', async () => {
|
||||
fetchImageWorkspaceConversationMock.mockResolvedValueOnce({
|
||||
...conversationFixture(),
|
||||
phase: 'shaping',
|
||||
brief: {
|
||||
version: 2,
|
||||
status: 'draft',
|
||||
medium: 'image',
|
||||
summary: '参考海洋公益海报生成新图',
|
||||
ready: false,
|
||||
missingDecision: '请选择参考图来源',
|
||||
},
|
||||
messages: [
|
||||
...conversationFixture().messages,
|
||||
{
|
||||
id: 'message-image-source',
|
||||
role: 'assistant',
|
||||
kind: 'choice',
|
||||
text: '请选择图生图参考图。',
|
||||
quickReplies: ['从作品列表选择图片'],
|
||||
generationQuote: null,
|
||||
turnRevision: 2,
|
||||
createdAt: '2026-08-12T09:00:00Z',
|
||||
},
|
||||
],
|
||||
turnRevision: 2,
|
||||
} satisfies DesignConversation);
|
||||
render(<MemoryRouter><ImageCanvas /></MemoryRouter>);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: '从作品列表选择图片' }));
|
||||
const picker = screen.getByRole('dialog', { name: '选择图生图参考图' });
|
||||
expect(within(picker).getByText(/作为图生图参考/)).toBeInTheDocument();
|
||||
const selectButton = within(picker).getByRole('button', { name: '选择此图片' });
|
||||
await waitFor(() => expect(selectButton).toBeEnabled());
|
||||
fireEvent.click(selectButton);
|
||||
|
||||
await waitFor(() => expect(sendImageWorkspaceMessageMock).toHaveBeenCalledWith(
|
||||
'workspace-cloud',
|
||||
'conversation-cloud',
|
||||
2,
|
||||
'使用作品图片作为图生图参考图',
|
||||
expect.stringMatching(/^turn-/),
|
||||
['asset-one'],
|
||||
));
|
||||
expect(screen.queryByRole('dialog', { name: '选择图生图参考图' }))
|
||||
.not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('uploads a local image reference and submits its Asset id to the Agent', async () => {
|
||||
fetchImageWorkspaceConversationMock.mockResolvedValueOnce({
|
||||
...conversationFixture(),
|
||||
messages: [
|
||||
...conversationFixture().messages,
|
||||
{
|
||||
id: 'message-image-source',
|
||||
role: 'assistant',
|
||||
kind: 'choice',
|
||||
text: '请选择图生图参考图。',
|
||||
quickReplies: ['从作品列表选择图片'],
|
||||
generationQuote: null,
|
||||
turnRevision: 2,
|
||||
createdAt: '2026-08-12T09:00:00Z',
|
||||
},
|
||||
],
|
||||
turnRevision: 2,
|
||||
} satisfies DesignConversation);
|
||||
render(<MemoryRouter><ImageCanvas /></MemoryRouter>);
|
||||
fireEvent.click(await screen.findByRole('button', { name: '从作品列表选择图片' }));
|
||||
const picker = screen.getByRole('dialog', { name: '选择图生图参考图' });
|
||||
const file = new File(['image-bytes'], 'reference.png', { type: 'image/png' });
|
||||
|
||||
fireEvent.change(within(picker).getByLabelText('上传本地图片'), {
|
||||
target: { files: [file] },
|
||||
});
|
||||
|
||||
await waitFor(() => expect(uploadImageWorkspaceAssetMock)
|
||||
.toHaveBeenCalledWith('workspace-cloud', file));
|
||||
await waitFor(() => expect(sendImageWorkspaceMessageMock).toHaveBeenCalledWith(
|
||||
'workspace-cloud',
|
||||
'conversation-cloud',
|
||||
2,
|
||||
'使用上传图片作为图生图参考图',
|
||||
expect.stringMatching(/^turn-/),
|
||||
['asset-uploaded'],
|
||||
));
|
||||
await waitFor(() => expect(
|
||||
screen.queryByRole('dialog', { name: '选择图生图参考图' }),
|
||||
).not.toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('submits a successful work Asset id when it is selected as the video first frame', async () => {
|
||||
const pendingSelection = deferred<DesignConversation>();
|
||||
sendImageWorkspaceMessageMock.mockReturnValueOnce(pendingSelection.promise);
|
||||
fetchImageWorkspaceConversationMock.mockResolvedValueOnce({
|
||||
...conversationFixture(),
|
||||
brief: {
|
||||
...conversationFixture().brief,
|
||||
medium: 'video',
|
||||
},
|
||||
turnRevision: 2,
|
||||
messages: [
|
||||
...conversationFixture().messages,
|
||||
@@ -759,6 +900,10 @@ describe('ImageCanvas Workspace-first design experience', () => {
|
||||
it('uploads a local first-frame image and submits its Asset id to the Agent', async () => {
|
||||
fetchImageWorkspaceConversationMock.mockResolvedValueOnce({
|
||||
...conversationFixture(),
|
||||
brief: {
|
||||
...conversationFixture().brief,
|
||||
medium: 'video',
|
||||
},
|
||||
messages: [
|
||||
...conversationFixture().messages,
|
||||
{
|
||||
@@ -793,6 +938,9 @@ describe('ImageCanvas Workspace-first design experience', () => {
|
||||
expect.stringMatching(/^turn-/),
|
||||
['asset-uploaded'],
|
||||
));
|
||||
await waitFor(() => expect(
|
||||
screen.queryByRole('dialog', { name: '选择视频首帧' }),
|
||||
).not.toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('renders policy-blocked generation tasks with a user-facing design message', async () => {
|
||||
|
||||
Reference in New Issue
Block a user