Files
SubMiner/src/renderer/handlers/controller-binding-capture.test.ts

130 lines
3.5 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createControllerBindingCapture } from './controller-binding-capture.js';
function createSnapshot(
overrides: {
axes?: number[];
buttons?: Array<{ value: number; pressed?: boolean; touched?: boolean }>;
} = {},
) {
return {
axes: overrides.axes ?? [0, 0, 0, 0, 0],
buttons:
overrides.buttons ??
Array.from({ length: 12 }, () => ({
value: 0,
pressed: false,
touched: false,
})),
};
}
test('controller binding capture waits for neutral-to-active button edge', () => {
const capture = createControllerBindingCapture({
triggerDeadzone: 0.5,
stickDeadzone: 0.2,
});
const heldButtons = createSnapshot({
buttons: [{ value: 1, pressed: true, touched: true }],
});
capture.arm({ actionId: 'toggleLookup', bindingType: 'discrete' }, heldButtons);
assert.equal(capture.poll(heldButtons), null);
const neutralButtons = createSnapshot();
assert.equal(capture.poll(neutralButtons), null);
const freshPress = createSnapshot({
buttons: [{ value: 1, pressed: true, touched: true }],
});
assert.deepEqual(capture.poll(freshPress), {
actionId: 'toggleLookup',
bindingType: 'discrete',
binding: { kind: 'button', buttonIndex: 0 },
});
});
test('controller binding capture records fresh axis direction for discrete learn mode', () => {
const capture = createControllerBindingCapture({
triggerDeadzone: 0.5,
stickDeadzone: 0.2,
});
capture.arm({ actionId: 'closeLookup', bindingType: 'discrete' }, createSnapshot());
assert.deepEqual(capture.poll(createSnapshot({ axes: [0, 0, 0, -0.8] })), {
actionId: 'closeLookup',
bindingType: 'discrete',
binding: { kind: 'axis', axisIndex: 3, direction: 'negative' },
});
});
test('controller binding capture ignores analog drift inside deadzone', () => {
const capture = createControllerBindingCapture({
triggerDeadzone: 0.5,
stickDeadzone: 0.3,
});
capture.arm({ actionId: 'mineCard', bindingType: 'discrete' }, createSnapshot());
assert.equal(capture.poll(createSnapshot({ axes: [0.2, 0, 0, 0] })), null);
assert.equal(capture.isArmed(), true);
});
test('controller binding capture emits axis binding for continuous learn mode', () => {
const capture = createControllerBindingCapture({
triggerDeadzone: 0.5,
stickDeadzone: 0.2,
});
capture.arm(
{
actionId: 'leftStickHorizontal',
bindingType: 'axis',
dpadFallback: 'horizontal',
},
createSnapshot(),
);
assert.deepEqual(capture.poll(createSnapshot({ axes: [0, 0, 0, 0.9] })), {
actionId: 'leftStickHorizontal',
bindingType: 'axis',
binding: { kind: 'axis', axisIndex: 3, dpadFallback: 'horizontal' },
});
});
test('controller binding capture ignores button presses for continuous learn mode', () => {
const capture = createControllerBindingCapture({
triggerDeadzone: 0.5,
stickDeadzone: 0.2,
});
capture.arm(
{
actionId: 'leftStickHorizontal',
bindingType: 'axis',
dpadFallback: 'horizontal',
},
createSnapshot(),
);
assert.equal(
capture.poll(
createSnapshot({
buttons: [{ value: 1, pressed: true, touched: true }],
}),
),
null,
);
assert.deepEqual(capture.poll(createSnapshot({ axes: [0, 0, 0.75, 0, 0] })), {
actionId: 'leftStickHorizontal',
bindingType: 'axis',
binding: { kind: 'axis', axisIndex: 2, dpadFallback: 'horizontal' },
});
});