diff --git a/src/frontend/flask_app/static/js/vision_overlay.js b/src/frontend/flask_app/static/js/vision_overlay.js index 6b2b648..fbbd873 100644 --- a/src/frontend/flask_app/static/js/vision_overlay.js +++ b/src/frontend/flask_app/static/js/vision_overlay.js @@ -249,15 +249,15 @@ var VisionOverlay = (function () { var pt = null; for (var i = 0; i < order.length && !pt; i++) pt = anchor(order[i]); if (!pt) return; - // #118: valore null/undefined/vuoto = quota non misurata (Number(null) e' 0): nessuna etichetta - if (r.value === null || r.value === undefined || r.value === '' || typeof r.value === 'boolean') return; - var v = Number(r.value); - if (!isFinite(v)) return; + // #118: valore null/undefined/vuoto/non finito = quota non misurata (Number(null) e' 0): etichetta NaN, status della riga (fail) + var v = (r.value === null || r.value === undefined || r.value === '' || typeof r.value === 'boolean') + ? NaN : Number(r.value); + var txt = isFinite(v) ? v.toFixed(3) : 'NaN'; out.push({ key: r.key, x: pt.x, y: pt.y, - text: r.name + ' ' + v.toFixed(3) + ' ' + (r.unit || ''), + text: r.name + ' ' + txt + ' ' + (r.unit || ''), status: r.status, }); }); diff --git a/src/frontend/flask_app/tests/js/test_vision_overlay.js b/src/frontend/flask_app/tests/js/test_vision_overlay.js index 63f7f54..ccb944e 100644 --- a/src/frontend/flask_app/tests/js/test_vision_overlay.js +++ b/src/frontend/flask_app/tests/js/test_vision_overlay.js @@ -224,17 +224,18 @@ const rows = fixture.measurements.map((m) => { check('labels: testo name + valore a 3 decimali + unit', f[0].text === 'T 1.500 mm', f[0].text); } -// --- #118: labels, valore null/undefined/non finito -> nessuna etichetta --- +// --- #118: labels, valore null/undefined/non finito -> etichetta NaN con status della riga --- { const ov = [{ type: 'segment', role: 'found', tool_id: 't', row1: 10, col1: 10, row2: 10, col2: 20 }]; const mk = (value) => ({ key: 1, name: 'T', value, unit: 'mm', status: 'fail', vision_output: 't.value' }); - check('labels: value null -> nessuna etichetta (Number(null) e\' 0)', VisionOverlay.labels([mk(null)], ov).length === 0); - check('labels: value undefined -> nessuna', VisionOverlay.labels([mk(undefined)], ov).length === 0); - check('labels: value NaN/Infinity -> nessuna', - VisionOverlay.labels([mk(NaN), mk(Infinity), mk(-Infinity)], ov).length === 0); - check('labels: value 0 resta un valore valido', VisionOverlay.labels([mk(0)], ov).length === 1); + const nan = (v) => { const l = VisionOverlay.labels([mk(v)], ov); return l.length === 1 && l[0].text === 'T NaN mm' && l[0].status === 'fail'; }; + check('labels: value null -> etichetta NaN, status fail (Number(null) e 0)', nan(null)); + check('labels: value undefined / stringa vuota -> etichetta NaN', nan(undefined) && nan('')); + check('labels: value NaN/Infinity -> etichetta NaN', nan(NaN) && nan(Infinity) && nan(-Infinity)); + check('labels: value 0 resta un valore valido', VisionOverlay.labels([mk(0)], ov)[0].text === 'T 0.000 mm'); const misto = VisionOverlay.labels([{ ...mk(null), key: 1 }, { ...mk(2.5), key: 2 }], ov); - check('labels: null saltata, le altre righe restano', misto.length === 1 && misto[0].key === 2); + check('labels: null e valida entrambe presenti', misto.length === 2 && misto[0].text === 'T NaN mm' && misto[1].key === 2); + check('labels: riga NaN senza ancoraggio -> nessuna etichetta', VisionOverlay.labels([mk(null)], []).length === 0); } // --- #121: svg(overlay, opts) ---