diff --git a/src/barcode.js b/src/barcode.js index 3b4fe9b..da76898 100644 --- a/src/barcode.js +++ b/src/barcode.js @@ -6,11 +6,11 @@ import { readBarcodes, prepareZXingModule, purgeZXingModule } from 'zxing-wasm/r // hintereinander gestartete Dekodierungen dieselbe, bereits laufende // Vorbereitung, statt sie erneut anzustossen (kein Race zwischen // "noch nicht fertig" und "schon gestartet"). -let vorbereitungsPromise = null; +let readyPromise = null; async function ensureReady() { - if (!vorbereitungsPromise) { - vorbereitungsPromise = prepareZXingModule({ fireImmediately: true }).catch((error) => { + if (!readyPromise) { + readyPromise = prepareZXingModule({ fireImmediately: true }).catch((error) => { // Scheitert die Vorbereitung (z. B. WASM-Datei nicht ladbar), darf der // Adapter nicht dauerhaft unbrauchbar bleiben. zxing-wasm cacht das // fehlgeschlagene Promise intern selbst und wuerde es sonst bei jedem @@ -18,11 +18,11 @@ async function ensureReady() { // internen Cache leeren und den eigenen Merker zuruecksetzen, damit // der naechste Aufruf einen echten neuen Versuch macht. purgeZXingModule(); - vorbereitungsPromise = null; + readyPromise = null; throw error; }); } - await vorbereitungsPromise; + await readyPromise; } /** diff --git a/src/ocr.js b/src/ocr.js index f039ff1..bd5e8dd 100644 --- a/src/ocr.js +++ b/src/ocr.js @@ -5,7 +5,7 @@ import { createWorker } from 'tesseract.js'; // Aufrufe dasselbe (bereits laufende oder fertige) Laden teilen, statt es // bei jedem Aufruf neu anzustossen - Tesseract laedt Sprachdaten und WASM, // das kann auf einem Handy mehrere Sekunden dauern. Gleiches Muster wie -// vorbereitungsPromise in barcode.js. +// readyPromise in barcode.js. let workerPromise = null; // Optimistisch: Bis zum ersten Fehlschlag gilt Texterkennung als verfuegbar. diff --git a/test/pipeline.test.js b/test/pipeline.test.js index a5506a4..699e29a 100644 --- a/test/pipeline.test.js +++ b/test/pipeline.test.js @@ -11,15 +11,15 @@ const deps = ({ codes = [], text = '' }) => ({ }); test('Barcode mit bekannter Teilenummer ergibt gruen und ueberspringt OCR', async () => { - let ocrAufgerufen = false; + let ocrCalled = false; const result = await recognize({}, { decodeBarcodes: async () => ['M386A8K40BM1-CRC4Y'], - runOcr: async () => { ocrAufgerufen = true; return ''; }, + runOcr: async () => { ocrCalled = true; return ''; }, }); assert.equal(result.source, 'barcode'); assert.equal(result.confidence, 'green'); assert.equal(result.spec.capacityGb, 64); - assert.equal(ocrAufgerufen, false, 'OCR darf bei gruenem Barcode nicht laufen'); + assert.equal(ocrCalled, false, 'OCR darf bei gruenem Barcode nicht laufen'); }); test('Barcode ohne bekannte Teilenummer faellt auf OCR zurueck', async () => { @@ -93,7 +93,7 @@ test('decodeBarcodes liefert ein Objekt statt einer Liste, kein Absturz', async test('runOcr liefert keine Zeichenkette, wird wie leerer Text behandelt', async () => { const result = await recognize({}, { decodeBarcodes: async () => [], - runOcr: async () => ({ unerwartet: true }), + runOcr: async () => ({ unexpected: true }), }); assert.equal(result.source, 'none'); assert.equal(result.confidence, 'red'); @@ -102,27 +102,27 @@ test('runOcr liefert keine Zeichenkette, wird wie leerer Text behandelt', async // --- Beanstandung 2: mehrere verwertbare Barcodes im selben Bild --- test('mehrere unvertraegliche Barcodes ergeben rot statt eines ungeprueften ersten Treffers', async () => { - let ocrAufgerufen = false; + let ocrCalled = false; const result = await recognize({}, { // Gleiche Bauform und Dichte, aber widersprechende Geschwindigkeit: // zwei unterschiedliche Module im selben Bild. decodeBarcodes: async () => ['M386A8K40BM1-CRC4Y', 'M386A8K40BM1-CWE4Y'], - runOcr: async () => { ocrAufgerufen = true; return ''; }, + runOcr: async () => { ocrCalled = true; return ''; }, }); assert.equal(result.source, 'none'); assert.equal(result.confidence, 'red'); assert.deepEqual(result.spec, emptySpec()); - assert.equal(ocrAufgerufen, false, 'bei mehrdeutigem Barcode-Ergebnis soll nicht geraten werden'); + assert.equal(ocrCalled, false, 'bei mehrdeutigem Barcode-Ergebnis soll nicht geraten werden'); }); test('mehrere untereinander vertraegliche Barcodes ergeben gruen (der erste Treffer entscheidet, es gibt nichts zusammenzufuehren)', async () => { - let ocrAufgerufen = false; + let ocrCalled = false; const result = await recognize({}, { // Zwei Lesungen desselben Etiketts (z.B. Mehrfachtreffer durch // Spiegelung) - inhaltlich identisch, nur die Schreibweise weicht // an einer verwechslungstoleranten Stelle ab (B/8). decodeBarcodes: async () => ['M386A8K40BM1-CRC4Y', 'M386A8K408M1-CRC4Y'], - runOcr: async () => { ocrAufgerufen = true; return ''; }, + runOcr: async () => { ocrCalled = true; return ''; }, }); assert.equal(result.source, 'barcode'); assert.equal(result.confidence, 'green'); @@ -130,7 +130,7 @@ test('mehrere untereinander vertraegliche Barcodes ergeben gruen (der erste Tref assert.equal(result.spec.formFactor, 'LRDIMM'); assert.equal(result.spec.rank, '4DRx4'); assert.equal(result.spec.speed, 'PC4-2400'); - assert.equal(ocrAufgerufen, false, 'OCR darf bei gruenem Mehrfachtreffer nicht laufen'); + assert.equal(ocrCalled, false, 'OCR darf bei gruenem Mehrfachtreffer nicht laufen'); }); // --- Beanstandung 1: haengender Adapter darf die Erkennung nicht dauerhaft blockieren --- diff --git a/test/session.test.js b/test/session.test.js index dd9b82f..093ec30 100644 --- a/test/session.test.js +++ b/test/session.test.js @@ -40,8 +40,8 @@ test('anderes Modul legt Stapel B an', () => { test('eine Verwechslung erzeugt keinen Fast-Duplikat-Stapel', () => { const session = createSession(); scan(session, s64()); - const verrauscht = { ...s64(), partNumber: 'M386A8K4OBM1-CRC4Y' }; - const plan = proposeAssignment(session, verrauscht); + const noisy = { ...s64(), partNumber: 'M386A8K4OBM1-CRC4Y' }; + const plan = proposeAssignment(session, noisy); assert.equal(plan.kind, 'match'); assert.equal(plan.stackId, 'A'); }); @@ -50,8 +50,8 @@ test('Scan ohne Teilenummer bei zwei passenden Stapeln ist mehrdeutig', () => { const session = createSession(); scan(session, { ...s64(), partNumber: 'M386A8K40BM1-CRC4Y' }); scan(session, { ...s64(), partNumber: 'HMAA8GL7AMR4N-UH' }); - const ohnePn = { ...s64(), partNumber: null }; - const plan = proposeAssignment(session, ohnePn); + const withoutPartNumber = { ...s64(), partNumber: null }; + const plan = proposeAssignment(session, withoutPartNumber); assert.equal(plan.kind, 'ambiguous'); assert.deepEqual(plan.candidates, ['A', 'B']); }); @@ -69,8 +69,8 @@ test('undoLast nimmt den letzten Eintrag zurueck', () => { const session = createSession(); scan(session, s64()); scan(session, s64()); - const entfernt = undoLast(session); - assert.equal(entfernt.stackId, 'A'); + const removed = undoLast(session); + assert.equal(removed.stackId, 'A'); assert.equal(session.stacks[0].count, 1); assert.equal(session.entries.length, 1); }); @@ -88,10 +88,10 @@ test('moveEntry sortiert einen Eintrag um', () => { const a = scan(session, s64()); scan(session, s32()); moveEntry(session, a.entryId, 'B'); - const stapelA = session.stacks.find((s) => s.id === 'A'); - const stapelB = session.stacks.find((s) => s.id === 'B'); - assert.equal(stapelA, undefined, 'leerer Stapel wird entfernt'); - assert.equal(stapelB.count, 2); + const stackA = session.stacks.find((s) => s.id === 'A'); + const stackB = session.stacks.find((s) => s.id === 'B'); + assert.equal(stackA, undefined, 'leerer Stapel wird entfernt'); + assert.equal(stackB.count, 2); }); test('removeEntry entfernt einen einzelnen Eintrag', () => { @@ -105,15 +105,15 @@ test('removeEntry entfernt einen einzelnen Eintrag', () => { test('Ergaenzung des Stapel-Specs veraendert nicht das Spec eines frueheren Eintrags', () => { const session = createSession(); - const unvollstaendig = { ...s64(), partNumber: null }; - const entry1 = scan(session, unvollstaendig); + const incomplete = { ...s64(), partNumber: null }; + const entry1 = scan(session, incomplete); const stack = session.stacks.find((s) => s.id === entry1.stackId); assert.notEqual(stack.spec, entry1.spec, 'Stapel-Spec und Eintrags-Spec duerfen kein gemeinsames Objekt sein'); assert.deepEqual(stack.spec, entry1.spec, 'inhaltlich sind beide Specs zunaechst gleich'); assert.equal(entry1.spec.partNumber, null); - const vollstaendiger = s64(); - scan(session, vollstaendiger); + const complete = s64(); + scan(session, complete); assert.equal(entry1.spec.partNumber, null, 'das Spec des ersten Eintrags darf durch eine spaetere Ergaenzung des Stapel-Specs nicht veraendert werden'); assert.equal(stack.spec.partNumber, 'M386A8K40BM1-CRC4Y'); @@ -121,13 +121,13 @@ test('Ergaenzung des Stapel-Specs veraendert nicht das Spec eines frueheren Eint test('moveEntry legt fuer einen neuen Stapel eine eigene Kopie des Specs an', () => { const session = createSession(); - const unvollstaendig = { ...s32(), partNumber: null }; - const a = scan(session, unvollstaendig); + const incomplete = { ...s32(), partNumber: null }; + const a = scan(session, incomplete); moveEntry(session, a.entryId, 'Z'); - const stapelZ = session.stacks.find((s) => s.id === 'Z'); - assert.notEqual(stapelZ.spec, a.spec, 'Stapel-Spec und Eintrags-Spec duerfen kein gemeinsames Objekt sein'); + const stackZ = session.stacks.find((s) => s.id === 'Z'); + assert.notEqual(stackZ.spec, a.spec, 'Stapel-Spec und Eintrags-Spec duerfen kein gemeinsames Objekt sein'); - stapelZ.spec.partNumber = 'M393A4K40BB1-CTD'; + stackZ.spec.partNumber = 'M393A4K40BB1-CTD'; assert.equal(a.spec.partNumber, null, 'eine Ergaenzung des neu angelegten Stapel-Specs darf das Eintrags-Spec nicht veraendern'); }); @@ -149,9 +149,9 @@ test('ein Stapel mit nur der Kapazitaet ist Kandidat fuer ein Modul gleicher Kap test('ein voellig unerkanntes Modul erzeugt einen eigenen Stapel und zieht keine weiteren an sich', () => { const session = createSession(); - const erster = scan(session, emptySpec()); - const zweiter = scan(session, emptySpec()); - assert.notEqual(erster.stackId, zweiter.stackId, 'zwei unerkannte Module ohne gemeinsame Grundlage teilen sich keinen Stapel'); + const first = scan(session, emptySpec()); + const second = scan(session, emptySpec()); + assert.notEqual(first.stackId, second.stackId, 'zwei unerkannte Module ohne gemeinsame Grundlage teilen sich keinen Stapel'); assert.equal(session.stacks.length, 2); const plan = proposeAssignment(session, s64()); @@ -164,13 +164,13 @@ test('undoLast-Vertrag: nach einem Umsortieren wird weiterhin der zuletzt erfass const b = scan(session, s32()); moveEntry(session, a.entryId, 'B'); // Zuletzt ausgefuehrte Handlung war das Umsortieren von a; zuletzt erfasst wurde jedoch b. - const entfernt = undoLast(session); - assert.equal(entfernt.entryId, b.entryId, 'undoLast nimmt den zuletzt erfassten Eintrag zurueck, nicht die zuletzt ausgefuehrte Handlung (das Umsortieren)'); + const removed = undoLast(session); + assert.equal(removed.entryId, b.entryId, 'undoLast nimmt den zuletzt erfassten Eintrag zurueck, nicht die zuletzt ausgefuehrte Handlung (das Umsortieren)'); assert.equal(session.entries.length, 1); assert.equal(session.entries[0].entryId, a.entryId); assert.equal(session.entries[0].stackId, 'B', 'das Umsortieren von a bleibt von der Rueckname des unbeteiligten Eintrags b unberuehrt'); - const stapelA = session.stacks.find((s) => s.id === 'A'); - const stapelB = session.stacks.find((s) => s.id === 'B'); - assert.equal(stapelA, undefined, 'Stapel A ist seit dem Umsortieren leer und wurde bereits entfernt'); - assert.equal(stapelB.count, 1, 'Stapel B enthaelt weiterhin a, nur b wurde zurueckgenommen'); + const stackA = session.stacks.find((s) => s.id === 'A'); + const stackB = session.stacks.find((s) => s.id === 'B'); + assert.equal(stackA, undefined, 'Stapel A ist seit dem Umsortieren leer und wurde bereits entfernt'); + assert.equal(stackB.count, 1, 'Stapel B enthaelt weiterhin a, nur b wurde zurueckgenommen'); }); diff --git a/test/spec-match.test.js b/test/spec-match.test.js index fc86f22..ac388ce 100644 --- a/test/spec-match.test.js +++ b/test/spec-match.test.js @@ -34,9 +34,9 @@ test('matchKnown funktioniert auch mit Zahlenlisten', () => { }); test('specsCompatible vergleicht nur beidseitig gesetzte Felder', () => { - const voll = { capacityGb: 64, formFactor: 'LRDIMM', rank: '4DRx4', speed: 'PC4-2400', partNumber: 'M386A8K40BM1-CRC4Y', dateCode: '1908' }; - const ohnePn = { ...voll, partNumber: null, dateCode: null }; - assert.equal(specsCompatible(voll, ohnePn), true); + const full = { capacityGb: 64, formFactor: 'LRDIMM', rank: '4DRx4', speed: 'PC4-2400', partNumber: 'M386A8K40BM1-CRC4Y', dateCode: '1908' }; + const withoutPartNumber = { ...full, partNumber: null, dateCode: null }; + assert.equal(specsCompatible(full, withoutPartNumber), true); }); test('specsCompatible erkennt einen echten Unterschied', () => {