Files
makelore/tests/unit/image-prompt-museum-page.test.tsx
inman 26b52d76e3
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled
feat: 完善图像工作区与创作工具体验
2026-08-16 14:08:27 +08:00

130 lines
4.9 KiB
TypeScript

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' }),
);
});
});