/** * 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(/Process Cost Platform/) // 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`) })