go-learn/packages/board/src/input.test.ts
sab.code.lab 1c85091186 chore: восстановление репозитория из снапшота v0.3.1
Прежняя git-история утрачена при переносе проекта на машину владельца
(снапшот без .git). Хэши коммитов в docs/reports/* относятся к утраченной
истории.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 09:34:02 +02:00

79 lines
2.9 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.

/**
* Тесты редьюсера тач-ввода: вся таблица переходов.
* tap → pixelToPoint; pending/commit/cancel/перенос по контракту.
*/
import { describe, expect, it } from 'vitest';
import type { Point } from '@go-learn/core';
import { computeGeometry, pointToPixel } from './geometry.js';
import type { InputEvent, InputState } from './input.js';
import { reduceInput } from './input.js';
const geo = computeGeometry(9, 450, false);
const IDLE: InputState = { pending: null };
function tap(point: Point): InputEvent {
const { x, y } = pointToPixel(geo, point);
return { type: 'tap', px: x, py: y };
}
const A: Point = { x: 3, y: 3 };
const B: Point = { x: 5, y: 6 };
describe('reduceInput: tap', () => {
it('тап при pending=null → pending=точка, commit=null', () => {
const result = reduceInput(IDLE, tap(A), geo);
expect(result.commit).toBeNull();
expect(result.state.pending).toEqual(A);
});
it('повторный тап по той же точке → commit=точка, pending=null', () => {
const result = reduceInput({ pending: A }, tap(A), geo);
expect(result.commit).toEqual(A);
expect(result.state.pending).toBeNull();
});
it('тап по другой точке → перенос pending, commit=null', () => {
const result = reduceInput({ pending: A }, tap(B), geo);
expect(result.commit).toBeNull();
expect(result.state.pending).toEqual(B);
});
it('тап мимо доски → состояние не меняется, commit=null', () => {
const miss: InputEvent = { type: 'tap', px: -20, py: 450 + 20 };
const fromIdle = reduceInput(IDLE, miss, geo);
expect(fromIdle.state).toBe(IDLE);
expect(fromIdle.commit).toBeNull();
const withPending: InputState = { pending: A };
const fromPending = reduceInput(withPending, miss, geo);
expect(fromPending.state).toBe(withPending);
expect(fromPending.commit).toBeNull();
});
});
describe('reduceInput: confirm', () => {
it('confirm при pending → commit=pending, pending=null', () => {
const result = reduceInput({ pending: A }, { type: 'confirm' }, geo);
expect(result.commit).toEqual(A);
expect(result.state.pending).toBeNull();
});
it('confirm без pending → commit=null, pending=null', () => {
const result = reduceInput(IDLE, { type: 'confirm' }, geo);
expect(result.commit).toBeNull();
expect(result.state.pending).toBeNull();
});
});
describe('reduceInput: cancel', () => {
it('cancel при pending → сброс, commit=null', () => {
const result = reduceInput({ pending: A }, { type: 'cancel' }, geo);
expect(result.commit).toBeNull();
expect(result.state.pending).toBeNull();
});
it('cancel без pending → commit=null, pending=null', () => {
const result = reduceInput(IDLE, { type: 'cancel' }, geo);
expect(result.commit).toBeNull();
expect(result.state.pending).toBeNull();
});
});