调整桌面首页进入创作主页
桌面端打开根路径默认进入创作主页 移动端根路径继续保持推荐首页 补充首页初始路由测试与创作主页文档说明
This commit is contained in:
+78
-11
@@ -3,9 +3,27 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import App from './App';
|
||||
import { resolveInitialSelectionStageFromPath } from './routing/appPageRoutes';
|
||||
|
||||
function mockMatchMedia(matches: boolean) {
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: vi.fn().mockImplementation((query: string) => ({
|
||||
matches,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
addListener: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
dispatchEvent: vi.fn(),
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
vi.mock('./components/platform-entry/PlatformEntryFlowShell', async () => {
|
||||
const React = await import('react');
|
||||
@@ -14,18 +32,30 @@ vi.mock('./components/platform-entry/PlatformEntryFlowShell', async () => {
|
||||
>;
|
||||
|
||||
return {
|
||||
PlatformEntryFlowShell: ({ setSelectionStage }: PlatformEntryFlowShellProps) =>
|
||||
PlatformEntryFlowShell: ({
|
||||
selectionStage,
|
||||
setSelectionStage,
|
||||
}: PlatformEntryFlowShellProps) =>
|
||||
React.createElement(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
onClick: () => {
|
||||
setSelectionStage('image-editor', {
|
||||
path: '/editor/canvas?projectid=project-from-test',
|
||||
});
|
||||
'div',
|
||||
null,
|
||||
React.createElement(
|
||||
'div',
|
||||
{ 'data-testid': 'selection-stage' },
|
||||
selectionStage,
|
||||
),
|
||||
React.createElement(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
onClick: () => {
|
||||
setSelectionStage('image-editor', {
|
||||
path: '/editor/canvas?projectid=project-from-test',
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
'打开最近项目',
|
||||
'打开最近项目',
|
||||
),
|
||||
),
|
||||
};
|
||||
});
|
||||
@@ -34,8 +64,45 @@ vi.mock('./RpgRuntimeApp', () => ({
|
||||
RpgRuntimeApp: () => <div>运行态</div>,
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('resolveInitialSelectionStageFromPath', () => {
|
||||
it('opens the desktop root route on the creation home stage', () => {
|
||||
expect(resolveInitialSelectionStageFromPath('/', true)).toBe(
|
||||
'creation-home',
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the mobile root route on the platform stage', () => {
|
||||
expect(resolveInitialSelectionStageFromPath('/', false)).toBe('platform');
|
||||
});
|
||||
|
||||
it('keeps explicit routes mapped to their own stages on desktop', () => {
|
||||
expect(resolveInitialSelectionStageFromPath('/creation/puzzle', true)).toBe(
|
||||
'puzzle-agent-workspace',
|
||||
);
|
||||
expect(resolveInitialSelectionStageFromPath('/creation', true)).toBe(
|
||||
'creation-home',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('App navigation history', () => {
|
||||
it('renders the desktop home URL with the creation home stage', () => {
|
||||
mockMatchMedia(true);
|
||||
window.history.replaceState(null, '', '/');
|
||||
|
||||
render(<App />);
|
||||
|
||||
expect(screen.getByTestId('selection-stage').textContent).toBe(
|
||||
'creation-home',
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps project canvas navigation as one history entry with projectid', async () => {
|
||||
mockMatchMedia(true);
|
||||
window.history.replaceState(null, '', '/creation');
|
||||
const pushStateSpy = vi.spyOn(window.history, 'pushState');
|
||||
const user = userEvent.setup();
|
||||
|
||||
+10
-3
@@ -9,6 +9,7 @@ import {
|
||||
|
||||
import { useAuthUi } from './components/auth/AuthUiContext';
|
||||
import { PlatformEntryFlowShell } from './components/platform-entry/PlatformEntryFlowShell';
|
||||
import { getInitialPlatformDesktopLayout } from './components/platform-entry/platformEntryResponsive';
|
||||
import type {
|
||||
CustomWorldRuntimeLaunchOptions,
|
||||
SelectionStage,
|
||||
@@ -19,8 +20,8 @@ import {
|
||||
normalizeAppPath,
|
||||
pushAppHistoryPath,
|
||||
readPublicWorkCodeFromLocationSearch,
|
||||
resolveInitialSelectionStageFromPath,
|
||||
resolvePathForSelectionStage,
|
||||
resolveSelectionStageFromPath,
|
||||
} from './routing/appPageRoutes';
|
||||
import type { RpgRuntimeAppIntent } from './RpgRuntimeApp';
|
||||
import type { CustomWorldProfile } from './types';
|
||||
@@ -59,7 +60,10 @@ export default function App() {
|
||||
isRpgRuntimeRoute(window.location.pathname),
|
||||
);
|
||||
const [selectionStage, setRawSelectionStage] = useState<SelectionStage>(() =>
|
||||
resolveSelectionStageFromPath(window.location.pathname),
|
||||
resolveInitialSelectionStageFromPath(
|
||||
window.location.pathname,
|
||||
getInitialPlatformDesktopLayout(),
|
||||
),
|
||||
);
|
||||
const [runtimeReturnStage, setRuntimeReturnStage] =
|
||||
useState<SelectionStage>('platform');
|
||||
@@ -84,7 +88,10 @@ export default function App() {
|
||||
|
||||
setIsRuntimeActive(false);
|
||||
setRawSelectionStage(
|
||||
resolveSelectionStageFromPath(window.location.pathname),
|
||||
resolveInitialSelectionStageFromPath(
|
||||
window.location.pathname,
|
||||
getInitialPlatformDesktopLayout(),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -101,6 +101,20 @@ export function resolveSelectionStageFromPath(
|
||||
return ROUTE_STAGE_BY_PATH.get(normalizeAppPath(pathname)) ?? 'platform';
|
||||
}
|
||||
|
||||
export function resolveInitialSelectionStageFromPath(
|
||||
pathname: string,
|
||||
isDesktopLayout: boolean,
|
||||
): SelectionStage {
|
||||
const normalizedPath = normalizeAppPath(pathname);
|
||||
const selectionStage = resolveSelectionStageFromPath(pathname);
|
||||
|
||||
if (normalizedPath === '/' && isDesktopLayout) {
|
||||
return 'creation-home';
|
||||
}
|
||||
|
||||
return selectionStage;
|
||||
}
|
||||
|
||||
export function resolvePathForSelectionStage(stage: SelectionStage) {
|
||||
return APP_STAGE_ROUTES[stage] ?? APP_STAGE_ROUTES.platform;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user