Files
Genarrative/src/components/MapModal.test.tsx
kdletters 1ad25e30f8 收口前端平台组件库能力
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件
迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome
补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
2026-06-10 10:24:18 +08:00

108 lines
3.6 KiB
TypeScript

/* @vitest-environment jsdom */
import { fireEvent, render, screen, within } from '@testing-library/react';
import type { HTMLAttributes, ReactNode } from 'react';
import { expect, test, vi } from 'vitest';
import { getCustomWorldSceneRelativePositionLabel } from '../data/customWorldSceneGraph';
import {
getConnectedScenePresets,
getWorldCampScenePreset,
} from '../data/scenePresets';
import { WorldType } from '../types';
import { MapModal } from './MapModal';
vi.mock('motion/react', () => ({
AnimatePresence: ({ children }: { children: ReactNode }) => <>{children}</>,
motion: {
div: ({
animate: _animate,
children,
exit: _exit,
initial: _initial,
transition: _transition,
...props
}: HTMLAttributes<HTMLDivElement> & {
animate?: unknown;
exit?: unknown;
initial?: unknown;
transition?: unknown;
}) => <div {...props}>{children}</div>,
},
}));
test('目标场景确认面板复用暗色琥珀 PlatformSubpanel 和胶囊标签', () => {
const currentScene = getWorldCampScenePreset(WorldType.WUXIA);
if (!currentScene) {
throw new Error('测试需要武侠营地场景');
}
const destination = getConnectedScenePresets(
WorldType.WUXIA,
currentScene.id,
)[0];
if (!destination) {
throw new Error('测试需要至少一个相邻场景');
}
const connection = currentScene.connections.find(
(item) => item.sceneId === destination.id,
);
const destinationLabel = connection
? getCustomWorldSceneRelativePositionLabel(connection.relativePosition)
: '前方';
render(
<MapModal
isOpen
currentScenePreset={currentScene}
worldType={WorldType.WUXIA}
onClose={vi.fn()}
onTravelToScene={vi.fn()}
/>,
);
const destinationNameNode = screen.getAllByText(destination.name)[0];
if (!destinationNameNode) {
throw new Error('测试需要展示目标场景名称');
}
const destinationButton = destinationNameNode.closest('button');
if (!destinationButton) {
throw new Error('测试需要可点击的目标场景节点');
}
const mapNodeLabelBadge =
within(destinationButton).getByText(destinationLabel);
expect(mapNodeLabelBadge.className).toContain('bg-emerald-500/10');
expect(mapNodeLabelBadge.className).toContain('rounded-full');
fireEvent.click(destinationButton);
const panel = screen.getByTestId('map-target-scene-panel');
const currentSummary = screen.getByTestId('map-current-scene-summary');
const nextSummary = screen.getByTestId('map-next-scene-summary');
const labelBadge = within(panel).getByText(destinationLabel);
const cancelButton = screen.getByRole('button', { name: '取消' });
const confirmButton = screen.getByRole('button', { name: '确认前往' });
expect(panel.className).toContain('border-amber-300/18');
expect(panel.className).toContain('bg-amber-500/8');
expect(panel.className).toContain('rounded-xl');
expect(panel.className).toContain('p-4');
expect(labelBadge.className).toContain('rounded-full');
expect(labelBadge.className).toContain('bg-amber-500/10');
expect(currentSummary.className).toContain('border-white/10');
expect(currentSummary.className).toContain('bg-black/25');
expect(nextSummary.className).toContain('border-white/10');
expect(nextSummary.className).toContain('bg-black/25');
expect(cancelButton.className).toContain(
'platform-action-button--editor-dark',
);
expect(cancelButton.className).toContain('bg-black/20');
expect(confirmButton.className).toContain(
'platform-action-button--editor-dark',
);
expect(confirmButton.className).toContain('bg-amber-500/20');
});