# Diagnóstico y pruebas

Investiga fallos por fase, reconoce códigos reales y valida montaje, comunicación y limpieza en navegador.

Consulta las versiones, cambios y requisitos en [Framework 4.0 y CLI 1.2](/es/docs/guides/releases/).


<span class="section-anchor" id="section-1"></span>

## Empieza por la fase que falló

```js
console.log(wu.version);
console.log(wu.getStats());
console.log(wu.getAppInfo('catalog'));
console.log(wu.getSandboxInfo('catalog'));
console.table(wu.getManifestDiagnostics());
console.log(wu.inspect({ events: 20 }));
```

Registro, carga, montaje, actualización y teardown tienen causas diferentes. Guarda el nombre de la app, URL, entry resuelto, selector, modo real y error original. Un screenshot vacío no permite distinguir una carga fallida de una raíz montada que luego borró el renderer del shell.

<span class="section-anchor" id="section-2"></span>

## Tabla de síntomas

| Síntoma | Comprobación concreta | Resolución |
| --- | --- | --- |
| App no registrada | `init` terminó; nombre idéntico en shell/manifest/define | Esperar init y corregir identidad |
| `WU_MANIFEST_LOAD_FAILED` | Status, CORS, respuesta de `/wu.json` | Servir JSON real desde la base registrada |
| `WU_MANIFEST_NAME_MISMATCH` | Nombre descargado vs config | Publicar manifest de esa app |
| `WU_MANIFEST_INVALID` | Campos, JSON, entry y permisos | Corregir manifest; no esconder el fallo con defaults |
| `WU_PERMISSION_REQUIRED` | Request obligatorio sin cobertura | Ajustar solicitud o grant del host deliberadamente |
| `WU_CAPABILITY_DENIED` | Operación scoped y recurso efectivo | Usar path/canal autorizado |
| `emit` devuelve `false` | Identidad, grants y namespace | Consultar callback/scoped facade, no asumir excepción |
| `WU_APP_SCOPE_REVOKED` | Se conserva API después de unmount | Cancelar trabajo y obtener nuevo contexto al montar |
| `Container not found` | Selector se resuelve desde `document` | Slot light DOM existente antes de mount |
| Failed dynamically imported module | Entry, chunks, MIME y CORS | Alinear manifest con build real |
| App vacía sin error | El host reconcilia hijos del slot | Separar nodo de montaje del indicador de loading |
| React hook inválido | Dos copias React o ReactDOM distinto | Inyectar el runtime coherente al adapter |
| Vue no refresca estado | Runtime Vue no disponible al crear ref | Instalar plugin/namespace y conectar suscripción |
| Error RPC sin handler | Proveedor todavía no montado | Ordenar lifecycle o usar un estado de espera |

<span class="section-anchor" id="section-3"></span>

## Resolver conflictos de identidad y arranque

`WU_APP_EXISTS` indica que el registro intenta ocupar un nombre que ya existe. Consulta `wu.getAppInfo(name)` y revisa qué bootstrap registra esa identidad. La configuración de una app existente conserva los grants del host; crear otro wrapper no es una forma de sustituirlos.

Para comprobar por separado configuración y montaje, utiliza un arranque explícito:

```js
import { wu } from 'wu-framework';

await wu.init({ apps: [{ name: 'catalog', url: '/apps/catalog' }] });
console.log(wu.getAppInfo('catalog'));

try {
  await wu.mount('catalog', '#catalog-slot');
} catch (error) {
  console.error('No se pudo montar catalog', error);
  console.log(wu.getSandboxInfo('catalog'));
  throw error;
}
```

`whenReady()` espera un arranque ya iniciado; no inicia el runtime. En integraciones con efectos padre/hijo, coordina primero el inicio y después el montaje. `wu.app()` realiza registro diferido al montar y comparte ese registro entre mounts concurrentes del mismo wrapper; consulta [lifecycle](/es/docs/framework/lifecycle/) para su contrato de referencias y limpieza.

