/**
 * Pruebas de la parte que decide, sin tocar la red.
 *
 * Lo unico que puede arruinar esta herramienta es acusar de mas: una lista con
 * falsos positivos deja de mirarse y entonces deja de servir. Asi que lo que se
 * prueba es exactamente eso, con los casos reales que ya me enganaron una vez.
 *
 *   node selftest.js
 */
'use strict';
const { execFileSync } = require('child_process');
const fs = require('fs');
const path = require('path');

// El script es un ejecutable, asi que se carga su fuente y se evaluan las
// funciones puras en un modulo aparte, sin lanzar el main.
const src = fs.readFileSync(path.join(__dirname, 'outsidein.js'), 'utf8')
  .replace(/^#!.*\n/, ''); // el shebang no es JavaScript valido dentro de Function
const body = src.slice(0, src.indexOf('(async () => {'));
const mod = { exports: {} };
new Function('module', 'exports', 'require', 'process',
  body + '\nmodule.exports={visibleText,isClientRendered,contentProblem,sameDestination,titleOf,isNoindex};'
)(mod, mod.exports, require, process);
const T = mod.exports;

let failed = 0;
function check(name, got, want) {
  const ok = JSON.stringify(got) === JSON.stringify(want);
  if (!ok) { failed++; console.log(`FAIL  ${name}\n      esperado ${JSON.stringify(want)}\n      obtenido ${JSON.stringify(got)}`); }
  else console.log(`ok    ${name}`);
}

const page = (title, bodyHtml, head = '') =>
  `<!doctype html><html><head><title>${title}</title>${head}</head><body>${bodyHtml}</body></html>`;

const long = 'Real content. '.repeat(60);
const html = (t, b, h) => ({ status: 200, type: 'text/html', body: page(t, b, h) });

check('pagina normal no da problema',
  T.contentProblem(html('My product', long)), null);

// El caso que me engano: un articulo que HABLA de errores 404.
check('un articulo sobre errores 404 no es un 404',
  T.contentProblem(html('An AI agent got flagged',
    'The API said public. ' + long + ' Every anonymous visitor got 404 not found.')), null);

check('titulo de error si es un soft 404',
  T.contentProblem(html('Page not found (404) - Gumroad', long)).level, 'FAIL');

check('pagina corta con frase de error es soft 404',
  T.contentProblem(html('Shop', 'Sorry, we could not find that page.')).level, 'FAIL');

check('pagina vacia pintada en cliente es aviso, no fallo',
  T.contentProblem(html('App', '<div id="root"></div>')).level, 'WARN');

check('el head enorme no cuenta como contenido',
  T.contentProblem(html('Real page', long, '<style>' + 'x'.repeat(40000) + '</style>')), null);

check('http a https no es redireccion que importe',
  T.sameDestination('http://a.com/x', 'https://www.a.com/x/'), true);

check('otro destino si importa',
  T.sameDestination('https://a.com/x', 'https://a.com/y'), false);

check('noindex se detecta',
  T.isNoindex('<meta name="robots" content="noindex, follow">'), true);

check('titulo se extrae limpio',
  T.titleOf(page('  Hello\n  world  ', '')), 'Hello world');

// Y una comprobacion de que el ejecutable arranca y responde a --help mal usado.
try {
  execFileSync(process.execPath, [path.join(__dirname, 'outsidein.js')], { stdio: 'pipe' });
  failed++; console.log('FAIL  sin argumentos deberia salir con codigo 2');
} catch (e) {
  check('sin argumentos sale con codigo 2', e.status, 2);
}

console.log(failed ? `\n${failed} fallos` : '\ntodo correcto');
process.exitCode = failed ? 1 : 0;
