Source profileQuality 65/100Review permissions

affaan-m/ECC/docs/es/skills/e2e-testing/SKILL.md

e2e-testing

Patrones de pruebas E2E con Playwright, Page Object Model, configuración, integración CI/CD, gestión de artefactos y estrategias para pruebas inestables.

Source repository stars
234,327
Declared platforms
0
Static risk flags
2
Last source update
2026-07-27
Source checked
2026-07-28

Decision brief

What it does—and where it fits

Patrones completos de Playwright para construir suites de pruebas E2E estables, rápidas y mantenibles.

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/affaan-m/ECC --skill "docs/es/skills/e2e-testing"
    Safe inspection promptEditorial

    Inspect the Agent Skill "e2e-testing" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/es/skills/e2e-testing/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Organización de Archivos de Prueba

      Review the “Organización de Archivos de Prueba” section in the pinned source before continuing.

      Review and apply the “Organización de Archivos de Prueba” source section.
    2. 02

      Page Object Model (POM)

      Review the “Page Object Model (POM)” section in the pinned source before continuing.

      Review and apply the “Page Object Model (POM)” source section.
    3. 03

      Estructura de Pruebas

      Review the “Estructura de Pruebas” section in the pinned source before continuing.

      Review and apply the “Estructura de Pruebas” source section.
    4. 04

      Configuración de Playwright

      Review the “Configuración de Playwright” section in the pinned source before continuing.

      Review and apply the “Configuración de Playwright” source section.
    5. 05

      Patrones de Pruebas Inestables (Flaky Tests)

      Review the “Patrones de Pruebas Inestables (Flaky Tests)” section in the pinned source before continuing.

      Review and apply the “Patrones de Pruebas Inestables (Flaky Tests)” source section.

    Permission review

    Static risk signals and limitations

    Network access

    medium · line 111

    The documentation includes network, browsing, or remote request actions.

    baseURL: process.env.BASE_URL || 'http://localhost:3000',

    Network access

    medium · line 126

    The documentation includes network, browsing, or remote request actions.

    url: 'http://localhost:3000',

    Runs scripts

    medium · line 152

    The documentation asks the agent to run terminal commands or scripts.

    npx playwright test tests/search.spec.ts --repeat-each=10

    Runs scripts

    medium · line 153

    The documentation asks the agent to run terminal commands or scripts.

    npx playwright test tests/search.spec.ts --retries=3

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score65/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars234,327SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    affaan-m/ECC
    Skill path
    docs/es/skills/e2e-testing/SKILL.md
    Commit
    4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38
    License
    MIT
    Collected
    2026-07-28
    Default branch
    main
    View the original SKILL.md

    Patrones de Pruebas E2E

    Patrones completos de Playwright para construir suites de pruebas E2E estables, rápidas y mantenibles.

    Organización de Archivos de Prueba

    tests/
    ├── e2e/
    │   ├── auth/
    │   │   ├── login.spec.ts
    │   │   ├── logout.spec.ts
    │   │   └── register.spec.ts
    │   ├── features/
    │   │   ├── browse.spec.ts
    │   │   ├── search.spec.ts
    │   │   └── create.spec.ts
    │   └── api/
    │       └── endpoints.spec.ts
    ├── fixtures/
    │   ├── auth.ts
    │   └── data.ts
    └── playwright.config.ts
    

    Page Object Model (POM)

    import { Page, Locator } from '@playwright/test'
    
    export class ItemsPage {
      readonly page: Page
      readonly searchInput: Locator
      readonly itemCards: Locator
      readonly createButton: Locator
    
      constructor(page: Page) {
        this.page = page
        this.searchInput = page.locator('[data-testid="search-input"]')
        this.itemCards = page.locator('[data-testid="item-card"]')
        this.createButton = page.locator('[data-testid="create-btn"]')
      }
    
      async goto() {
        await this.page.goto('/items')
        await this.page.waitForLoadState('networkidle')
      }
    
      async search(query: string) {
        await this.searchInput.fill(query)
        await this.page.waitForResponse(resp => resp.url().includes('/api/search'))
        await this.page.waitForLoadState('networkidle')
      }
    
      async getItemCount() {
        return await this.itemCards.count()
      }
    }
    

    Estructura de Pruebas

    import { test, expect } from '@playwright/test'
    import { ItemsPage } from '../../pages/ItemsPage'
    
    test.describe('Item Search', () => {
      let itemsPage: ItemsPage
    
      test.beforeEach(async ({ page }) => {
        itemsPage = new ItemsPage(page)
        await itemsPage.goto()
      })
    
      test('should search by keyword', async ({ page }) => {
        await itemsPage.search('test')
    
        const count = await itemsPage.getItemCount()
        expect(count).toBeGreaterThan(0)
    
        await expect(itemsPage.itemCards.first()).toContainText(/test/i)
        await page.screenshot({ path: 'artifacts/search-results.png' })
      })
    
      test('should handle no results', async ({ page }) => {
        await itemsPage.search('xyznonexistent123')
    
        await expect(page.locator('[data-testid="no-results"]')).toBeVisible()
        expect(await itemsPage.getItemCount()).toBe(0)
      })
    })
    

    Configuración de Playwright

    import { defineConfig, devices } from '@playwright/test'
    
    export default defineConfig({
      testDir: './tests/e2e',
      fullyParallel: true,
      forbidOnly: !!process.env.CI,
      retries: process.env.CI ? 2 : 0,
      workers: process.env.CI ? 1 : undefined,
      reporter: [
        ['html', { outputFolder: 'playwright-report' }],
        ['junit', { outputFile: 'playwright-results.xml' }],
        ['json', { outputFile: 'playwright-results.json' }]
      ],
      use: {
        baseURL: process.env.BASE_URL || 'http://localhost:3000',
        trace: 'on-first-retry',
        screenshot: 'only-on-failure',
        video: 'retain-on-failure',
        actionTimeout: 10000,
        navigationTimeout: 30000,
      },
      projects: [
        { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
        { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
        { name: 'webkit', use: { ...devices['Desktop Safari'] } },
        { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
      ],
      webServer: {
        command: 'npm run dev',
        url: 'http://localhost:3000',
        reuseExistingServer: !process.env.CI,
        timeout: 120000,
      },
    })
    

    Patrones de Pruebas Inestables (Flaky Tests)

    Cuarentena

    test('flaky: complex search', async ({ page }) => {
      test.fixme(true, 'Flaky - Issue #123')
      // código de prueba...
    })
    
    test('conditional skip', async ({ page }) => {
      test.skip(process.env.CI, 'Flaky in CI - Issue #123')
      // código de prueba...
    })
    

    Identificar Inestabilidad

    npx playwright test tests/search.spec.ts --repeat-each=10
    npx playwright test tests/search.spec.ts --retries=3
    

    Causas Comunes y Soluciones

    Condiciones de carrera:

    // Mal: asume que el elemento está listo
    await page.click('[data-testid="button"]')
    
    // Bien: locator con auto-espera
    await page.locator('[data-testid="button"]').click()
    

    Timing de red:

    // Mal: timeout arbitrario
    await page.waitForTimeout(5000)
    
    // Bien: esperar condición específica
    await page.waitForResponse(resp => resp.url().includes('/api/data'))
    

    Timing de animación:

    // Mal: hacer clic durante la animación
    await page.click('[data-testid="menu-item"]')
    
    // Bien: esperar estabilidad
    await page.locator('[data-testid="menu-item"]').waitFor({ state: 'visible' })
    await page.waitForLoadState('networkidle')
    await page.locator('[data-testid="menu-item"]').click()
    

    Gestión de Artefactos

    Capturas de Pantalla

    await page.screenshot({ path: 'artifacts/after-login.png' })
    await page.screenshot({ path: 'artifacts/full-page.png', fullPage: true })
    await page.locator('[data-testid="chart"]').screenshot({ path: 'artifacts/chart.png' })
    

    Trazas

    await browser.startTracing(page, {
      path: 'artifacts/trace.json',
      screenshots: true,
      snapshots: true,
    })
    // ... acciones de prueba ...
    await browser.stopTracing()
    

    Video

    // En playwright.config.ts
    use: {
      video: 'retain-on-failure',
      videosPath: 'artifacts/videos/'
    }
    

    Integración CI/CD

    # .github/workflows/e2e.yml
    name: E2E Tests
    on: [push, pull_request]
    
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with:
              node-version: 20
          - run: npm ci
          - run: npx playwright install --with-deps
          - run: npx playwright test
            env:
              BASE_URL: ${{ vars.STAGING_URL }}
          - uses: actions/upload-artifact@v4
            if: always()
            with:
              name: playwright-report
              path: playwright-report/
              retention-days: 30
    

    Plantilla de Reporte de Pruebas

    # Reporte de Pruebas E2E
    
    **Fecha:** YYYY-MM-DD HH:MM
    **Duración:** Xm Ys
    **Estado:** PASANDO / FALLANDO
    
    ## Resumen
    - Total: X | Pasaron: Y (Z%) | Fallaron: A | Inestables: B | Omitidas: C
    
    ## Pruebas Fallidas
    
    ### nombre-de-prueba
    **Archivo:** `tests/e2e/feature.spec.ts:45`
    **Error:** Expected element to be visible
    **Captura:** artifacts/failed.png
    **Corrección Recomendada:** [descripción]
    
    ## Artefactos
    - Reporte HTML: playwright-report/index.html
    - Capturas: artifacts/*.png
    - Videos: artifacts/videos/*.webm
    - Trazas: artifacts/*.zip
    

    Pruebas de Wallet / Web3

    test('wallet connection', async ({ page, context }) => {
      // Mock del proveedor de wallet
      await context.addInitScript(() => {
        window.ethereum = {
          isMetaMask: true,
          request: async ({ method }) => {
            if (method === 'eth_requestAccounts')
              return ['0x1234567890123456789012345678901234567890']
            if (method === 'eth_chainId') return '0x1'
          }
        }
      })
    
      await page.goto('/')
      await page.locator('[data-testid="connect-wallet"]').click()
      await expect(page.locator('[data-testid="wallet-address"]')).toContainText('0x1234')
    })
    

    Pruebas de Flujos Financieros / Críticos

    test('trade execution', async ({ page }) => {
      // Omitir en producción — dinero real
      test.skip(process.env.NODE_ENV === 'production', 'Skip on production')
    
      await page.goto('/markets/test-market')
      await page.locator('[data-testid="position-yes"]').click()
      await page.locator('[data-testid="trade-amount"]').fill('1.0')
    
      // Verificar preview
      const preview = page.locator('[data-testid="trade-preview"]')
      await expect(preview).toContainText('1.0')
    
      // Confirmar y esperar blockchain
      await page.locator('[data-testid="confirm-trade"]').click()
      await page.waitForResponse(
        resp => resp.url().includes('/api/trade') && resp.status() === 200,
        { timeout: 30000 }
      )
    
      await expect(page.locator('[data-testid="trade-success"]')).toBeVisible()
    })
    

    Alternatives

    Compare before choosing