Files
ocr_scanner/test/storage.test.js
T
vchuserandClaude Opus 5 4b2553d4f4 Rename deutsche Testbezeichner und ergaenze Mehrstapel-Testabdeckung
test/storage.test.js: wieder -> reloaded, kaputt -> broken, zweiterEintrag
-> secondEntry, vorschlag -> proposal (Bezeichner, nicht die deutschen
Testbeschreibungen).

Neuer Test deckt die bislang nur mit einem einzigen Stapel geprueften
Stapelzaehler-Neuberechnung beim Laden ab: drei gespeicherte Stapel mit
absichtlich falschem count, davon einer (C) ganz ohne zugeordnete
Eintraege - alle drei muessen unabhaengig voneinander korrekt aus den
tatsaechlichen Eintraegen neu berechnet werden (A=2, B=1, C=0).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 18:24:43 +02:00

256 lines
8.2 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { saveSession, loadSession, clearSession } from '../src/storage.js';
import {
createSession,
commitAssignment,
proposeAssignment,
moveEntry,
removeEntry,
} from '../src/session.js';
import { emptySpec } from '../src/spec.js';
function fakeStore() {
const data = new Map();
return {
data,
getItem: (key) => (data.has(key) ? data.get(key) : null),
setItem: (key, value) => data.set(key, value),
removeItem: (key) => data.delete(key),
};
}
test('leerer Speicher liefert null', () => {
assert.equal(loadSession(fakeStore()), null);
});
test('Sitzung ueberlebt Sichern und Laden', () => {
const store = fakeStore();
const session = createSession();
commitAssignment(session, { ...emptySpec(), capacityGb: 64 }, 'barcode', 'A');
saveSession(session, store);
const reloaded = loadSession(store);
assert.equal(reloaded.stacks.length, 1);
assert.equal(reloaded.stacks[0].count, 1);
assert.equal(reloaded.entries[0].spec.capacityGb, 64);
assert.equal(reloaded.nextEntryId, 2);
});
test('clearSession raeumt auf', () => {
const store = fakeStore();
saveSession(createSession(), store);
clearSession(store);
assert.equal(loadSession(store), null);
});
test('kaputter Inhalt liefert null statt einer Ausnahme', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', '{kein json');
assert.equal(loadSession(store), null);
});
test('Sichern ohne funktionierenden Speicher wirft nicht', () => {
const broken = {
getItem: () => null,
setItem: () => { throw new Error('quota exceeded'); },
removeItem: () => {},
};
assert.doesNotThrow(() => saveSession(createSession(), broken));
});
test('stacks mit Nicht-Objekten liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: ['x', 'y'],
entries: [],
nextEntryId: 1,
}));
assert.equal(loadSession(store), null);
});
test('fehlender nextEntryId liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [],
}));
assert.equal(loadSession(store), null);
});
test('nextEntryId als Zeichenkette liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [],
nextEntryId: '2',
}));
assert.equal(loadSession(store), null);
});
test('Stapel mit Zaehler als Zeichenkette liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [{ id: 'A', count: '3', spec: emptySpec() }],
entries: [],
nextEntryId: 1,
}));
assert.equal(loadSession(store), null);
});
test('Eintrag ohne Spec liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [{ entryId: 1, stackId: 'A' }],
nextEntryId: 2,
}));
assert.equal(loadSession(store), null);
});
test('Stapelzaehler wird beim Laden aus den Eintraegen neu berechnet', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [{ id: 'A', count: 5, spec: emptySpec() }],
entries: [{ entryId: 1, stackId: 'A', spec: emptySpec(), source: 'barcode' }],
nextEntryId: 2,
}));
const reloaded = loadSession(store);
assert.notEqual(reloaded, null);
assert.equal(reloaded.stacks[0].count, 1);
});
test('Stapelzaehler werden beim Laden fuer mehrere Stapel unabhaengig neu berechnet, auch fuer einen ohne Eintraege', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [
{ id: 'A', count: 99, spec: emptySpec() },
{ id: 'B', count: 99, spec: emptySpec() },
{ id: 'C', count: 99, spec: emptySpec() },
],
entries: [
{ entryId: 1, stackId: 'A', spec: emptySpec(), source: 'barcode' },
{ entryId: 2, stackId: 'A', spec: emptySpec(), source: 'barcode' },
{ entryId: 3, stackId: 'B', spec: emptySpec(), source: 'ocr' },
],
nextEntryId: 4,
}));
const reloaded = loadSession(store);
assert.notEqual(reloaded, null);
assert.equal(reloaded.stacks.find((s) => s.id === 'A').count, 2, 'Stapel A hat zwei zugeordnete Eintraege');
assert.equal(reloaded.stacks.find((s) => s.id === 'B').count, 1, 'Stapel B hat einen zugeordneten Eintrag');
assert.equal(reloaded.stacks.find((s) => s.id === 'C').count, 0, 'Stapel C ohne jeden Eintrag wird auf 0 neu berechnet, nicht auf den gespeicherten Wert');
});
test('Eintrag mit unbekannter Stapelkennung liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [{ entryId: 1, stackId: 'Z', spec: emptySpec(), source: 'barcode' }],
nextEntryId: 2,
}));
assert.equal(loadSession(store), null);
});
test('doppelte Eintragsnummern liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [{ id: 'A', count: 2, spec: emptySpec() }],
entries: [
{ entryId: 1, stackId: 'A', spec: emptySpec(), source: 'barcode' },
{ entryId: 1, stackId: 'A', spec: emptySpec(), source: 'barcode' },
],
nextEntryId: 2,
}));
assert.equal(loadSession(store), null);
});
test('doppelte Stapelkennungen liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [
{ id: 'A', count: 0, spec: emptySpec() },
{ id: 'A', count: 0, spec: emptySpec() },
],
entries: [],
nextEntryId: 1,
}));
assert.equal(loadSession(store), null);
});
test('nextEntryId nicht groesser als vorhandene Eintragsnummer liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [{ id: 'A', count: 1, spec: emptySpec() }],
entries: [{ entryId: 5, stackId: 'A', spec: emptySpec(), source: 'barcode' }],
nextEntryId: 5,
}));
assert.equal(loadSession(store), null);
});
test('nach Sichern und Laden funktioniert Weiterarbeiten weiterhin', () => {
const store = fakeStore();
const session = createSession();
const spec = { ...emptySpec(), capacityGb: 64 };
commitAssignment(session, spec, 'barcode', 'A');
const secondEntry = commitAssignment(session, spec, 'barcode', 'A');
saveSession(session, store);
const reloaded = loadSession(store);
const proposal = proposeAssignment(reloaded, spec);
assert.equal(proposal.kind, 'match');
assert.equal(proposal.stackId, 'A');
commitAssignment(reloaded, spec, 'barcode', proposal.stackId);
assert.equal(reloaded.stacks[0].count, 3);
assert.equal(reloaded.nextEntryId, 4);
moveEntry(reloaded, secondEntry.entryId, 'B');
assert.equal(reloaded.stacks.find((s) => s.id === 'A').count, 2);
assert.equal(reloaded.stacks.find((s) => s.id === 'B').count, 1);
removeEntry(reloaded, secondEntry.entryId);
assert.equal(reloaded.entries.find((e) => e.entryId === secondEntry.entryId), undefined);
assert.equal(reloaded.stacks.find((s) => s.id === 'B'), undefined);
});
test('nextEntryId als negative Zahl liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [],
nextEntryId: -5,
}));
assert.equal(loadSession(store), null);
});
test('nextEntryId als gebrochene Zahl liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [],
nextEntryId: 1.5,
}));
assert.equal(loadSession(store), null);
});
test('nextEntryId als Null liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [],
entries: [],
nextEntryId: 0,
}));
assert.equal(loadSession(store), null);
});
test('Eintrag mit gebrochener entryId liefert null', () => {
const store = fakeStore();
store.setItem('ram-sortierhilfe:session', JSON.stringify({
stacks: [{ id: 'A', count: 1, spec: emptySpec() }],
entries: [{ entryId: 1.5, stackId: 'A', spec: emptySpec(), source: 'barcode' }],
nextEntryId: 2,
}));
assert.equal(loadSession(store), null);
});