Qué es Cypress, setup en TypeScript y primer test

Setup de Cypress 15 con TypeScript contra Serenity.is. Electron crasheó, Chrome se colgó, TypeScript rompió. Edge salvó el día. Proceso real.

Cypress Test Runner con test verde y página de login de Serenity.is visible en Edge 149
Test verde en modo interactivo: pasos del test a la izquierda, app a la derecha

Contexto

Ya publiqué frameworks completos con Selenium + Java, Playwright + TypeScript y Appium + Java. Cada uno tiene su serie documentada, su repo público y sus errores al descubierto.

Ahora arranco con Cypress.

No porque sea mejor o peor que los otros. Porque es parte del arsenal que necesito para cubrir el espectro de herramientas que el mercado pide. Selenium domina en demanda, Playwright crece rápido, y Cypress ocupa un lugar específico: E2E testing con una arquitectura distinta a las dos anteriores.

Este es el Post 1 de la serie. 17 posts planeados. Todo en TypeScript desde el primer commit.

Repo: github.com/cesarbeassuarez/cypress-typescript-framework

Qué es Cypress (breve)

Cypress es un framework de testing E2E basado en JavaScript/TypeScript. La diferencia fundamental con Selenium y Playwright es arquitectónica: Cypress corre dentro del browser, no por fuera controlándolo con un protocolo externo (WebDriver en Selenium, CDP en Playwright).

Eso tiene implicaciones prácticas que se van a ir viendo a lo largo de la serie. Por ahora, lo relevante es que la experiencia de desarrollo es distinta: el feedback es más inmediato, no hay waits explícitos, y el Test Runner te muestra la app y los pasos del test en la misma ventana.

No voy a hacer una tabla comparativa extensa acá. Las diferencias reales se ven en la práctica, no en teoría.

Decisiones técnicas

TypeScript desde el día 1. Ya trabajé con TypeScript en Playwright. No tiene sentido arrancar en JavaScript para migrar después. El repo se llama cypress-typescript-framework y tiene que ser coherente desde el primer commit.

Serenity.is como AUT. Es una aplicación demo con login, dashboard, formularios, y API. Suficiente para cubrir los escenarios que necesito en la serie. URL: https://demo.serenity.is.

Dashboard de Serenity.is mostrando tablero con Orders, Customers, Product Types y mapa de visitantes
Dashboard de Serenity.is — la AUT que voy a usar en toda la serie

Cursor como IDE. Primera vez usándolo. Es VS Code con AI integrada. Todo lo que funciona en VS Code funciona acá. Lo elegí para practicar con herramientas de AI-assisted coding, que cada vez se piden más en roles de QA.

Setup

Repo y proyecto

Creé cypress-typescript-framework en GitHub. Público, con README y .gitignore de Node. Lo cloné con SourceTree y lo abrí en Cursor.

Inicialicé el proyecto:

npm init -y

Instalación

npm install cypress typescript --save-dev

170 paquetes instalados, 0 vulnerabilidades. Cypress descarga un binario pesado, tardó unos minutos.

Primera apertura de Cypress

npx cypress open

Cypress 15.17.0 se verificó e instaló. Al elegir E2E Testing, generó automáticamente la estructura de archivos:

cypress/
├── e2e/
├── fixtures/
│   └── example.json
└── support/
    ├── commands.ts
    └── e2e.ts
cypress.config.ts
Estructura de archivos del proyecto cypress-typescript-framework en Cursor
Estructura final del proyecto después del setup

Detalle importante: Cypress detectó que TypeScript estaba instalado y generó todos los archivos como .ts. No tuve que renombrar nada. En versiones anteriores esto requería configuración manual.

Configuración

cypress.config.ts — lo reemplacé con una configuración limpia:

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    baseUrl: 'https://demo.serenity.is',
    supportFile: 'cypress/support/e2e.ts',
    specPattern: 'cypress/e2e/**/*.cy.ts',
  },
})

tsconfig.json — creado en la raíz:

