Files
Mujoco_WASM/web_platform/src/app/components/ActuatorControl.test.tsx
T
chenlin 60d3a6d68c
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
chore(web-platform): release V0.6.1 工程质量优化
2026-08-28 15:38:10 +08:00

99 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { fireEvent, render, screen } from '@testing-library/react';
import { ActuatorControl } from './SidebarPanel';
import type { ActuatorInfo } from '../../simulation/SimulationSession';
const actuator: ActuatorInfo = {
id: 0,
name: 'shoulder_motor',
value: 0.5,
min: -1,
max: 1,
limited: true,
jointId: 0,
jointName: 'shoulder',
jointType: 3,
unit: 'N·m',
kind: 'motor',
controlCount: 1,
gear: 2,
gain: 1,
kp: 0,
kv: 0,
ctrlLimited: true,
ctrlMin: -1,
ctrlMax: 1,
forceLimited: true,
forceMin: -20,
forceMax: 20,
};
describe('ActuatorControl', () => {
it('显示对应关节和常用力矩单位', () => {
render(<ActuatorControl actuator={actuator} onControl={() => {}} onParameters={() => {}} />);
expect(screen.getByText('shoulder_motor')).toBeVisible();
expect(screen.getByText('关节:shoulder')).toBeVisible();
expect(screen.getByText('1.000 N·m')).toBeVisible();
});
it('内部按 gear 换算输出,但参数面板只开放 kp、kv 等业务参数', () => {
const onControl = vi.fn(),
onParameters = vi.fn();
render(
<ActuatorControl actuator={actuator} onControl={onControl} onParameters={onParameters} />,
);
fireEvent.change(screen.getByRole('slider'), { target: { value: '2' } });
expect(onControl).toHaveBeenCalledWith(1);
fireEvent.click(screen.getByText('常用参数'));
expect(screen.queryByLabelText('传动比 gear')).not.toBeInTheDocument();
expect(screen.queryByLabelText('固定增益 gain')).not.toBeInTheDocument();
const kp = screen.getByLabelText(/kpMJCF stiffness/);
fireEvent.change(kp, { target: { value: '3' } });
fireEvent.blur(kp);
expect(onParameters).toHaveBeenCalledWith(
expect.objectContaining({ kp: 3, ctrlLimited: true, forceLimited: true }),
);
});
it('position 伺服使用角度目标并开放 kp、kv', () => {
const onParameters = vi.fn();
render(
<ActuatorControl
actuator={{
...actuator,
name: 'shoulder_servo',
kind: 'position',
unit: '°',
value: Math.PI / 2,
min: -Math.PI,
max: Math.PI,
gear: 1,
kp: 100,
kv: 10,
gain: 100,
}}
onControl={() => {}}
onParameters={onParameters}
/>,
);
expect(screen.getByText('90.000 °')).toBeVisible();
fireEvent.click(screen.getByText('常用参数'));
const kp = screen.getByLabelText(/位置增益 kp/);
fireEvent.change(kp, { target: { value: '150' } });
fireEvent.blur(kp);
expect(onParameters).toHaveBeenCalledWith(expect.objectContaining({ kp: 150, kv: 10 }));
});
it('非 motor 驱动器保持原始控制单位且不开放通用参数编辑', () => {
render(
<ActuatorControl
actuator={{ ...actuator, name: 'custom', kind: 'other', unit: '', value: 0.25 }}
onControl={() => {}}
onParameters={() => {}}
/>,
);
expect(screen.getByText('0.250')).toBeVisible();
expect(screen.queryByText('常用参数')).not.toBeInTheDocument();
expect(screen.getByText(/不是可直接编辑的 motor\/position/)).toBeVisible();
});
});