- OBSERVATIONS.md reseteado para Sprint 2 - STRATEGIC_DIRECTION.md con reflexiones del sprint - TECH_DEBT.md curado: items resueltos archivados - methodology/CASE_STUDIES/inq-roi-sprint-1-5.md generado Sprint 1.5 cerrado: - 11 etapas + 1 fix pre-Etapa 11 - 526 unit tests + 38 E2E al cierre - Producto con identidad InQ aplicada en web + 3 PDFs - Metodología documentada con casos reales (2 de mala clasificación de iniciativa, originaron AP.8 + refinamiento C.6) - Material para transmisión al equipo de 5 técnicos
92 lines
4.3 KiB
TypeScript
92 lines
4.3 KiB
TypeScript
/**
|
|
* Smoke test de producción — verifica el flujo completo en la URL live.
|
|
* Usa el proceso de ejemplo "Aprobación de crédito" (carga via fetch desde el CDN).
|
|
*
|
|
* Ejecutar: npx playwright test --config=playwright.prod.config.ts
|
|
*/
|
|
import { test, expect } from '@playwright/test'
|
|
import { readFileSync, mkdirSync } from 'fs'
|
|
import { resolve } from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
|
const OUTPUT_DIR = resolve(__dirname, '__output__')
|
|
|
|
test.beforeAll(() => {
|
|
mkdirSync(OUTPUT_DIR, { recursive: true })
|
|
})
|
|
|
|
test('prod-smoke — import → simulate → export PDF', async ({ page }) => {
|
|
// ── 1. Landing page carga correctamente ──────────────────────────────────
|
|
await page.goto('/')
|
|
await expect(page).toHaveTitle(/InQ ROI/)
|
|
|
|
// Verificar heading principal
|
|
await expect(page.getByText('Cuantificá el costo operativo')).toBeVisible({ timeout: 10_000 })
|
|
|
|
// Verificar que los 3 procesos de ejemplo están presentes
|
|
await expect(page.getByText('Aprobación de crédito')).toBeVisible()
|
|
await expect(page.getByText('Proceso lineal simple')).toBeVisible()
|
|
await expect(page.getByText('Control de calidad con revisión')).toBeVisible()
|
|
|
|
// ── 2. Cargar proceso de ejemplo "Proceso lineal simple" ──────────────────
|
|
await page.getByText('Proceso lineal simple').click()
|
|
|
|
// Esperar navegación al workspace
|
|
await page.waitForURL(/\/workspace\//, { timeout: 30_000 })
|
|
|
|
// ── 3. Workspace: diagrama BPMN + botón Simular ───────────────────────────
|
|
await page.waitForSelector('button:has-text("Simular")', { timeout: 20_000 })
|
|
await page.waitForTimeout(1_500)
|
|
|
|
// Nombre del proceso visible en la topbar
|
|
await expect(page.getByText('simple-linear')).toBeVisible()
|
|
|
|
const simularBtn = page.getByRole('button', { name: 'Simular' })
|
|
await expect(simularBtn).not.toBeDisabled({ timeout: 5_000 })
|
|
await simularBtn.click()
|
|
|
|
// ── 4. Reporte carga ──────────────────────────────────────────────────────
|
|
await page.waitForURL(/\/report\//, { timeout: 30_000 })
|
|
await page.waitForSelector('button:has-text("Exportar PDF")', { timeout: 30_000 })
|
|
await page.waitForSelector('.bpmn-container .djs-group', { timeout: 30_000 })
|
|
|
|
// KPIs visibles
|
|
await expect(page.getByText('COSTO TOTAL ESPERADO')).toBeVisible()
|
|
|
|
// ── 5. Export PDF ─────────────────────────────────────────────────────────
|
|
const pdfPath = resolve(OUTPUT_DIR, 'prod-smoke.pdf')
|
|
|
|
const pdfDownload = page.waitForEvent('download', { timeout: 90_000 })
|
|
await page.getByRole('button', { name: 'Exportar PDF' }).click()
|
|
const dl = await pdfDownload
|
|
await dl.saveAs(pdfPath)
|
|
|
|
const pdfBuffer = readFileSync(pdfPath)
|
|
const pdfKB = (pdfBuffer.length / 1024).toFixed(1)
|
|
console.log(`\n📄 prod-smoke.pdf: ${pdfBuffer.length} bytes (${pdfKB} KB)`)
|
|
|
|
expect(pdfBuffer.length, 'PDF debe ser > 40 KB').toBeGreaterThan(40_000)
|
|
expect(pdfBuffer.length, 'PDF debe ser < 2 MB').toBeLessThan(2_000_000)
|
|
|
|
// JPEG heatmap embebido
|
|
const jpegMarker = Buffer.from([0xff, 0xd8, 0xff])
|
|
const hasJpeg = pdfBuffer.includes(jpegMarker)
|
|
console.log(` Heatmap JPEG embebido: ${hasJpeg}`)
|
|
expect(hasJpeg, 'PDF de prod debe tener heatmap embebido').toBe(true)
|
|
|
|
// ── 6. Export CSV ─────────────────────────────────────────────────────────
|
|
const csvPath = resolve(OUTPUT_DIR, 'prod-smoke.csv')
|
|
const csvDownload = page.waitForEvent('download')
|
|
await page.getByRole('button', { name: 'Exportar CSV' }).click()
|
|
const dlCsv = await csvDownload
|
|
await dlCsv.saveAs(csvPath)
|
|
|
|
const csvText = readFileSync(csvPath, 'utf-8')
|
|
expect(csvText, 'CSV debe tener BOM UTF-8').toMatch(/^/)
|
|
expect(csvText, 'CSV debe contener encabezado').toContain('Costo total')
|
|
|
|
console.log(`\n✅ Prod smoke PASSED — https://process-cost-platform.pages.dev`)
|
|
console.log(` PDF: ${pdfKB} KB | CSV: ${csvText.length} chars`)
|
|
})
|