127 lines
4.5 KiB
JavaScript
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);
|
|
});
|
|
});
|