From 9ebe6990a51b60b87622a795568553520fa7a90b Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Sun, 23 Aug 2026 11:47:59 -0500 Subject: [PATCH] =?UTF-8?q?Pruebas=20de=20voz:=20cubrir=20tambi=C3=A9n=20e?= =?UTF-8?q?l=20camino=20feliz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La suite probaba los fallos (recolector, motor pausado, bloqueo, voz lenta) pero no que HABLE BIEN: qué texto dice exactamente, con qué voz, y cómo pronuncia. Un anuncio que suena pero dice «MaríA GóMez» o elige la voz remota teniendo la local también es un fallo, y no estaba vigilado. Cuatro casos nuevos: el texto deletrea el código y cierra con el destino, las tildes capitalizan bien, se prefiere la voz local sobre la remota es-CO, y sin nombre de paciente igual habla. 13 verificaciones en total. Co-Authored-By: Claude Fable 5 --- scripts/test_tv_voz.js | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/scripts/test_tv_voz.js b/scripts/test_tv_voz.js index 099dedb..d5ce481 100644 --- a/scripts/test_tv_voz.js +++ b/scripts/test_tv_voz.js @@ -131,6 +131,59 @@ function escenario({ bloqueado = false, msArranque = 20 } = {}) { e.beacons.length >= 2); } +// ── 6. El camino feliz: habla bien ────────────────────────────────────── +// Qué dice exactamente, y con qué voz. Un anuncio que "funciona" pero +// pronuncia mal el nombre o elige la voz equivocada también es un fallo. +{ + // Instrumentación directa: escenario propio con captura de la locución + let t = 0; const cola = []; + const st = (fn, ms) => cola.push({ t: t + ms, fn }); + class Utt { + constructor(x) { this.texto = x; this.l = {}; } + addEventListener(e, f) { (this.l[e] = this.l[e] || []).push(f); } + emit(e, a) { (this.l[e] || []).forEach(f => f(a || {})); } + } + let capturada = null; + const synth = { + speaking: false, pending: false, pause() {}, cancel() {}, resume() {}, + getVoices: () => [ + { name: 'Microsoft Sabina', lang: 'es-MX', localService: true }, + { name: 'Google español de Colombia', lang: 'es-CO', localService: false }, + ], + speak(u) { + capturada = u; + st(() => u.emit('start'), 10); + st(() => u.emit('end'), 4000); + }, + }; + const api = new Function( + 'window', 'setTimeout', 'setInterval', 'SpeechSynthesisUtterance', + 'localStorage', 'navigator', 'Blob', 'Date', + cuerpo + '; return { anunciarTurno };' + )({ speechSynthesis: synth }, st, () => {}, Utt, + { getItem: () => '[]', setItem: () => {} }, + { sendBeacon: () => {} }, function Blob() {}, + Object.assign(function () { return { toISOString: () => '2026-01-01T00:00:00' }; }, { now: () => t })); + + api.anunciarTurno('A01', 'Consultorio 2', 'maría fernanda gómez', () => {}); + let n = 0; + while (cola.length && n++ < 200) { cola.sort((a, b) => a.t - b.t); const ev = cola.shift(); t = ev.t; ev.fn(); } + + ok('el texto deletrea el código y termina con el destino', + capturada && capturada.texto === 'Turno A 0 1, María Fernanda Gómez, pase a Consultorio 2'); + ok('los nombres con tilde salen bien capitalizados (María, no MaríA)', + capturada && capturada.texto.includes('María Fernanda Gómez')); + ok('elige la voz LOCAL (Sabina) aunque la remota es-CO esté disponible', + capturada && capturada.voice && capturada.voice.name === 'Microsoft Sabina'); + ok('sin nombre de paciente igual habla: solo código y destino', (() => { + capturada = null; + api.anunciarTurno('B02', 'Recepción 1', null, () => {}); + let m = 0; + while (cola.length && m++ < 200) { cola.sort((a, b) => a.t - b.t); const ev = cola.shift(); t = ev.t; ev.fn(); } + return capturada && capturada.texto === 'Turno B 0 2, pase a Recepción 1'; + })()); +} + console.log(); console.log(fallos === 0 ? 'Todo correcto.' : fallos + ' pruebas fallaron.'); process.exit(fallos === 0 ? 0 : 1);