Playlist TV: subir en cola con resumen — «subí 5 y solo salieron 2»
El reproductor no se saltaba nada: en la base solo había 2 videos. El defecto estaba en la subida: los archivos elegidos se mandaban TODOS EN PARALELO (inp.files.forEach), peleándose el ancho de banda de subida. Los primeros alcanzaban a entrar y el resto moría por timeout — avisando con un toast que desaparece en segundos y con una barra de progreso que además era la misma para todos, pisándose entre sí. El cliente veía «subí 5», la playlist tenía 2. Ahora los archivos van de a uno (secuencial a propósito), un fallo no frena a los que siguen, y al terminar queda un RESUMEN FIJO: «3 de 5 agregados», con el nombre de cada rechazado y su motivo en cristiano. Los videos de iPhone (.mov) —causa probable del resto de los faltantes— se rechazan de inmediato con la instrucción de convertirlos a MP4, en el navegador y en el servidor. Y los límites de PHP (INI_SIZE, FORM_SIZE, PARTIAL) dejan de caer en «error de subida desconocido». Verificado además que nginx acepta cuerpos de 90 MB o más: el límite del web server no era la causa. scripts/test_tv_playlist.js: 11 pruebas contra el código real — nunca dos subidas a la vez, los 5 se intentan pese a fallos, el resumen cuenta y nombra, y los pre-chequeos rechazan sin tocar la red. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
1ba6805799
commit
587c23adcd
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* scripts/test_tv_playlist.js — node scripts/test_tv_playlist.js
|
||||
*
|
||||
* Pruebas de la subida de la playlist del televisor, contra el código real de
|
||||
* configuracion.php. Vigilan el defecto reportado: «subí 5 videos y solo
|
||||
* salieron 2» — los archivos se subían todos en paralelo, los lentos morían
|
||||
* por timeout y el aviso era un toast que desaparecía en segundos.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
let fallos = 0;
|
||||
const ok = (d, c) => { console.log((c ? ' ok ' : ' FALLA ') + d); if (!c) fallos++; };
|
||||
|
||||
const src = fs.readFileSync(__dirname + '/../modules/turnero/views/configuracion.php', 'utf8')
|
||||
.replace(/<\?(php|=)[\s\S]*?\?>/g, '"PHP"');
|
||||
|
||||
// ── extracciones ────────────────────────────────────────────────────────
|
||||
const iCola = src.indexOf('const escHtml');
|
||||
const fCola = src.indexOf('function subirTvMedia(file)');
|
||||
const colaSrc = src.slice(iCola, fCola); // escHtml + subirTvMediaEnCola
|
||||
const fFin = src.indexOf('function agregarItemTvMedia');
|
||||
const subirSrc = src.slice(fCola, fFin); // subirTvMedia real
|
||||
|
||||
ok('el selector de archivos usa la cola, no la andanada paralela',
|
||||
src.includes('subirTvMediaEnCola(Array.from(inp.files))'));
|
||||
ok('el reproductor salta al siguiente si un video falla',
|
||||
src.includes("addEventListener('error', siguiente)") ||
|
||||
fs.readFileSync(__dirname + '/../modules/turnero/views/display_global.php', 'utf8')
|
||||
.includes("addEventListener('error', siguiente)"));
|
||||
|
||||
// ── 1. La cola sube de a UNO y no se detiene ante un fallo ──────────────
|
||||
{
|
||||
const orden = [];
|
||||
let simultaneos = 0, picoSimultaneos = 0;
|
||||
const resumenDiv = { style: {}, innerHTML: '', className: '' };
|
||||
const doc = { getElementById: id => (id === 'tv-upload-resumen' ? resumenDiv : null) };
|
||||
|
||||
// subirTvMedia de mentira: tarda distinto por archivo, falla el 2º y el 4º
|
||||
const stub = async (f) => {
|
||||
simultaneos++; picoSimultaneos = Math.max(picoSimultaneos, simultaneos);
|
||||
orden.push('inicio:' + f.name);
|
||||
await new Promise(x => setTimeout(x, f.ms));
|
||||
simultaneos--;
|
||||
orden.push('fin:' + f.name);
|
||||
return f.falla ? { ok: false, nombre: f.name, motivo: 'timeout simulado' }
|
||||
: { ok: true, nombre: f.name };
|
||||
};
|
||||
|
||||
const enCola = new Function('subirTvMedia', 'document',
|
||||
colaSrc + '; return subirTvMediaEnCola;')(stub, doc);
|
||||
|
||||
const files = [
|
||||
{ name: 'v1.mp4', ms: 30 },
|
||||
{ name: 'v2.mp4', ms: 10, falla: true },
|
||||
{ name: 'v3.mp4', ms: 20 },
|
||||
{ name: 'v4.mp4', ms: 10, falla: true },
|
||||
{ name: 'v5.mp4', ms: 15 },
|
||||
];
|
||||
|
||||
enCola(files).then(() => {
|
||||
ok('sube estrictamente de a uno (nunca hubo dos a la vez)', picoSimultaneos === 1);
|
||||
ok('un fallo no frena a los que siguen: los 5 se intentaron',
|
||||
orden.filter(x => x.startsWith('inicio:')).length === 5);
|
||||
ok('respeta el orden elegido',
|
||||
orden.filter(x => x.startsWith('inicio:')).join(',') ===
|
||||
'inicio:v1.mp4,inicio:v2.mp4,inicio:v3.mp4,inicio:v4.mp4,inicio:v5.mp4');
|
||||
ok('el resumen dice cuántos entraron: «3 de 5»',
|
||||
resumenDiv.innerHTML.includes('3 de 5'));
|
||||
ok('el resumen NOMBRA los que fallaron y su motivo',
|
||||
resumenDiv.innerHTML.includes('v2.mp4') && resumenDiv.innerHTML.includes('v4.mp4')
|
||||
&& resumenDiv.innerHTML.includes('timeout simulado'));
|
||||
ok('el resumen queda visible (no es un toast fugaz)',
|
||||
resumenDiv.style.display === '');
|
||||
|
||||
// ── 2. Los pre-chequeos rechazan claro y ANTES de tocar la red ──────
|
||||
const docTrampa = { getElementById: () => { throw new Error('tocó el DOM'); } };
|
||||
const subir = new Function('document', 'XMLHttpRequest', 'FormData', 'API',
|
||||
subirSrc + '; return subirTvMedia;')(
|
||||
docTrampa, function () { throw new Error('tocó la red'); }, function () {}, '');
|
||||
|
||||
Promise.all([
|
||||
subir({ name: 'clip.mov', type: 'video/quicktime', size: 1000 }),
|
||||
subir({ name: 'doc.pdf', type: 'application/pdf', size: 1000 }),
|
||||
subir({ name: 'giga.mp4', type: 'video/mp4', size: 600 * 1024 * 1024 }),
|
||||
]).then(([mov, pdf, giga]) => {
|
||||
ok('un .mov de iPhone se rechaza con instrucción de convertir a MP4',
|
||||
!mov.ok && /iPhone|MP4/.test(mov.motivo));
|
||||
ok('un formato ajeno se rechaza nombrando los admitidos',
|
||||
!pdf.ok && /MP4/.test(pdf.motivo));
|
||||
ok('el que pasa de 500 MB se rechaza por tamaño',
|
||||
!giga.ok && /500/.test(giga.motivo));
|
||||
console.log();
|
||||
console.log(fallos === 0 ? 'Todo correcto.' : fallos + ' pruebas fallaron.');
|
||||
process.exit(fallos === 0 ? 0 : 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user