Files
slop-game-opus5.5/tests/js/settings.test.js
T
2026-09-24 17:57:54 +02:00

101 lines
3.7 KiB
JavaScript

import { describe, expect, it, vi } from 'vitest';
import { AUDIO, STORAGE_KEYS } from '../../app/static/js/config.js';
import { SafeStorage, Settings } from '../../app/static/js/systems/Settings.js';
/** Einfacher localStorage-Ersatz. */
function memoryBackend(initial = {}) {
const data = new Map(Object.entries(initial));
return {
getItem: (key) => (data.has(key) ? data.get(key) : null),
setItem: (key, value) => data.set(key, String(value)),
data,
};
}
/** localStorage, der jeden Zugriff verweigert (z. B. blockierte Website-Daten). */
const throwingBackend = {
getItem: () => {
throw new Error('SecurityError');
},
setItem: () => {
throw new Error('QuotaExceededError');
},
};
describe('SafeStorage', () => {
it('speichert JSON-Werte', () => {
const storage = new SafeStorage(memoryBackend());
expect(storage.set('a', { x: 1 })).toBe(true);
expect(storage.get('a', null)).toEqual({ x: 1 });
});
it('liefert den Standardwert bei fehlenden oder kaputten Einträgen', () => {
const storage = new SafeStorage(memoryBackend({ kaputt: '{nicht json' }));
expect(storage.get('fehlt', 42)).toBe(42);
expect(storage.get('kaputt', 'fallback')).toBe('fallback');
});
it('funktioniert ohne localStorage für die laufende Sitzung weiter', () => {
for (const backend of [null, throwingBackend]) {
const storage = new SafeStorage(backend);
expect(storage.set('k', 'v')).toBe(false);
expect(storage.get('k', null)).toBe('v');
}
});
});
describe('Settings', () => {
it('merkt sich die Disclaimer-Bestätigung', () => {
const backend = memoryBackend();
const settings = new Settings(new SafeStorage(backend));
expect(settings.isDisclaimerAccepted()).toBe(false);
settings.acceptDisclaimer();
expect(new Settings(new SafeStorage(backend)).isDisclaimerAccepted()).toBe(true);
expect(backend.data.get(STORAGE_KEYS.disclaimerAccepted)).toBe('true');
});
it('startet mit Standardlautstärken und begrenzt Werte auf 0..1', () => {
const settings = new Settings(new SafeStorage(memoryBackend()));
expect(settings.getVolume('music')).toBe(AUDIO.defaultVolumes.music);
settings.setVolume('music', 5);
expect(settings.getVolume('music')).toBe(1);
settings.setVolume('sfx', -1);
expect(settings.getVolume('sfx')).toBe(0);
settings.setVolume('sfx', Number.NaN);
expect(settings.getVolume('sfx')).toBe(0);
});
it('ignoriert ungültige gespeicherte Lautstärken', () => {
const backend = memoryBackend({ [STORAGE_KEYS.volumes]: JSON.stringify({ master: 'laut', music: 0.25, sfx: 9 }) });
const settings = new Settings(new SafeStorage(backend));
expect(settings.getVolume('master')).toBe(AUDIO.defaultVolumes.master);
expect(settings.getVolume('music')).toBe(0.25);
expect(settings.getVolume('sfx')).toBe(1);
});
it('berechnet die effektive Lautstärke inklusive Gesamtregler', () => {
const settings = new Settings(new SafeStorage(memoryBackend()));
settings.setVolume('master', 0.5);
settings.setVolume('sfx', 0.5);
expect(settings.effectiveVolume('sfx')).toBeCloseTo(0.25);
});
it('benachrichtigt Zuhörer bei Lautstärkeänderungen', () => {
const settings = new Settings(new SafeStorage(memoryBackend()));
const listener = vi.fn();
const unsubscribe = settings.onVolumeChange(listener);
settings.setVolume('master', 0.3);
expect(listener).toHaveBeenCalledWith('master', 0.3);
unsubscribe();
settings.setVolume('master', 0.4);
expect(listener).toHaveBeenCalledTimes(1);
});
it('speichert den letzten Namen gekürzt', () => {
const settings = new Settings(new SafeStorage(memoryBackend()));
settings.setLastName('A'.repeat(40));
expect(settings.getLastName()).toHaveLength(16);
});
});