E2E
LeadFlow SaaS — Suite de Tests E2E
Agente E2E · Playwright 1.44 · Run #47 · 18 Jun 2026, 09:14:33
29
Passed
2
Failed
1
Flaky
1
Skipped
6m 48s
Duración
Resultados
Código
CI/CD
Métricas
29
Tests pasados
2
Tests fallados
⚠️
1
Flaky (cuarentena)
⏭️
1
Omitidos
⏱️
6m 48s
Tiempo total · 3 workers
Cobertura de Journeys — 87.9% pass rate (29/33 tests activos)
Passed (29) Failed (2) Flaky – quarantined (1) Skipped (1)
🔐 Journey 1 — Registro & Autenticación HIGH RISK
7/7 ✅ 1m 12s auth.spec.ts
Test
Archivo
Duración
Estado
Artefactos
Registro con email válido crea cuenta
[data-testid="register-form"]
auth.spec.ts:12
8.2s
PASS
📷 PNG
Email duplicado muestra error inline
[data-testid="email-error"]
auth.spec.ts:34
4.1s
PASS
📷 PNG
Login correcto redirige a /dashboard
[data-testid="login-btn"]
auth.spec.ts:58
5.4s
PASS
📷 PNG
Login incorrecto muestra mensaje de error
[data-testid="login-error"]
auth.spec.ts:78
3.8s
PASS
Recuperación de contraseña envía email
[data-testid="forgot-password"]
auth.spec.ts:99
6.2s
PASS
📷 PNG
Logout invalida sesión y redirige a /login
[data-testid="logout-btn"]
auth.spec.ts:118
3.2s
PASS
Onboarding wizard completa perfil de empresa
[data-testid="onboarding-step"]
auth.spec.ts:145
22.1s
PASS
🎥 VID 🔍 TRC
📥 Journey 2 — Importación de Leads (CSV) HIGH RISK
6/8 ✅ · 2 ❌ 2m 04s leads-import.spec.ts
Test
Archivo
Duración
Estado
Artefactos
Upload CSV válido (500 filas) parsea correctamente
[data-testid="csv-upload"]
leads-import.spec.ts:15
14.3s
PASS
📷 PNG
Mapeo de campos: auto-detecta email, nombre, empresa
[data-testid="field-mapper"]
leads-import.spec.ts:42
9.7s
PASS
📷 PNG
Validación rechaza emails malformados
[data-testid="validation-errors"]
leads-import.spec.ts:68
6.1s
PASS
Deduplicación elimina 12 registros duplicados
[data-testid="dedup-summary"]
leads-import.spec.ts:91
11.8s
PASS
📷 PNG
Import CSV >5MB muestra error de límite de plan
[data-testid="plan-limit-banner"]
leads-import.spec.ts:115
18.4s
FAIL
📷 PNG 🔍 TRC
Progreso de importación en tiempo real (WebSocket)
[data-testid="import-progress"]
leads-import.spec.ts:148
16.2s
PASS
🎥 VID
Import falla a mitad muestra rollback y estado limpio
[data-testid="import-rollback"]
leads-import.spec.ts:175
30.1s
FAIL
📷 PNG 🎥 VID 🔍 TRC
Import via API key (headless) retorna 201 + job_id
POST /api/v1/leads/import
leads-import.spec.ts:210
4.8s
PASS
🤖 Journey 3 — Scoring IA de Leads MEDIUM RISK
6/7 ✅ · 1 ⚠️ flaky 1m 38s ai-scoring.spec.ts
Test
Archivo
Duración
Estado
Artefactos
Trigger scoring manual genera puntuación 0-100
[data-testid="score-lead-btn"]
ai-scoring.spec.ts:18
12.4s
PASS
📷 PNG
Filtro por score >70 devuelve leads calientes
[data-testid="score-filter"]
ai-scoring.spec.ts:44
5.2s
PASS
Tabla de scoring se ordena por puntuación desc
[data-testid="leads-table-sort"]
ai-scoring.spec.ts:65
3.8s
PASS
⚠️
Scoring masivo 1000 leads <30s (timeout race)
[data-testid="bulk-score-progress"]
ai-scoring.spec.ts:88
31.7s
FLAKY
🔍 TRC
Explicación IA muestra top-3 señales de scoring
[data-testid="score-explain"]
ai-scoring.spec.ts:115
8.9s
PASS
📷 PNG
Webhook dispara al superar score umbral 80
POST /webhooks/score-threshold
ai-scoring.spec.ts:138
6.4s
PASS
Re-score tras editar datos del lead actualiza score
[data-testid="lead-edit-form"]
ai-scoring.spec.ts:161
10.1s
PASS
📷 PNG
💳 Journey 4 — Billing & Upgrade (Stripe) HIGH RISK
7/7 ✅ · 1 ⏭️ skip 1m 28s billing.spec.ts
Test
Archivo
Duración
Estado
Artefactos
Modal upgrade muestra planes y precios actuales
[data-testid="upgrade-modal"]
billing.spec.ts:22
4.2s
PASS
📷 PNG
Checkout Stripe abre con tarjeta de test 4242
[data-testid="checkout-frame"]
billing.spec.ts:48
14.8s
PASS
🎥 VID 🔍 TRC
Pago exitoso activa plan Pro instantáneamente
[data-testid="plan-badge-pro"]
billing.spec.ts:82
18.2s
PASS
📷 PNG
Tarjeta declinada (4000 0000 0000 0002) muestra error Stripe
[data-testid="stripe-error"]
billing.spec.ts:110
11.4s
PASS
📷 PNG
Portal de facturación muestra historial de facturas
[data-testid="billing-portal"]
billing.spec.ts:138
7.6s
PASS
📷 PNG
Cancelación downgrade a Free al final del ciclo
[data-testid="cancel-subscription"]
billing.spec.ts:162
9.3s
PASS
📷 PNG
Webhook Stripe invoice.paid actualiza estado en DB
POST /webhooks/stripe
billing.spec.ts:188
3.8s
PASS
⏭️
3D Secure challenge flow (bloqueado en CI sandbox)
[data-testid="3ds-challenge"]
billing.spec.ts:215
SKIP
📣 Journey 5 — Envío de Campañas MEDIUM RISK
7/7 ✅ 1m 02s campaigns.spec.ts
Test
Archivo
Duración
Estado
Artefactos
Crear campaña con nombre, segmento y plantilla
[data-testid="campaign-builder"]
campaigns.spec.ts:14
8.1s
PASS
📷 PNG
Preview de email renderiza variables personalizadas
[data-testid="email-preview"]
campaigns.spec.ts:38
4.4s
PASS
📷 PNG
Programar envío a futuro guarda fecha correcta
[data-testid="schedule-picker"]
campaigns.spec.ts:59
5.8s
PASS
Lanzar campaña muestra contador de enviados en vivo
[data-testid="send-counter"]
campaigns.spec.ts:82
14.2s
PASS
🎥 VID
Dashboard muestra open rate, CTR y bounces
[data-testid="campaign-metrics"]
campaigns.spec.ts:108
6.3s
PASS
📷 PNG
Pausar campaña en curso detiene envíos pendientes
[data-testid="pause-campaign"]
campaigns.spec.ts:131
7.8s
PASS
Export CSV de resultados de campaña descarga archivo
[data-testid="export-results"]
campaigns.spec.ts:155
3.6s
PASS
📷 PNG
⚠️ Tests en Cuarentena (Flaky)
ai-scoring.spec.ts:88 — Scoring masivo 1000 leads <30s
Race condition: La respuesta del job llega en 28-34s según carga del worker. Falla ~30% de las ejecuciones en CI.
test.fixme(true, 'Flaky – Issue #234: bulk-score timeout race. Aumentar timeout a 45s o mockear worker response.')
⏱️ Distribución de Tiempos por Journey
🔐 Auth & Registro
17.7%
1m 12s
📥 Importación de Leads
30.3%
2m 04s
🤖 Scoring IA
24%
1m 38s
💳 Billing Stripe
21.6%
1m 28s
📣 Campañas
15.2%
1m 02s
Métricas de Calidad
Pass rate (tests activos) 87.9%
Pass rate (excl. fallos conocidos) 96.7%
Flaky rate 3.0%
Duración total (3 workers) 6m 48s
Objetivo duración < 8m ✅
Artefactos generados 18 PNG · 4 VID · 5 TRC
JUnit XML test-results.xml ✅
Fallos Activos — Acción Requerida
❌ leads-import.spec.ts:115
Import CSV >5MB no dispara [data-testid="plan-limit-banner"]
Timeout en Expect después de 5000ms. El banner no aparece. Probable: validación de tamaño movida a worker asíncrono sin actualizar el componente. Asignado a @frontend
❌ leads-import.spec.ts:175
Import rollback no limpia registros parciales
Expect leads.count toBe(0) recibido 47. Transacción DB no hace rollback si el worker muere en paso 3. Asignado a @backend
📄 Ejemplo de Código Generado — Page Object + Test
Page Object Model: LeadImport tests/pages/lead-import.page.ts
import { Page, Locator } from '@playwright/test';

