Files
2026-09-24 17:57:54 +02:00

127 lines
4.5 KiB
JavaScript

import { describe, expect, it } from 'vitest';
import { ORBITAL } from '../../app/static/js/config.js';
import {
codeToDirection,
ComboInput,
isPrefix,
validateCommands,
} from '../../app/static/js/logic/comboInput.js';
const COMMANDS = [
{ id: 'strike', sequence: ['up', 'right', 'down', 'down'] },
{ id: 'supply', sequence: ['down', 'down', 'up', 'right'] },
{ id: 'turret', sequence: ['down', 'up', 'right', 'right', 'up'] },
];
const typeAll = (combo, dirs) => dirs.map((d) => combo.push(d));
describe('codeToDirection', () => {
it('bildet Pfeiltasten und WASD (physische Position) ab', () => {
expect(codeToDirection('ArrowUp')).toBe('up');
expect(codeToDirection('KeyW')).toBe('up');
expect(codeToDirection('KeyA')).toBe('left');
expect(codeToDirection('ArrowRight')).toBe('right');
expect(codeToDirection('KeyS')).toBe('down');
expect(codeToDirection('KeyQ')).toBeNull();
});
});
describe('isPrefix', () => {
it('erkennt Anfänge von Folgen', () => {
expect(isPrefix([], ['up'])).toBe(true);
expect(isPrefix(['up'], ['up', 'down'])).toBe(true);
expect(isPrefix(['down'], ['up', 'down'])).toBe(false);
expect(isPrefix(['up', 'down', 'up'], ['up', 'down'])).toBe(false);
});
});
describe('validateCommands', () => {
it('akzeptiert die Befehle aus der Konfiguration', () => {
expect(() => validateCommands(ORBITAL.commands)).not.toThrow();
});
it('lehnt Folgen ab, die Anfang einer anderen sind', () => {
expect(() =>
validateCommands([
{ id: 'a', sequence: ['up', 'down'] },
{ id: 'b', sequence: ['up', 'down', 'left'] },
]),
).toThrow(/Anfang/);
});
it('lehnt doppelte IDs, leere Folgen und unbekannte Richtungen ab', () => {
expect(() => validateCommands([{ id: 'a', sequence: ['up'] }, { id: 'a', sequence: ['down'] }])).toThrow();
expect(() => validateCommands([{ id: 'a', sequence: [] }])).toThrow();
expect(() => validateCommands([{ id: 'a', sequence: ['oben'] }])).toThrow();
});
});
describe('ComboInput', () => {
it('ignoriert Eingaben, solange die Halte-Taste nicht gedrückt ist', () => {
const combo = new ComboInput(COMMANDS);
expect(combo.push('up').status).toBe('inactive');
});
it('erkennt eine vollständige Folge', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
const results = typeAll(combo, ['up', 'right', 'down', 'down']);
expect(results.slice(0, 3).map((r) => r.status)).toEqual(['progress', 'progress', 'progress']);
expect(results[3]).toEqual({ status: 'match', commandId: 'strike' });
expect(combo.buffer).toEqual([]);
});
it('meldet passende Kandidaten während der Eingabe', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
expect(combo.push('down')).toEqual({ status: 'progress', candidates: ['supply', 'turret'] });
expect(combo.push('up')).toEqual({ status: 'progress', candidates: ['turret'] });
});
it('meldet Fehleingaben und erlaubt direkt einen neuen Versuch', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
combo.push('up');
expect(combo.push('up').status).toBe('fail');
expect(combo.buffer).toEqual([]);
const retry = typeAll(combo, ['down', 'down', 'up', 'right']);
expect(retry.at(-1)).toEqual({ status: 'match', commandId: 'supply' });
});
it('erlaubt mehrere Befehle hintereinander, solange die Taste gehalten wird', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
expect(typeAll(combo, ['up', 'right', 'down', 'down']).at(-1).commandId).toBe('strike');
expect(typeAll(combo, ['down', 'up', 'right', 'right', 'up']).at(-1).commandId).toBe('turret');
});
it('verwirft halbe Eingaben beim Loslassen', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
typeAll(combo, ['up', 'right']);
combo.end();
combo.begin();
expect(combo.push('down').status).toBe('progress');
expect(combo.buffer).toEqual(['down']);
});
it('ignoriert unbekannte Richtungen ohne den Puffer zu verändern', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
combo.push('up');
expect(combo.push('diagonal').status).toBe('ignored');
expect(combo.buffer).toEqual(['up']);
});
it('zeigt den Fortschritt je Befehl für das HUD', () => {
const combo = new ComboInput(COMMANDS);
combo.begin();
typeAll(combo, ['down', 'down']);
expect(combo.progressFor('supply')).toBe(2);
expect(combo.progressFor('turret')).toBe(0);
expect(combo.progressFor('strike')).toBe(0);
expect(combo.progressFor('unbekannt')).toBe(0);
});
});