Increase VectorEngine timeouts and add image UI
Add VectorEngine image generation config and raise request timeouts (env + scripts) from 180000 to 1000000ms. Introduce a reusable CreativeImageInputPanel component with tests and wire up mobile keyboard-focus helpers; update generation views and related tests (CustomWorldGenerationView, BarkBattle editor, Match3D, Puzzle flows). Improve API error handling / VectorEngine request guidance (packages/shared http.ts and docs), and apply multiple backend/frontend fixes for puzzle/match3d/prompt handling. Also include extensive docs and decision-log updates describing UI/UX decisions and verification steps.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { afterEach, expect, test, vi } from 'vitest';
|
||||
|
||||
@@ -83,7 +83,9 @@ const testEntryConfig = {
|
||||
],
|
||||
} satisfies CreationEntryConfig;
|
||||
|
||||
const testCreationTypes = derivePlatformCreationTypes(testEntryConfig.creationTypes);
|
||||
const testCreationTypes = derivePlatformCreationTypes(
|
||||
testEntryConfig.creationTypes,
|
||||
);
|
||||
|
||||
const originalClipboard = navigator.clipboard;
|
||||
|
||||
@@ -315,7 +317,9 @@ test('creation hub hides square hole works when the creation type is hidden', ()
|
||||
);
|
||||
|
||||
expect(screen.queryByText('隐藏方洞挑战')).toBeNull();
|
||||
expect(screen.queryByText('入口隐藏后,这条作品不应出现在创作页作品架。')).toBeNull();
|
||||
expect(
|
||||
screen.queryByText('入口隐藏后,这条作品不应出现在创作页作品架。'),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
test('creation hub mixes puzzle works into the same grid and uses puzzle tag to distinguish', () => {
|
||||
@@ -494,10 +498,43 @@ test('creation hub hides persisted draft delete action behind swipe underlay', (
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.querySelector('.creation-work-card__swipe-underlay')).toBeTruthy();
|
||||
expect(
|
||||
container.querySelector('.creation-work-card__swipe-underlay'),
|
||||
).toBeTruthy();
|
||||
expect(screen.queryByRole('button', { name: '删除' })).toBeNull();
|
||||
});
|
||||
|
||||
test('creation hub reveals persisted draft delete action from left swipe', () => {
|
||||
const { container } = render(
|
||||
<CustomWorldCreationHub
|
||||
items={[{ ...baseDraftItem, profileId: 'profile-1' }]}
|
||||
loading={false}
|
||||
error={null}
|
||||
onRetry={() => {}}
|
||||
onCreateType={noopCreateType}
|
||||
onOpenDraft={() => {}}
|
||||
onEnterPublished={() => {}}
|
||||
onDeletePublished={() => {}}
|
||||
entryConfig={testEntryConfig}
|
||||
creationTypes={testCreationTypes}
|
||||
/>,
|
||||
);
|
||||
|
||||
const card = screen.getByRole('button', { name: /继续完善《潮雾列岛》/u });
|
||||
fireEvent.touchStart(card, {
|
||||
touches: [{ clientX: 180, clientY: 20 }],
|
||||
});
|
||||
fireEvent.touchMove(card, {
|
||||
touches: [{ clientX: 92, clientY: 22 }],
|
||||
});
|
||||
fireEvent.touchEnd(card);
|
||||
|
||||
expect(screen.getByRole('button', { name: '删除' })).toBeTruthy();
|
||||
expect(
|
||||
container.querySelector('.creation-work-card-shell--actions-visible'),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('creation hub reveals persisted draft delete action from keyboard', async () => {
|
||||
const user = userEvent.setup();
|
||||
render(
|
||||
@@ -519,6 +556,7 @@ test('creation hub reveals persisted draft delete action from keyboard', async (
|
||||
await user.keyboard('{ArrowLeft}');
|
||||
|
||||
expect(screen.getByRole('button', { name: '删除' })).toBeTruthy();
|
||||
expect(screen.queryByRole('button', { name: '分享' })).toBeNull();
|
||||
});
|
||||
|
||||
test('creation hub shows delete action for baby object match drafts', async () => {
|
||||
@@ -548,11 +586,13 @@ test('creation hub shows delete action for baby object match drafts', async () =
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '删除' }));
|
||||
|
||||
expect(onDeleteBabyObjectMatch).toHaveBeenCalledWith(babyObjectMatchDraftItem);
|
||||
expect(onDeleteBabyObjectMatch).toHaveBeenCalledWith(
|
||||
babyObjectMatchDraftItem,
|
||||
);
|
||||
expect(onOpenBabyObjectMatchDetail).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('creation hub published work delete action is available beside share without opening card', async () => {
|
||||
test('creation hub published work delete action is revealed without opening card', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onDeletePuzzle = vi.fn();
|
||||
const onOpenPuzzleDetail = vi.fn();
|
||||
@@ -705,3 +745,35 @@ test('creation hub published swipe share button copies share text without openin
|
||||
await screen.findByRole('button', { name: '分享内容已复制' }),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('creation hub left swipe draft reveals delete without opening card', () => {
|
||||
const onDeletePublished = vi.fn();
|
||||
const onOpenDraft = vi.fn();
|
||||
|
||||
render(
|
||||
<CustomWorldCreationHub
|
||||
items={[{ ...baseDraftItem, profileId: 'profile-1' }]}
|
||||
loading={false}
|
||||
error={null}
|
||||
onRetry={() => {}}
|
||||
onCreateType={noopCreateType}
|
||||
onOpenDraft={onOpenDraft}
|
||||
onEnterPublished={() => {}}
|
||||
onDeletePublished={onDeletePublished}
|
||||
entryConfig={testEntryConfig}
|
||||
creationTypes={testCreationTypes}
|
||||
/>,
|
||||
);
|
||||
|
||||
const card = screen.getByRole('button', { name: /继续完善《潮雾列岛》/u });
|
||||
fireEvent.touchStart(card, {
|
||||
touches: [{ clientX: 180, clientY: 20 }],
|
||||
});
|
||||
fireEvent.touchMove(card, {
|
||||
touches: [{ clientX: 88, clientY: 22 }],
|
||||
});
|
||||
fireEvent.touchEnd(card);
|
||||
|
||||
expect(screen.getByRole('button', { name: '删除' })).toBeTruthy();
|
||||
expect(onOpenDraft).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user