mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-09 16:19:25 -07:00
130 lines
3.5 KiB
TypeScript
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' },
|
|
});
|
|
});
|