export class LeadImportPage {
  readonly page: Page;
  readonly uploadInput:  Locator;
  readonly fieldMapper:  Locator;
  readonly importBtn:    Locator;
  readonly progressBar:  Locator;
  readonly successToast: Locator;

  constructor(page: Page) {
    this.page        = page;
    this.uploadInput  = page.locator('[data-testid="csv-upload"]');
    this.fieldMapper  = page.locator('[data-testid="field-mapper"]');
    this.importBtn    = page.locator('[data-testid="confirm-import-btn"]');
    this.progressBar  = page.locator('[data-testid="import-progress"]');
    this.successToast = page.locator('[data-testid="success-toast"]');
  }

  async uploadCSV(filePath: string) {
    await this.page.goto('/leads/import');
    await this.uploadInput.setInputFiles(filePath);
    await this.fieldMapper.waitFor({ state: 'visible' });
  }

  async confirmImport() {
    await this.importBtn.click();
    await this.page.waitForResponse(
      res => res.url().includes('/api/v1/leads/import') &&
              res.status() === 201
    );
    await this.successToast.waitFor({ state: 'visible', timeout: 30_000 });
  }
}
E2E Test: CSV Import — Happy Path tests/leads-import.spec.ts
import { test, expect } from '@playwright/test';
import { LeadImportPage } from './pages/lead-import.page';

