feat: 完善图像工作区与创作工具体验
This commit is contained in:
129
tests/unit/image-prompt-museum-page.test.tsx
Normal file
129
tests/unit/image-prompt-museum-page.test.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { ImagePromptMuseum } from '@/pages/ImagePromptMuseum';
|
||||
import { useImagePromptMuseumStore } from '@/stores/image-prompt-museum';
|
||||
import type { PromptMuseumEntry, PromptMuseumPage } from '../../shared/image-prompt-museum';
|
||||
|
||||
const fetchPromptMuseumPageMock = vi.hoisted(() => vi.fn());
|
||||
const fetchPromptMuseumEntryMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock('@/lib/image-prompt-museum', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/lib/image-prompt-museum')>();
|
||||
return {
|
||||
...actual,
|
||||
fetchPromptMuseumPage: (...args: unknown[]) => fetchPromptMuseumPageMock(...args),
|
||||
fetchPromptMuseumEntry: (...args: unknown[]) => fetchPromptMuseumEntryMock(...args),
|
||||
};
|
||||
});
|
||||
|
||||
const pageFixture: PromptMuseumPage = {
|
||||
items: [{
|
||||
id: 'prompt-one',
|
||||
slug: 'editorial-poster',
|
||||
title: '编辑感产品海报',
|
||||
summary: '一张留白充足的编辑版式海报。',
|
||||
thumbnail: {
|
||||
url: 'https://cdn.example.com/prompt-one/thumb.webp',
|
||||
width: 1200,
|
||||
height: 900,
|
||||
alt: '编辑感产品海报示例',
|
||||
},
|
||||
categories: [
|
||||
{ id: 'poster', name: '海报', group: 'use_case' },
|
||||
{ id: 'editorial', name: '编辑感', group: 'style' },
|
||||
],
|
||||
model: { id: 'gpt-image-2', name: 'GPT Image 2' },
|
||||
language: 'zh-CN',
|
||||
attribution: {
|
||||
author: { name: '示例作者' },
|
||||
source: { name: '示例来源', url: 'https://example.com/source' },
|
||||
license: { name: 'CC BY 4.0', attributionText: '示例作者 / 示例来源 / CC BY 4.0' },
|
||||
},
|
||||
publishedAt: '2026-08-01T00:00:00Z',
|
||||
updatedAt: '2026-08-01T00:00:00Z',
|
||||
}],
|
||||
facets: {
|
||||
useCases: [{ id: 'poster', name: '海报', count: 1 }],
|
||||
styles: [{ id: 'editorial', name: '编辑感', count: 1 }],
|
||||
subjects: [],
|
||||
},
|
||||
nextCursor: null,
|
||||
total: 1,
|
||||
};
|
||||
|
||||
const entryFixture: PromptMuseumEntry = {
|
||||
...pageFixture.items[0],
|
||||
prompt: 'Create a clean editorial product poster with generous negative space.',
|
||||
variables: [],
|
||||
images: [pageFixture.items[0].thumbnail],
|
||||
requiresReferenceImages: false,
|
||||
};
|
||||
|
||||
describe('Prompt Museum page', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
useImagePromptMuseumStore.getState().clearPendingPrompt();
|
||||
fetchPromptMuseumPageMock.mockResolvedValue(pageFixture);
|
||||
fetchPromptMuseumEntryMock.mockResolvedValue(entryFixture);
|
||||
});
|
||||
|
||||
it('keeps the inspiration filters compact and below the native title bar', async () => {
|
||||
render(
|
||||
<MemoryRouter initialEntries={['/image-prompts']}>
|
||||
<Routes>
|
||||
<Route path="/image-prompts" element={<ImagePromptMuseum />} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
expect(screen.queryByText('提示词博物馆')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('image-prompt-museum-filters')).toHaveClass('sticky', 'top-0');
|
||||
});
|
||||
|
||||
it('renders server cards, opens attribution details, and sends the exact prompt back to Canvas', async () => {
|
||||
render(
|
||||
<MemoryRouter initialEntries={['/image-prompts']}>
|
||||
<Routes>
|
||||
<Route path="/image-prompts" element={<ImagePromptMuseum />} />
|
||||
<Route path="/image-canvas" element={<div data-testid="canvas-target">Canvas</div>} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: '查看 编辑感产品海报' }));
|
||||
expect(await screen.findByText('示例作者')).toBeInTheDocument();
|
||||
expect(screen.getByText('示例来源')).toBeInTheDocument();
|
||||
expect(screen.getByText(entryFixture.prompt)).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '使用此 Prompt' }));
|
||||
await waitFor(() => expect(screen.getByTestId('canvas-target')).toBeInTheDocument());
|
||||
expect(useImagePromptMuseumStore.getState().pendingPrompt).toEqual({
|
||||
promptId: entryFixture.id,
|
||||
title: entryFixture.title,
|
||||
prompt: entryFixture.prompt,
|
||||
});
|
||||
});
|
||||
|
||||
it('loads the next server cursor without bundling another page locally', async () => {
|
||||
const secondItem = { ...pageFixture.items[0], id: 'prompt-two', title: '第二条灵感' };
|
||||
fetchPromptMuseumPageMock
|
||||
.mockResolvedValueOnce({ ...pageFixture, nextCursor: 'cursor-two' })
|
||||
.mockResolvedValueOnce({ ...pageFixture, items: [secondItem], nextCursor: null });
|
||||
|
||||
render(
|
||||
<MemoryRouter initialEntries={['/image-prompts']}>
|
||||
<Routes>
|
||||
<Route path="/image-prompts" element={<ImagePromptMuseum />} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: '加载更多' }));
|
||||
expect(await screen.findByRole('button', { name: '查看 第二条灵感' })).toBeInTheDocument();
|
||||
expect(fetchPromptMuseumPageMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({ cursor: 'cursor-two' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user