Files
Genarrative/apps/admin-web/src/pages/AdminEditorAssetQueryPage.test.tsx
T
kdletters b288b091b2 完善精选审核与素材查询展示
移除素材查询分类筛选和分类列

精选审核通过后改为手动设置展示分类

公开精选按分类展示并补充底部点赞按钮

使用文档大拇指透明图标并同步点赞测试

同步精选审核数据契约、绑定和文档
2026-07-05 18:01:02 +08:00

201 lines
5.7 KiB
TypeScript

/* @vitest-environment jsdom */
import {fireEvent, render, screen, waitFor, within} from '@testing-library/react';
import {beforeEach, expect, test, vi} from 'vitest';
import {
getAdminAssetReadUrl,
listAdminEditorAssets,
} from '../api/adminApiClient';
import type {AdminEditorAssetPayload} from '../api/adminApiTypes';
import {AdminEditorAssetQueryPage} from './AdminEditorAssetQueryPage';
vi.mock('../api/adminApiClient', () => ({
getAdminAssetReadUrl: vi.fn(),
listAdminEditorAssets: vi.fn(),
}));
const generatedAsset: AdminEditorAssetPayload = {
assetId: 'asset-1',
ownerUserId: 'user-1',
authorDisplayName: '作者昵称',
authorPublicUserCode: 'SY-00000042',
folderId: 'folder-1',
label: '角色形象 1',
assetObjectId: 'asset-object-1',
imageSrc: '/generated-character-drafts/editor/spec.png',
objectKey: 'generated-character-drafts/editor/spec.png',
width: 1024,
height: 1024,
sourceType: 'generated',
prompt: '完整提示词内容',
actualPrompt: null,
model: 'gpt-image-2',
provider: 'character',
taskId: 'task-1',
assetKind: 'character',
generationInputs: {style: 'clay'},
sourceResourceId: 'resource-1',
thumbnailSrc: null,
generationCostMudPoints: 12,
createdAt: '2026-07-04T10:00:00Z',
updatedAt: '2026-07-04T10:00:00Z',
};
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(listAdminEditorAssets).mockResolvedValue({
entries: [generatedAsset],
nextCursor: null,
});
vi.mocked(getAdminAssetReadUrl).mockResolvedValue({
read: {
objectKey: 'generated-character-drafts/editor/spec.png',
signedUrl:
'https://signed.example.com/generated-character-drafts/editor/spec.png',
expiresAt: '2026-07-04T11:00:00Z',
},
});
});
test('后台素材查询展示作者昵称和陶泥号', async () => {
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
expect(await screen.findByText('作者昵称')).toBeTruthy();
expect(screen.getByText('SY-00000042')).toBeTruthy();
expect(screen.queryByText('user-1')).toBeNull();
});
test('后台素材查询按用户、搜索和时间调用查询接口', async () => {
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
await screen.findByRole('img', {name: '素材:角色形象 1'});
fireEvent.change(screen.getByLabelText('用户 ID'), {
target: {value: 'user-1'},
});
fireEvent.change(screen.getByLabelText('搜索'), {
target: {value: '陶泥角色'},
});
fireEvent.change(screen.getByLabelText('开始时间'), {
target: {value: '2026-07-01'},
});
fireEvent.change(screen.getByLabelText('结束时间'), {
target: {value: '2026-07-04'},
});
await waitFor(() => {
expect(listAdminEditorAssets).toHaveBeenLastCalledWith('admin-token', {
ownerUserId: 'user-1',
keyword: '陶泥角色',
createdAfter: '2026-07-01T00:00:00+08:00',
createdBefore: '2026-07-04T23:59:59.999+08:00',
limit: 80,
});
});
});
test('后台素材查询不展示分类筛选和分类列', async () => {
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
expect(await screen.findByText('角色形象 1')).toBeTruthy();
expect(screen.queryByLabelText('分类')).toBeNull();
expect(screen.queryByRole('columnheader', {name: '分类'})).toBeNull();
});
test('后台素材查询缩略图使用 objectKey 换签后展示', async () => {
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
const image = await screen.findByRole('img', {name: '素材:角色形象 1'});
await waitFor(() => {
expect(image.getAttribute('src')).toBe(
'https://signed.example.com/generated-character-drafts/editor/spec.png',
);
});
expect(getAdminAssetReadUrl).toHaveBeenCalledWith({
objectKey: 'generated-character-drafts/editor/spec.png',
expireSeconds: 300,
});
});
test('后台素材查询格式化微秒时间文本', async () => {
vi.mocked(listAdminEditorAssets).mockResolvedValueOnce({
entries: [
{
...generatedAsset,
createdAt: '1783231493.573727Z',
updatedAt: '1783231493.573727Z',
},
],
nextCursor: null,
});
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
expect(await screen.findByText('角色形象 1')).toBeTruthy();
expect(screen.queryByText('1783231493.573727Z')).toBeNull();
});
test('后台素材查询可查看素材详情', async () => {
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
fireEvent.click(await screen.findByRole('button', {name: '详情'}));
const dialog = screen.getByRole('dialog', {name: '素材详情'});
expect(within(dialog).getByText('asset-1')).toBeTruthy();
expect(within(dialog).getByText('1024 x 1024')).toBeTruthy();
expect(within(dialog).getByText('12 泥点')).toBeTruthy();
expect(within(dialog).getByText(/"style": "clay"/u)).toBeTruthy();
});
test('后台素材查询可打开弹窗查看完整提示词', async () => {
render(
<AdminEditorAssetQueryPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
fireEvent.click(await screen.findByRole('button', {name: '完整提示词内容'}));
const dialog = screen.getByRole('dialog', {name: '完整提示词'});
expect(within(dialog).getByText('完整提示词内容')).toBeTruthy();
fireEvent.click(within(dialog).getByRole('button', {name: '关闭完整提示词'}));
await waitFor(() => {
expect(screen.queryByRole('dialog', {name: '完整提示词'})).toBeNull();
});
});