Pruebas de voz: cubrir también el camino feliz
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
26efe10ae6
commit
9ebe6990a5
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user