Reines Funktionen-Modul fuer die drei Scan-Funktionen
Kennung, deutsche Beschriftung, Codearten, laufende Suche und Texterkennung je Funktion an einer einzigen Stelle (src/scan-modes.js), ohne Browser-Zugriff und damit unter Node pruefbar. Funktion "QR-Code" enthaelt bewusst kein DataMatrix.
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
// Die drei Scan-Funktionen, die der Nutzer vor dem Scannen waehlt. Reines
|
||||||
|
// Modul ohne Browser-Zugriff (kein window/document/navigator) - einzige
|
||||||
|
// Quelle fuer Kennung, Beschriftung, Codearten und Verhalten je Funktion.
|
||||||
|
// Sowohl die Auswahl-Oberflaeche als auch main.js lesen ausschliesslich von
|
||||||
|
// hier - es darf keine zweite Stelle geben, an der Codearten oder
|
||||||
|
// Beschriftungen stehen.
|
||||||
|
//
|
||||||
|
// Ausdrueckliche Entscheidung des Auftraggebers (nicht abaendern): Funktion 2
|
||||||
|
// liest streng nur QR (QRCode, MicroQRCode, RMQRCode) - kein DataMatrix, auch
|
||||||
|
// wenn die 2D-Codes auf den eigenen RAM-Etiketten DataMatrix sind. Der
|
||||||
|
// Arbeitsablauf des Auftraggebers laeuft ueber Funktion 1 (Teilenummer im
|
||||||
|
// Strichcode); Funktion 2 dient anderer Ware.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} ScanMode
|
||||||
|
* @property {string} id Kennung, intern verwendet (main.js, Speicherung der Wahl).
|
||||||
|
* @property {string} label Deutsche Beschriftung fuer die Oberflaeche.
|
||||||
|
* @property {string[]} barcodeFormats An decodeBarcodes() zu uebergebende
|
||||||
|
* Codearten (zxing-wasm-Formatnamen). Leer, wenn die Funktion keine
|
||||||
|
* Barcode-Dekodierung nutzt.
|
||||||
|
* @property {boolean} continuousSearch Ob waehrend die Kamera laeuft
|
||||||
|
* fortwaehrend nach Codes gesucht wird (statt nur auf Knopfdruck).
|
||||||
|
* @property {boolean} useOcr Ob die Texterkennung (Tesseract) genutzt wird.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {ScanMode[]} */
|
||||||
|
export const SCAN_MODES = [
|
||||||
|
{
|
||||||
|
id: 'barcode',
|
||||||
|
label: 'Strichcode',
|
||||||
|
// Eindimensionale Codes, wie sie auf Teilenummern-Etiketten vorkommen.
|
||||||
|
barcodeFormats: ['Code128', 'Code39', 'Code93', 'ITF', 'EAN13', 'EAN8', 'UPCA', 'UPCE', 'Codabar'],
|
||||||
|
continuousSearch: true,
|
||||||
|
useOcr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'qrcode',
|
||||||
|
label: 'QR-Code',
|
||||||
|
// Ausschliesslich QR-Varianten - bewusst kein DataMatrix, siehe Kommentar oben.
|
||||||
|
barcodeFormats: ['QRCode', 'MicroQRCode', 'RMQRCode'],
|
||||||
|
continuousSearch: true,
|
||||||
|
useOcr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ocr',
|
||||||
|
label: 'Text erkennen',
|
||||||
|
// Keine Codes - allein die Texterkennung, auf Knopfdruck.
|
||||||
|
barcodeFormats: [],
|
||||||
|
continuousSearch: false,
|
||||||
|
useOcr: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert die Funktion zu einer Kennung.
|
||||||
|
* @param {string} id
|
||||||
|
* @returns {ScanMode}
|
||||||
|
* @throws {Error} wenn die Kennung keiner der drei Funktionen entspricht -
|
||||||
|
* ein Programmfehler (main.js darf nie eine fremde Kennung durchreichen),
|
||||||
|
* kein regulaerer Ausgang.
|
||||||
|
*/
|
||||||
|
export function getScanMode(id) {
|
||||||
|
const mode = SCAN_MODES.find((candidate) => candidate.id === id);
|
||||||
|
if (!mode) {
|
||||||
|
throw new Error(`Unbekannte Scan-Funktion: ${id}`);
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { test } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { SCAN_MODES, getScanMode } from '../src/scan-modes.js';
|
||||||
|
|
||||||
|
test('genau drei Funktionen in fester Reihenfolge', () => {
|
||||||
|
assert.equal(SCAN_MODES.length, 3);
|
||||||
|
assert.deepEqual(SCAN_MODES.map((mode) => mode.id), ['barcode', 'qrcode', 'ocr']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 1 (Strichcode): eindimensionale Codearten, laufende Suche, keine Texterkennung', () => {
|
||||||
|
const mode = getScanMode('barcode');
|
||||||
|
assert.equal(mode.label, 'Strichcode');
|
||||||
|
assert.deepEqual(mode.barcodeFormats, [
|
||||||
|
'Code128', 'Code39', 'Code93', 'ITF', 'EAN13', 'EAN8', 'UPCA', 'UPCE', 'Codabar',
|
||||||
|
]);
|
||||||
|
assert.equal(mode.continuousSearch, true);
|
||||||
|
assert.equal(mode.useOcr, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 2 (QR-Code): ausschliesslich QR-Varianten, kein DataMatrix', () => {
|
||||||
|
const mode = getScanMode('qrcode');
|
||||||
|
assert.equal(mode.label, 'QR-Code');
|
||||||
|
assert.deepEqual(mode.barcodeFormats, ['QRCode', 'MicroQRCode', 'RMQRCode']);
|
||||||
|
assert.ok(!mode.barcodeFormats.includes('DataMatrix'), 'Funktion 2 darf kein DataMatrix lesen');
|
||||||
|
assert.equal(mode.continuousSearch, true);
|
||||||
|
assert.equal(mode.useOcr, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 3 (Text erkennen): keine Codearten, keine laufende Suche, Texterkennung', () => {
|
||||||
|
const mode = getScanMode('ocr');
|
||||||
|
assert.equal(mode.label, 'Text erkennen');
|
||||||
|
assert.deepEqual(mode.barcodeFormats, []);
|
||||||
|
assert.equal(mode.continuousSearch, false);
|
||||||
|
assert.equal(mode.useOcr, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('unbekannte Kennung wirft statt undefined zurueckzugeben', () => {
|
||||||
|
assert.throws(() => getScanMode('unbekannt'));
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user