新增 /project 项目页和我的页项目入口 补齐图片画布工程列表、重命名和删除 API 支持 /editor/canvas 按 projectid 加载指定工程 更新图片画布文档、TRACKING 和对应测试
236 lines
7.7 KiB
TypeScript
236 lines
7.7 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
pushAppHistoryPath,
|
|
resolvePathForSelectionStage,
|
|
resolveSelectionStageFromPath,
|
|
} from './appPageRoutes';
|
|
|
|
describe('appPageRoutes', () => {
|
|
it('resolves profile feedback route', () => {
|
|
expect(resolveSelectionStageFromPath('/profile/feedback')).toBe(
|
|
'profile-feedback',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/profile/feedback/')).toBe(
|
|
'profile-feedback',
|
|
);
|
|
expect(resolvePathForSelectionStage('profile-feedback')).toBe(
|
|
'/profile/feedback',
|
|
);
|
|
});
|
|
|
|
it('resolves the image editor route', () => {
|
|
expect(resolveSelectionStageFromPath('/editor/canvas')).toBe(
|
|
'image-editor',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/EDITOR/CANVAS/')).toBe(
|
|
'image-editor',
|
|
);
|
|
expect(resolvePathForSelectionStage('image-editor')).toBe('/editor/canvas');
|
|
});
|
|
|
|
it('resolves the project route', () => {
|
|
expect(resolveSelectionStageFromPath('/project')).toBe('project');
|
|
expect(resolveSelectionStageFromPath('/PROJECT/')).toBe('project');
|
|
expect(resolvePathForSelectionStage('project')).toBe('/project');
|
|
});
|
|
|
|
it('resolves jump-hop creation, gallery and runtime routes', () => {
|
|
expect(resolveSelectionStageFromPath('/creation/jump-hop')).toBe(
|
|
'jump-hop-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/jump-hop/generating')).toBe(
|
|
'jump-hop-generating',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/jump-hop/result')).toBe(
|
|
'jump-hop-result',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/gallery/jump-hop/detail')).toBe(
|
|
'jump-hop-gallery-detail',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/runtime/jump-hop')).toBe(
|
|
'jump-hop-runtime',
|
|
);
|
|
expect(resolvePathForSelectionStage('jump-hop-workspace')).toBe(
|
|
'/creation/jump-hop',
|
|
);
|
|
expect(resolvePathForSelectionStage('jump-hop-generating')).toBe(
|
|
'/creation/jump-hop/generating',
|
|
);
|
|
expect(resolvePathForSelectionStage('jump-hop-result')).toBe(
|
|
'/creation/jump-hop/result',
|
|
);
|
|
expect(resolvePathForSelectionStage('jump-hop-gallery-detail')).toBe(
|
|
'/gallery/jump-hop/detail',
|
|
);
|
|
expect(resolvePathForSelectionStage('jump-hop-runtime')).toBe(
|
|
'/runtime/jump-hop',
|
|
);
|
|
});
|
|
|
|
it('resolves puzzle-clear creation and runtime routes', () => {
|
|
expect(resolveSelectionStageFromPath('/creation/puzzle-clear')).toBe(
|
|
'puzzle-clear-workspace',
|
|
);
|
|
expect(
|
|
resolveSelectionStageFromPath('/creation/puzzle-clear/generating'),
|
|
).toBe('puzzle-clear-generating');
|
|
expect(resolveSelectionStageFromPath('/creation/puzzle-clear/result')).toBe(
|
|
'puzzle-clear-result',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/runtime/puzzle-clear')).toBe(
|
|
'puzzle-clear-runtime',
|
|
);
|
|
expect(resolvePathForSelectionStage('puzzle-clear-workspace')).toBe(
|
|
'/creation/puzzle-clear',
|
|
);
|
|
expect(resolvePathForSelectionStage('puzzle-clear-generating')).toBe(
|
|
'/creation/puzzle-clear/generating',
|
|
);
|
|
expect(resolvePathForSelectionStage('puzzle-clear-result')).toBe(
|
|
'/creation/puzzle-clear/result',
|
|
);
|
|
expect(resolvePathForSelectionStage('puzzle-clear-runtime')).toBe(
|
|
'/runtime/puzzle-clear',
|
|
);
|
|
});
|
|
|
|
it('resolves wooden fish creation and runtime routes', () => {
|
|
expect(resolveSelectionStageFromPath('/creation/wooden-fish')).toBe(
|
|
'wooden-fish-workspace',
|
|
);
|
|
expect(
|
|
resolveSelectionStageFromPath('/creation/wooden-fish/generating'),
|
|
).toBe('wooden-fish-generating');
|
|
expect(resolveSelectionStageFromPath('/creation/wooden-fish/result')).toBe(
|
|
'wooden-fish-result',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/runtime/wooden-fish')).toBe(
|
|
'wooden-fish-runtime',
|
|
);
|
|
expect(resolvePathForSelectionStage('wooden-fish-workspace')).toBe(
|
|
'/creation/wooden-fish',
|
|
);
|
|
expect(resolvePathForSelectionStage('wooden-fish-generating')).toBe(
|
|
'/creation/wooden-fish/generating',
|
|
);
|
|
expect(resolvePathForSelectionStage('wooden-fish-result')).toBe(
|
|
'/creation/wooden-fish/result',
|
|
);
|
|
expect(resolvePathForSelectionStage('wooden-fish-runtime')).toBe(
|
|
'/runtime/wooden-fish',
|
|
);
|
|
});
|
|
|
|
it('resolves creation routes to the existing entry form stages', () => {
|
|
expect(resolveSelectionStageFromPath('/creation/rpg')).toBe(
|
|
'agent-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/big-fish')).toBe(
|
|
'big-fish-agent-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/match3d')).toBe(
|
|
'match3d-agent-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/square-hole')).toBe(
|
|
'square-hole-agent-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/puzzle')).toBe(
|
|
'puzzle-agent-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/bark-battle')).toBe(
|
|
'bark-battle-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/visual-novel')).toBe(
|
|
'visual-novel-agent-workspace',
|
|
);
|
|
expect(resolveSelectionStageFromPath('/creation/baby-object-match')).toBe(
|
|
'baby-object-match-workspace',
|
|
);
|
|
|
|
expect(resolvePathForSelectionStage('agent-workspace')).toBe(
|
|
'/creation/rpg',
|
|
);
|
|
expect(resolvePathForSelectionStage('puzzle-agent-workspace')).toBe(
|
|
'/creation/puzzle',
|
|
);
|
|
expect(resolvePathForSelectionStage('bark-battle-workspace')).toBe(
|
|
'/creation/bark-battle',
|
|
);
|
|
expect(resolvePathForSelectionStage('baby-object-match-workspace')).toBe(
|
|
'/creation/baby-object-match',
|
|
);
|
|
});
|
|
|
|
it('preserves creation restore query params within the same creation flow', () => {
|
|
window.history.replaceState(
|
|
null,
|
|
'',
|
|
'/creation/rpg?sessionId=session-1&profileId=profile-1&draftId=draft-1&workId=work-1&clientRuntime=wechat_mini_program',
|
|
);
|
|
|
|
pushAppHistoryPath('/creation/rpg/result');
|
|
|
|
expect(window.location.pathname).toBe('/creation/rpg/result');
|
|
expect(window.location.search).toBe(
|
|
'?sessionId=session-1&profileId=profile-1&draftId=draft-1&workId=work-1&clientRuntime=wechat_mini_program',
|
|
);
|
|
});
|
|
|
|
it('preserves mini program runtime context while normalizing app paths', () => {
|
|
window.history.replaceState(
|
|
null,
|
|
'',
|
|
'/?clientType=mini_program&clientRuntime=wechat_mini_program&miniProgramEnv=trial',
|
|
);
|
|
|
|
pushAppHistoryPath('/');
|
|
|
|
expect(window.location.pathname).toBe('/');
|
|
expect(window.location.search).toBe(
|
|
'?clientType=mini_program&clientRuntime=wechat_mini_program&miniProgramEnv=trial',
|
|
);
|
|
});
|
|
|
|
it('keeps mini program runtime context when navigating to explicit query routes', () => {
|
|
window.history.replaceState(
|
|
null,
|
|
'',
|
|
'/?clientRuntime=wechat_mini_program',
|
|
);
|
|
|
|
pushAppHistoryPath('/works/detail?work=PZ-7A7B18D9');
|
|
|
|
expect(window.location.pathname).toBe('/works/detail');
|
|
expect(window.location.search).toBe(
|
|
'?work=PZ-7A7B18D9&clientRuntime=wechat_mini_program',
|
|
);
|
|
});
|
|
|
|
it('clears creation restore query params when leaving the flow or switching flows', () => {
|
|
window.history.replaceState(
|
|
null,
|
|
'',
|
|
'/creation/rpg?sessionId=session-1&profileId=profile-1',
|
|
);
|
|
|
|
pushAppHistoryPath('/creation/puzzle');
|
|
|
|
expect(window.location.pathname).toBe('/creation/puzzle');
|
|
expect(window.location.search).toBe('');
|
|
|
|
window.history.replaceState(
|
|
null,
|
|
'',
|
|
'/creation/rpg?sessionId=session-2&profileId=profile-2',
|
|
);
|
|
|
|
pushAppHistoryPath('/');
|
|
|
|
expect(window.location.pathname).toBe('/');
|
|
expect(window.location.search).toBe('');
|
|
});
|
|
});
|