primer commit

This commit is contained in:
absandoval
2026-10-13 21:22:54 -06:00
commit b6b4bc3f01
13 changed files with 2428 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
# Capturas de pantalla
Cómo producir las capturas que acompañarán a los manuales. Esta guía presupone que tienes instalada la skill `playwright-skill` de lackeyjb.
## Configuración del navegador
- **Viewport**: 1440×900 px (escritorio estándar).
- **Factor de escala**: 2 (DPR 2). Resultado: imagen a 2880×1800. Reduce al 50% en el CSS con `max-width: 100%` y `image-rendering: -webkit-optimize-contrast`.
- **Localización**: `es-ES` (o la del usuario). Forzar la zona horaria de la operación si afecta a la UI.
- **User agent**: dejar el de Chromium por defecto.
- **Modo headless**: recomendado. Usar `headless: true` para ejecuciones desatendidas. Reservar headed para depuración puntual.
Plantilla de configuración para `playwright-skill`:
```bash
export PW_HEADLESS=true
export PW_ARTIFACT_DIR="$PWD/artifacts"
node "$SKILL_DIR/run.js" "$TMP_DIR/capturar-flujo.js"
```
## Resolución y nombrado
- Tamaño final recomendado: entre 1200 y 1600 px de ancho (después del downscale). Más grande no mejora la impresión y aumenta el peso del PDF.
- Formato: PNG para capturas con texto nítido. JPEG (`quality: 80`) para pantallas con muchas fotos.
- Nombres de archivo: `NN-slug-corto.png` donde `NN` es el número de paso. Ejemplo: `01-login.png`, `02-panel-principal.png`, `03-formulario-cliente.png`.
- Guardar todas las capturas dentro de `artifacts/` en la raíz del manual. El build copia esa carpeta al directorio temporal de render.
## Antes de capturar
1. **Sesión limpia**: cierra banners de cookies, notificaciones push y tooltips de onboarding. Si la app tiene un banner de "tour", descártalo.
2. **Datos consistentes**: usa siempre el mismo usuario de pruebas, mismo idioma y mismo conjunto de datos. Cualquier inconsistencia se notará en el manual.
3. **Quita lo accesorio**: oculta elementos beta, flags, datos personales reales, mensajes transitorios. No falsees pantallas: si un paso intermedio no es representativo, no lo fotografíes.
4. **Espera activa**: usa `await page.locator(...).waitFor({ state: 'visible' })` o `await page.getByRole(...).waitFor()` en lugar de `waitForTimeout`. La captura debe hacerse después de que la UI termine de actualizarse.
## Encuadre
- Captura la pantalla completa con `fullPage: true` solo si la página entera es el contenido relevante. Para vistas con scroll, prefiere captura del viewport (`fullPage: false`).
- Recorta a la zona de interés con `page.locator(selector).screenshot({ path })` cuando solo importa un componente (por ejemplo, un modal).
- Deja al menos 16pt de margen visual alrededor del elemento principal.
- Incluye en la captura el contexto suficiente para que el lector se ubique: la barra de navegación, el breadcrumb o el encabezado de sección son válidos.
- Evita capturas con scrollbars visibles a menos que sea indispensable.
## Privacidad y seguridad
- **Nunca** incluyas contraseñas, tokens, claves API, datos personales reales o números de identificación reales. Sustituye por placeholders tipográficos como `usuario@ejemplo.com`, `••••••••`, `1234567X` o cuentas de prueba claramente ficticias.
- Antes de capturar, valida que la vista no contenga datos sensibles: usa cuentas de test y datos sintéticos.
- Si necesitas capturar un error real, anonimiza la URL y los IDs antes de pegarla en el manual.
- Revisa el fondo de la captura: pueden aparecer datos de otras pestañas sincronizadas, notificaciones del sistema o fechas de la máquina.
## Anotaciones
Las anotaciones se aplican en el HTML con la clase `.annotations` y el atributo `data-annotations`. Cada elemento del array es un marcador posicionado en porcentaje respecto a la imagen:
```html
<figure class="screenshot-frame">
<img src="artifacts/01-login.png" alt="Pantalla de inicio de sesión" />
<ol class="annotations" data-annotations='[
{"x": 62, "y": 58, "n": 1, "label": "Botón Iniciar sesión"},
{"x": 50, "y": 74, "n": 2, "label": "Campo contraseña"}
]'></ol>
<figcaption>Inicio de sesión con credenciales de prueba.</figcaption>
</figure>
```
Convenciones:
- `x` y `y` son porcentajes sobre el ancho y alto de la imagen. 0/0 es la esquina superior izquierda, 100/100 la inferior derecha.
- `n` es el número que se muestra en el círculo. Debe coincidir con el orden lógico del paso (1, 2, 3…).
- `label` es texto accesible (lectores de pantalla) y se usa como tooltip al pasar el cursor.
- En el manual impreso, los marcadores se muestran en blanco con borde primary, número primary.
## Plantilla de script Playwright
```javascript
const { chromium } = require('playwright');
const path = require('node:path');
const fs = require('node:fs');
const TARGET = process.env.TARGET_URL || 'http://localhost:3000';
const ART = process.env.PW_ARTIFACT_DIR || path.join(process.cwd(), 'artifacts');
fs.mkdirSync(ART, { recursive: true });
(async () => {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
locale: 'es-ES',
timezoneId: 'Europe/Madrid',
});
const page = await context.newPage();
// Paso 1: login
await page.goto(`${TARGET}/login`);
await page.getByLabel('Email').waitFor();
await page.screenshot({ path: path.join(ART, '01-login.png'), fullPage: false });
// Paso 2: panel principal
await page.getByLabel('Email').fill('demo@factorpesca.com');
await page.getByLabel('Contraseña').fill('Demo-2025!');
await page.getByRole('button', { name: 'Iniciar sesión' }).click();
await page.getByRole('heading', { name: /panel/i }).waitFor();
await page.screenshot({ path: path.join(ART, '02-panel.png'), fullPage: false });
await browser.close();
})();
```
Guarda el script como `scripts/capturar.js` y ejecútalo a través de la skill `playwright-skill` con `node "$SKILL_DIR/run.js" capturar.js`.
## Verificación rápida
Antes de pasar al redactor, ejecuta este checklist:
- [ ] Las capturas se ven nítidas a tamaño real (sin pixelado al 100%).
- [ ] El texto de la UI es legible.
- [ ] No hay datos personales reales.
- [ ] El número de capturas coincide con el número de pasos previstos.
- [ ] Los nombres de archivo siguen el patrón `NN-slug.png`.
- [ ] Cada captura muestra el estado final del paso anterior, no un estado intermedio de carga.
- [ ] Los banners de cookies, tooltips de onboarding y notificaciones de "tour" están cerrados.