test.describe('Journey 2 — Importación de Leads (CSV)', () => {
  test.beforeEach(async ({ page }) => {
    // Login como usuario Pro con fixture pre-seeded
    await page.goto('/login');
    await page.fill('[data-testid="email"]', 'demo@leadflow.io');
    await page.fill('[data-testid="password"]', 'test-secure-pw!');
    await page.click('[data-testid="login-btn"]');
    await expect(page).toHaveURL('/dashboard');
  });

  test('Upload CSV válido (500 filas) parsea correctamente',
    async ({ page }) => {
      const importPage = new LeadImportPage(page);

      await importPage.uploadCSV('./fixtures/leads-500.csv');

      // Verifica autodetección de columnas
      await expect(importPage.fieldMapper
        .locator('[data-col="email"]'))
        .toHaveText('email');

      await expect(page
        .locator('[data-testid="preview-count"]'))
        .toContainText('500 filas detectadas');

      await importPage.confirmImport();

      await expect(importPage.successToast)
        .toContainText('500 leads importados');

      await page.screenshot({ path: 'artifacts/import-success.png' });
    }
  );

  // Quarantined: race condition en worker
  test('flaky: scoring masivo 1000 leads', async ({ page }) => {
    test.fixme(true, 'Flaky – Issue #234: bulk-score timeout race');
  });
});