feat: require cover for first project submission
This commit is contained in:
1 parent
7e8d9e3811
commit
145a6ce571
7 files changed
+318
-121
No files matched your search
@@ -63,7 +63,9 @@ async function advancePoll() {
|
||||
});
|
||||
}
|
||||
|
||||
async function submitProjectMetadata() {
|
||||
const pngBytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 1]);
|
||||
|
||||
async function submitProjectMetadata({ includeCover = true }: { includeCover?: boolean } = {}) {
|
||||
fetchCurrentWorksProjectStatusMock.mockRejectedValueOnce(Object.assign(
|
||||
new Error('project missing'),
|
||||
{ statusCode: 404 },
|
||||
@@ -75,6 +77,17 @@ async function submitProjectMetadata() {
|
||||
fireEvent.change(screen.getByLabelText(/发布者姓名/), { target: { value: '小明' } });
|
||||
fireEvent.change(screen.getByLabelText(/发布者年龄/), { target: { value: '12' } });
|
||||
fireEvent.change(screen.getByLabelText(/项目简介/), { target: { value: '这是一个太空清洁小游戏。' } });
|
||||
if (includeCover) {
|
||||
fireEvent.change(screen.getByLabelText(/项目封面/), {
|
||||
target: { files: [new File([pngBytes], 'space-cover.png', { type: 'image/png' })] },
|
||||
});
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
});
|
||||
expect(screen.getByText('space-cover.png')).toBeVisible();
|
||||
expect(screen.getByAltText('项目封面预览')).toBeVisible();
|
||||
expect(screen.getByText('重新选择')).toBeVisible();
|
||||
}
|
||||
fireEvent.click(screen.getByRole('button', { name: '提交审核' }));
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
@@ -95,7 +108,7 @@ describe('ProjectPublishAction', () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('creates a new project without a cover and locks after Builder succeeds', async () => {
|
||||
it('creates a new project with a cover DTO and locks after Builder succeeds', async () => {
|
||||
fetchCurrentWorksProjectStatusMock.mockResolvedValue(projectStatus('succeeded'));
|
||||
render(<ProjectPublishAction project={project} projectType="mini_game" />);
|
||||
|
||||
@@ -104,7 +117,7 @@ describe('ProjectPublishAction', () => {
|
||||
await flushSubmission();
|
||||
|
||||
expect(screen.getByTestId('project-publish-status')).toHaveTextContent(
|
||||
'无封面作品与本次构建结果已提交,正在等待平台校验。',
|
||||
'作品封面与本次构建结果已提交,正在等待平台校验。',
|
||||
);
|
||||
|
||||
expect(publishWorksProjectSourceMock).toHaveBeenCalledWith({
|
||||
@@ -121,9 +134,12 @@ describe('ProjectPublishAction', () => {
|
||||
age_band: null,
|
||||
difficulty: null,
|
||||
},
|
||||
cover: {
|
||||
fileName: 'space-cover.png',
|
||||
mimeType: 'image/png',
|
||||
dataBase64: 'iVBORw0KGgoB',
|
||||
},
|
||||
});
|
||||
expect(screen.queryByLabelText(/项目封面/)).not.toBeInTheDocument();
|
||||
expect(publishWorksProjectSourceMock.mock.calls[0]?.[0]).not.toHaveProperty('cover');
|
||||
expect(fetchCurrentWorksProjectStatusMock).toHaveBeenCalledOnce();
|
||||
|
||||
await advancePoll();
|
||||
@@ -133,7 +149,36 @@ describe('ProjectPublishAction', () => {
|
||||
);
|
||||
expect(fetchCurrentWorksProjectStatusMock).toHaveBeenCalledTimes(2);
|
||||
expect(screen.getByRole('button', { name: '已提交,等待运营审核' })).toBeDisabled();
|
||||
expect(screen.getByTestId('project-publish-status')).toHaveTextContent('无封面作品已提交');
|
||||
expect(screen.getByTestId('project-publish-status')).toHaveTextContent('作品与封面已提交');
|
||||
});
|
||||
|
||||
it('blocks first submission until a cover is selected', async () => {
|
||||
render(<ProjectPublishAction project={project} projectType="mini_game" />);
|
||||
|
||||
await submitProjectMetadata({ includeCover: false });
|
||||
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('首次提交必须上传');
|
||||
expect(publishWorksProjectSourceMock).not.toHaveBeenCalled();
|
||||
expect(screen.getByRole('dialog')).toBeVisible();
|
||||
});
|
||||
|
||||
it('rejects unsupported and oversized cover files before confirmation', async () => {
|
||||
fetchCurrentWorksProjectStatusMock.mockRejectedValue(Object.assign(new Error('missing'), { statusCode: 404 }));
|
||||
render(<ProjectPublishAction project={project} projectType="mini_game" />);
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: '一键提交审核' }));
|
||||
await Promise.resolve();
|
||||
});
|
||||
const input = screen.getByLabelText(/项目封面/);
|
||||
|
||||
fireEvent.change(input, { target: { files: [new File(['text'], 'cover.gif', { type: 'image/gif' })] } });
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('仅支持 PNG、JPEG 或 WebP');
|
||||
|
||||
fireEvent.change(input, {
|
||||
target: { files: [new File([new Uint8Array(10 * 1024 * 1024 + 1)], 'huge.png', { type: 'image/png' })] },
|
||||
});
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('不能超过 10 MiB');
|
||||
expect(publishWorksProjectSourceMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows a friendly Builder failure without raw details', async () => {
|
||||
|
||||
Reference in new issue
Block a user