feat(web-platform): release V0.8.3 常规界面优化
web-platform-release / Build and publish release (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
web-platform-release / Build and publish release (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import type { ComponentProps } from 'react';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { DEFAULT_PHYSICAL_MAP_CONFIG } from '../../map/types';
|
||||
import type { SimulationSnapshot } from '../../simulation/SimulationSession';
|
||||
import { ModelControlsSidebar } from './ModelControlsSidebar';
|
||||
|
||||
const snapshot = {
|
||||
bodies: [
|
||||
{ id: 0, name: 'world', parentId: 0 },
|
||||
{ id: 1, name: 'base', parentId: 0 },
|
||||
{ id: 2, name: 'arm', parentId: 1 },
|
||||
],
|
||||
joints: [
|
||||
{
|
||||
id: 7,
|
||||
name: 'arm_joint',
|
||||
bodyId: 2,
|
||||
type: 3,
|
||||
value: 0.25,
|
||||
min: -1,
|
||||
max: 1,
|
||||
limitMin: -1,
|
||||
limitMax: 1,
|
||||
limited: true,
|
||||
limitsIgnored: false,
|
||||
editable: true,
|
||||
axis: [0, 0, 1],
|
||||
},
|
||||
],
|
||||
actuators: [],
|
||||
model: { nbody: 3, njnt: 1, ngeom: 2, ncam: 0, nactuator: 0, nu: 0, nq: 1, nv: 1 },
|
||||
} as unknown as SimulationSnapshot;
|
||||
|
||||
const noop = () => {};
|
||||
const asyncTrue = async () => true;
|
||||
|
||||
function props(
|
||||
patch: Partial<ComponentProps<typeof ModelControlsSidebar>> = {},
|
||||
): ComponentProps<typeof ModelControlsSidebar> {
|
||||
return {
|
||||
snapshot,
|
||||
selection: null,
|
||||
viewerSelection: null,
|
||||
loading: false,
|
||||
urdfMode: 'mjcf',
|
||||
baseMode: 'floating',
|
||||
showCollision: false,
|
||||
ignoreJointLimits: false,
|
||||
jointAdvanced: false,
|
||||
angleUnit: 'rad',
|
||||
mapSelection: { kind: 'none' },
|
||||
mapSceneDirty: false,
|
||||
maps: [],
|
||||
showVisualMap: true,
|
||||
showMapCollision: false,
|
||||
editorDocument: null,
|
||||
workspaceTool: null,
|
||||
onWorkspaceToolChange: noop,
|
||||
onSelectJoint: noop,
|
||||
onUrdfMode: noop,
|
||||
onBaseMode: noop,
|
||||
onShowCollision: noop,
|
||||
onResetJoints: noop,
|
||||
onToggleJointLimits: noop,
|
||||
onToggleAdvanced: noop,
|
||||
onToggleAngleUnit: noop,
|
||||
onActuator: noop,
|
||||
onActuatorParameters: noop,
|
||||
onJoint: noop,
|
||||
onApplyMap: noop,
|
||||
onMapDraft: noop,
|
||||
onEditorPreview: noop,
|
||||
onEditorDraftChange: noop,
|
||||
onEditorApply: asyncTrue,
|
||||
onEditorExport: noop,
|
||||
onEditorConvert: asyncTrue,
|
||||
onEditorBindInteraction: noop,
|
||||
onEditorSelect: noop,
|
||||
onEditorSessionStateChange: noop,
|
||||
onMapDisplay: noop,
|
||||
...patch,
|
||||
};
|
||||
}
|
||||
|
||||
describe('ModelControlsSidebar', () => {
|
||||
it('没有选择时显示场景摘要,并保留基础地图快速入口', () => {
|
||||
render(<ModelControlsSidebar {...props()} />);
|
||||
expect(screen.getByText('未选择对象')).toBeVisible();
|
||||
expect(screen.getByText('模型摘要')).toBeVisible();
|
||||
expect(screen.getByText('未选择地图实例')).toBeVisible();
|
||||
});
|
||||
|
||||
it('按照统一选择自动路由 Body 与 Joint 检查器', () => {
|
||||
const view = render(
|
||||
<ModelControlsSidebar {...props({ selection: { kind: 'body', bodyId: 2 } })} />,
|
||||
);
|
||||
expect(screen.getByText('Robot / Body')).toBeVisible();
|
||||
expect(screen.getByText('arm', { selector: '[title="arm"]' })).toBeVisible();
|
||||
|
||||
view.rerender(
|
||||
<ModelControlsSidebar {...props({ selection: { kind: 'joint', jointId: 7, bodyId: 2 } })} />,
|
||||
);
|
||||
expect(screen.getByText('Robot / Joint')).toBeVisible();
|
||||
expect(screen.getByText('Hinge · arm')).toBeVisible();
|
||||
expect(screen.getByText('关联 Actuator')).toBeVisible();
|
||||
});
|
||||
|
||||
it('控制台与数据录制在右侧面板内切换,不创建模态窗口', () => {
|
||||
const onWorkspaceToolChange = vi.fn();
|
||||
render(
|
||||
<ModelControlsSidebar
|
||||
{...props({
|
||||
selection: { kind: 'body', bodyId: 2 },
|
||||
workspaceTool: 'controls',
|
||||
workspaceTools: (
|
||||
<div role="tabpanel" aria-label="控制台">
|
||||
内嵌控制工具
|
||||
</div>
|
||||
),
|
||||
onWorkspaceToolChange,
|
||||
})}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('tabpanel', { name: '控制台' })).toBeVisible();
|
||||
expect(screen.getByText('内嵌控制工具')).toBeVisible();
|
||||
const inspector = document.querySelector('[role="tabpanel"][aria-label="检查器"]');
|
||||
expect(inspector).not.toBeNull();
|
||||
expect(inspector).not.toBeVisible();
|
||||
const controlsTab = screen.getByRole('tab', { name: '控制台' });
|
||||
expect(controlsTab).toHaveAttribute('aria-selected', 'true');
|
||||
|
||||
fireEvent.keyDown(controlsTab, { key: 'ArrowRight' });
|
||||
expect(onWorkspaceToolChange).toHaveBeenCalledWith('data');
|
||||
fireEvent.click(screen.getByRole('tab', { name: '检查器' }));
|
||||
expect(onWorkspaceToolChange).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('选择地图实例后自动展示地图检查器,并把全局工具移到右侧入口', () => {
|
||||
const onWorkspaceToolChange = vi.fn();
|
||||
render(
|
||||
<ModelControlsSidebar
|
||||
{...props({
|
||||
selection: { kind: 'map', mapAssetId: 'terrain-a' },
|
||||
activeMapAssetId: 'terrain-a',
|
||||
activeMapAssetName: '随机粗糙地形',
|
||||
mapSelection: {
|
||||
kind: 'builtin',
|
||||
config: { ...DEFAULT_PHYSICAL_MAP_CONFIG, preset: 'rough' },
|
||||
},
|
||||
onWorkspaceToolChange,
|
||||
})}
|
||||
/>,
|
||||
);
|
||||
expect(screen.getByText('Map / Instance')).toBeVisible();
|
||||
expect(screen.getByText('随机粗糙地形', { selector: '[title="随机粗糙地形"]' })).toBeVisible();
|
||||
fireEvent.click(screen.getByRole('tab', { name: '控制台' }));
|
||||
fireEvent.click(screen.getByRole('tab', { name: '数据录制' }));
|
||||
expect(onWorkspaceToolChange.mock.calls).toEqual([['controls'], ['data']]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user