Erzwinge innere Stimmigkeit in loadSession statt nur Typprüfung
Stapelzähler wird beim Laden immer aus den zugeordneten Einträgen neu berechnet statt aus dem gespeicherten Wert übernommen. Zusätzlich wird verworfen (null): Einträge mit unbekannter Stapelkennung, doppelte Eintragsnummern, doppelte Stapelkennungen und ein nextEntryId, der nicht größer als jede vorhandene Eintragsnummer ist. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,15 @@ function isUsableEntry(entry) {
|
||||
* zurueckgegeben. Ein halb brauchbarer Zustand wird nicht repariert oder
|
||||
* teilweise uebernommen - dann lieber die Sitzung verlieren (null) als mit
|
||||
* falschen Zaehlern oder doppelten entryIds lautlos weiterarbeiten.
|
||||
*
|
||||
* Der gespeicherte Stapelzaehler (stack.count) wird nie uebernommen, sondern
|
||||
* beim Laden stets aus der Zahl der ihm tatsaechlich zugeordneten Eintraege
|
||||
* neu berechnet - er dient in isUsableStack nur noch dazu, grob kaputten
|
||||
* Inhalt schon an der Typprueung scheitern zu lassen. Zeigt ein Eintrag auf
|
||||
* eine Stapelkennung, die es nicht gibt, kommt eine Eintragsnummer oder eine
|
||||
* Stapelkennung mehrfach vor, oder ist nextEntryId nicht groesser als jede
|
||||
* vorhandene Eintragsnummer, ist der Inhalt in sich unstimmig und wird
|
||||
* komplett verworfen (null) statt lautlos falsch weiterverwendet zu werden.
|
||||
*/
|
||||
export function loadSession(store) {
|
||||
try {
|
||||
@@ -59,6 +68,22 @@ export function loadSession(store) {
|
||||
if (!isFiniteNumber(parsed.nextEntryId)) return null;
|
||||
if (!parsed.stacks.every(isUsableStack)) return null;
|
||||
if (!parsed.entries.every(isUsableEntry)) return null;
|
||||
|
||||
const stackIds = parsed.stacks.map((stack) => stack.id);
|
||||
if (new Set(stackIds).size !== stackIds.length) return null;
|
||||
|
||||
const entryIds = parsed.entries.map((entry) => entry.entryId);
|
||||
if (new Set(entryIds).size !== entryIds.length) return null;
|
||||
|
||||
const stackIdSet = new Set(stackIds);
|
||||
if (!parsed.entries.every((entry) => stackIdSet.has(entry.stackId))) return null;
|
||||
|
||||
if (entryIds.some((entryId) => entryId >= parsed.nextEntryId)) return null;
|
||||
|
||||
for (const stack of parsed.stacks) {
|
||||
stack.count = parsed.entries.filter((entry) => entry.stackId === stack.id).length;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
} catch {
|
||||
return null;
|
||||
|
||||
@@ -108,6 +108,64 @@ test('Eintrag ohne Spec liefert null', () => {
|
||||
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 wieder = loadSession(store);
|
||||
assert.notEqual(wieder, null);
|
||||
assert.equal(wieder.stacks[0].count, 1);
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user