Add unit tests for navigation controllers to cover pointer lock cleanup and gamepad bindings

This commit is contained in:
2026-04-27 19:34:41 +02:00
parent efefdacd67
commit a2e1a31658
2 changed files with 66 additions and 0 deletions

View File

@@ -162,6 +162,39 @@ describe("FirstPersonNavigationController", () => {
expect(exitPointerLockSpy).toHaveBeenCalledTimes(1);
});
it("clears held movement keys when pointer lock is released", () => {
const { context, domElement } = createRuntimeControllerContext();
const controller = new FirstPersonNavigationController();
let pointerLockElement: Element | null = domElement;
Object.defineProperty(document, "pointerLockElement", {
configurable: true,
get: () => pointerLockElement
});
controller.activate(context);
const controllerInternals = controller as unknown as {
pressedKeys: Set<string>;
handleKeyDown(event: KeyboardEvent): void;
handlePointerLockChange(): void;
};
controllerInternals.handleKeyDown(
new KeyboardEvent("keydown", { code: "KeyW" })
);
expect(controllerInternals.pressedKeys.has("KeyW")).toBe(true);
pointerLockElement = null;
controllerInternals.handlePointerLockChange();
expect(controllerInternals.pressedKeys.size).toBe(0);
controller.deactivate(context, {
releasePointerLock: false
});
});
it("uses authored gamepad bindings instead of the hardcoded stick mapping", () => {
const playerStart = createPlayerStartEntity({
id: "entity-player-start-custom-gamepad",

View File

@@ -142,6 +142,39 @@ describe("ThirdPersonNavigationController", () => {
controller.deactivate(context);
});
it("clears held movement keys when pointer lock is released", () => {
const { context } = createRuntimeControllerContext();
const controller = new ThirdPersonNavigationController();
let pointerLockElement: Element | null = context.domElement;
Object.defineProperty(document, "pointerLockElement", {
configurable: true,
get: () => pointerLockElement
});
controller.activate(context);
const controllerInternals = controller as unknown as {
pressedKeys: Set<string>;
handleKeyDown(event: KeyboardEvent): void;
handlePointerLockChange(): void;
};
controllerInternals.handleKeyDown(
new KeyboardEvent("keydown", { code: "ArrowUp" })
);
expect(controllerInternals.pressedKeys.has("ArrowUp")).toBe(true);
pointerLockElement = null;
controllerInternals.handlePointerLockChange();
expect(controllerInternals.pressedKeys.size).toBe(0);
controller.deactivate(context, {
releasePointerLock: false
});
});
it("uses the gamepad right stick for third-person camera orbit", () => {
const { context } = createRuntimeControllerContext();
const controller = new ThirdPersonNavigationController();