{
  "compilerOptions": {
    "target": "ES2021",
    "lib": ["ES2021", "DOM", "DOM.Iterable"],
    "types": ["cypress"],
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["cypress/**/*.ts", "cypress.config.ts"],
  "exclude": ["node_modules"]
}

Un detalle sobre moduleResolution: originalmente puse "node", que es lo que recomiendan la mayoría de los tutoriales. Pero al correr el test, Cypress rompió con un error TS5107 diciendo que esa opción está deprecated. Lo cambié a "bundler" y funcionó.

Terminal mostrando error TS5107 moduleResolution node10 deprecated al correr Cypress con Edge
Error de TypeScript: moduleResolution "node" está deprecated

La solución fue cambiarlo a "bundler".

Primer test

cypress/e2e/login.cy.ts:

describe('Serenity.is Login Page', () => {
  it('should load the login page', () => {
    cy.visit('/Account/Login')
    cy.get('#LoginPanel').should('be.visible')
  })
})
Archivo login.cy.ts abierto en Cursor mostrando el primer test de Cypress contra Serenity.is
Primer test: cinco líneas, abrir el login y verificar que el panel sea visible

Cinco líneas. Abrir la página de login de Serenity.is y verificar que el panel de login sea visible.

Tres errores antes del primer test verde

Error 1: Electron crasheó. Correr npx cypress run (que usa Electron por defecto) dio: "We detected that the Electron Renderer process just crashed." El test falló con 0 segundos de duración y un ERR_FAILED (-2) loading 'about:blank'. No investigué mucho porque Electron no es un browser real — es el fallback de Cypress para cuando no hay otro disponible.

Terminal mostrando Electron Renderer process crashed al correr npx cypress run
Electron crasheó al intentar correr el test

Error 2: Chrome se colgó. npx cypress run --browser chrome mostró el warning de allowCypressEnv y se quedó ahí. Sin output, sin progreso, sin error. Pasaron más de dos minutos y nada. Cancelé con Ctrl+C.

Terminal mostrando npx cypress run con Chrome colgado sin output después del warning
Chrome se quedó ahí. Sin output, sin progreso, sin error

Error 3: TypeScript rompió la compilación. npx cypress run --browser edge por fin arrancó, pero Webpack no pudo compilar el test:

[tsl] ERROR
TS5107: Option 'moduleResolution=node10' is deprecated
and will stop functioning in TypeScript 7.0.
Error TS5107 moduleResolution node10 deprecated en Cypress con Webpack Compilation Error
El error real: moduleResolution "node" ya no funciona con TypeScript 5.x

El fix fue cambiar "moduleResolution": "node" a "moduleResolution": "bundler" en tsconfig.json.

Test verde

Después del fix, Edge corrió el test:

npx cypress run --browser edge
  Serenity.is Login Page
    ✓ should load the login page (9146ms)

  1 passing (9s)

  ┌──────────────────────────────────────┐
  │ Tests:        1                      │
  │ Passing:      1                      │
  │ Failing:      0                      │
  └──────────────────────────────────────┘

    ✓  All specs passed!
Terminal mostrando All specs passed con 1 test passing en Cypress headless con Edge 149
Primer test verde en headless después de resolver los tres errores

También lo corrí en modo interactivo:

npx cypress open --browser edge

El Test Runner abrió Edge, hice click en login.cy.ts, y el test pasó. A la izquierda los pasos (visit, get, assert), a la derecha la app de Serenity.is con el formulario de login visible.

Cypress Test Runner en Edge mostrando test verde con login de Serenity.is y pasos visit, get, assert
Modo interactivo: el equivalente a --ui de Playwright

La diferencia con npx cypress run (headless, para CI/CD) vs npx cypress open (interactivo, para desarrollo) es la misma que npx playwright test vs npx playwright test --ui. El interactivo te da time-travel: podés hacer hover sobre cada paso y ver el estado del DOM en ese momento.

Versiones

Herramienta Versión
Cypress 15.17.0
TypeScript 5.x (latest)
Node.js v24.14.0
Edge 149
Cursor latest

Estado actual

Tengo:

  • Proyecto Cypress + TypeScript configurado
  • Primer test E2E corriendo contra Serenity.is
  • Ejecución headless (Edge) y modo interactivo funcionando
  • Repo público actualizado

Estructura del proyecto

cypress-typescript-framework/
├── cypress/
│   ├── e2e/
│   │   └── login.cy.ts
│   ├── fixtures/
│   │   └── example.json
│   └── support/
│       ├── commands.ts
│       └── e2e.ts
├── .gitignore
├── cypress.config.ts
├── package.json
├── package-lock.json
├── README.md
└── tsconfig.json

Próximo post: selectores, comandos y login completo en Serenity.is.