Evita utilizar `WuApp.destroy()` y recrear el mismo nombre como mecanismo de actualización de configuración: ese método no limpia todos los registros relacionados. Desmonta el renderer para una transición normal o reinicializa el core completo cuando el shell deba sustituir su composición.

<span class="section-anchor" id="section-4"></span>

## Recuperación de montaje

El error boundary tiene handlers de red, carga de scripts, montaje, timeout y fallback genérico. El core interpreta solicitudes de reintento y vuelve a ejecutar montaje con limpieza; preserva la definición porque un módulo ESM cacheado no se vuelve a evaluar por importarlo otra vez.

El core reconoce `retry` y `retry-with-longer-timeout` en su camino de reintento. El nombre de una acción devuelta por un handler no cambia por sí solo una URL o un timeout: configura y verifica el comportamiento que consume el core. La clasificación también utiliza nombres y fragmentos de mensajes de error; conserva el error completo para poder diagnosticarlo.

La función genérica registrada al final de los handlers por defecto acepta todo. `register()` agrega al final, así que un handler añadido después puede quedar detrás del genérico y no ejecutarse como el usuario esperaba. Comprueba el orden antes de basar recuperación de negocio en extensiones de ese sistema.

<span class="section-anchor" id="section-5"></span>

## Pruebas del repositorio

Las suites separan unidades del runtime, integración entre subsistemas y límites de seguridad. Elige el nivel que corresponda al contrato que estás cambiando:

```bash
npm run test:unit
npm run test:integration
npm run test:security
npm run test:coverage
```

`test:package` compila y ejecuta el contrato de distribución. `test:mcp` ejecuta el paquete MCP separado. Una suite que importa `src` no demuestra por sí sola que el paquete `dist` entregue los exports/chunks correctos.

Una regresión de registro debe ejecutar `WuCore` y su validación real. Puedes sustituir la descarga del manifest y el renderer para controlar el escenario, pero un mock completo del core no comprueba identidad, grants ni cleanup. Para concurrencia, difiere la respuesta del manifest y lanza dos montajes antes de resolverla; comprueba tanto el registro único como las referencias de montaje.

Antes de publicar cambios de runtime, ejecuta la suite relevante y los tests de paquete sobre el build que distribuirás.

<span class="section-anchor" id="section-6"></span>

## Aceptación en navegador

Una prueba útil del sistema políglota monta al menos dos renderers, cambia un estado compartido y verifica que ambos reflejen el dato. Luego desmonta uno, vuelve a emitir y confirma que sus callbacks no se ejecuten. Finalmente remonta y verifica que no haya listeners duplicados.

Para fallos de CSS, compara `styleMode`, hojas del ShadowRoot y ownership. Para HMR o producción, prueba tanto servidor Vite como assets compilados. Para SSR, confirma que hay contenido en la primera respuesta y que la hidratación conserva ese DOM sin duplicarlo.

<span class="section-anchor" id="section-7"></span>

## Referencia de implementación

Inspección: `src/core/wu-core.js`; recuperación: `src/core/wu-core.js`; error boundary: `src/core/wu-error-boundary.js` y `src/core/wu-error-boundary.js`; wrapper: `src/core/wu-app.js`; detección de duplicado: `src/core/wu-core.js`; scripts: `package.json`. Pruebas: `tests/unit/final-hardening-regressions.test.js`, `tests/unit/shared-container-navigation.test.js`, `tests/unit/props-channel.test.js`, `tests/integration/multi-app-isolation.test.js`.

Al actualizar a 4.0, compara `error.code`, no textos de mensajes: los errores core usan códigos como `WU_APP_NOT_REGISTERED`, `WU_CONTAINER_NOT_FOUND`, `WU_APP_NOT_DEFINED`, `WU_DEFINE_TIMEOUT` y `WU_CONTAINER_OCCUPIED`. Los contratos usan `WU_CAPABILITY_*`. El error boundary envía fallos no recuperables directamente al fallback; no decide reintentos buscando palabras en el mensaje.