Ya ejecutas Cypress para pruebas de extremo a extremo. Ahora quieres llamar a una API directamente, verificar el código de estado y hacer aserciones sobre el JSON sin pasar por la interfaz de usuario. Cypress lo permite con cy.request(), que envía solicitudes HTTP reales desde Node, fuera del navegador, para probar endpoints de forma aislada o preparar el estado antes de una prueba de UI.
En esta guía verás cómo probar APIs con Cypress: usar cy.request(), validar respuestas, encadenar solicitudes para reutilizar tokens de autenticación y simular tráfico del navegador con cy.intercept(). También verás cuándo Cypress encaja bien para pruebas de API y cuándo conviene usar una herramienta nativa de API.
¿Por qué probar APIs con Cypress?
La mayoría de las suites de Cypress controlan un navegador. Pero muchas verificaciones de UI dependen de la API:
- ¿
/logindevuelve un token? - ¿
/usersdevuelve la estructura esperada? - ¿Un
POSTcrea el registro correcto?
Probar esos endpoints directamente tiene dos ventajas prácticas:
- Las pruebas son más rápidas: no hay renderizado, selección de elementos ni esperas de UI.
-
Puedes preparar datos de prueba: en vez de completar formularios para crear datos, haces un
POSTy pasas directo a la aserción importante.
Si Cypress ya está en tu stack, añadir pruebas de API no requiere otro runner. Puedes escribirlas en los mismos archivos de especificación, con las mismas aserciones expect, y ejecutarlas en la misma pipeline de CI.
Conceptos básicos de cy.request()
cy.request() realiza una solicitud HTTP y devuelve la respuesta. Se ejecuta desde el proceso de Node de Cypress, no desde el navegador, por lo que no está limitado por CORS ni por la política de mismo origen.
Puedes usarlo de varias formas:
cy.request(url)
cy.request(url, body)
cy.request(method, url)
cy.request(method, url, body)
cy.request(options)
La llamada más simple hace un GET por defecto:
cy.request('https://jsonplaceholder.typicode.com/users')
Para controlar método, headers, query params o body, usa un objeto de opciones:
cy.request({
method: 'POST',
url: 'https://jsonplaceholder.typicode.com/posts',
headers: {
'Content-Type': 'application/json'
},
body: {
title: 'API test',
body: 'created from Cypress',
userId: 1
}
})
Opciones útiles:
-
method: verbo HTTP (GET,POST,PUT,PATCH,DELETE, etc.). Por defecto esGET. -
url: endpoint de la API. Es obligatorio. -
body: cuerpo de la solicitud. Cypress serializa objetos a JSON. -
headers: encabezados HTTP. -
auth: credenciales para Autenticación Básica HTTP. -
qs: parámetros de query string como objeto. -
failOnStatusCode: usafalsecuando quieres validar respuestas4xxo5xxsin que Cypress falle automáticamente.
Ejemplo de prueba negativa:
cy.request({
method: 'GET',
url: 'https://jsonplaceholder.typicode.com/users/99999',
failOnStatusCode: false
}).then((response) => {
expect(response.status).to.eq(404)
})
Por defecto, cy.request() falla si la respuesta no es 2xx o 3xx. Por eso failOnStatusCode: false es necesario cuando esperas errores controlados.
Aserciones sobre estado, body y headers
cy.request() devuelve un objeto de respuesta. Encadena .then() para inspeccionarlo:
cy.request('https://jsonplaceholder.typicode.com/users').then((response) => {
// response.status
// response.body
// response.headers
// response.duration
})
Propiedades principales:
-
status: código HTTP. -
body: cuerpo de la respuesta. Si elContent-Typees JSON, Cypress lo parsea como objeto JavaScript. -
headers: encabezados de respuesta. -
duration: tiempo de respuesta en milisegundos.
Ejemplo completo:
describe('Users API', () => {
it('returns a list of users', () => {
cy.request('https://jsonplaceholder.typicode.com/users').then((response) => {
expect(response.status).to.eq(200)
expect(response.body).to.be.an('array')
expect(response.body).to.have.length(10)
expect(response.body[0]).to.have.property('email')
})
})
})
Como response.body ya está parseado, puedes usar Chai para validar tipos, longitudes, propiedades anidadas o valores exactos:
cy.request('https://jsonplaceholder.typicode.com/users/1').then((response) => {
expect(response.status).to.eq(200)
expect(response.body).to.include.keys(['id', 'name', 'email'])
expect(response.body.address).to.have.property('city')
})
También puedes validar headers:
cy.request('https://jsonplaceholder.typicode.com/users').then((response) => {
expect(response.headers['content-type']).to.include('application/json')
})
Para profundizar en la estructura de estas verificaciones, consulta la guía sobre aserción de API y las mejores prácticas de pruebas de API.
Encadenar solicitudes y reutilizar un token de autenticación
En APIs reales, normalmente necesitas autenticarte antes de llamar a endpoints protegidos. El patrón es:
- Hacer login.
- Leer el token de la respuesta.
- Usar ese token en las siguientes solicitudes.
Ejemplo:
describe('Authenticated API flow', () => {
it('logs in and fetches a protected resource', () => {
cy.request({
method: 'POST',
url: 'https://api.example.com/login',
body: {
email: 'user@example.com',
password: 'secret'
}
}).then((loginResponse) => {
expect(loginResponse.status).to.eq(200)
const token = loginResponse.body.token
cy.request({
method: 'GET',
url: 'https://api.example.com/profile',
headers: {
Authorization: `Bearer ${token}`
}
}).then((profileResponse) => {
expect(profileResponse.status).to.eq(200)
expect(profileResponse.body).to.have.property('email', 'user@example.com')
})
})
})
})
Si varias pruebas necesitan el mismo token, mueve el login a un beforeEach:
describe('Authenticated API tests', () => {
beforeEach(() => {
cy.request({
method: 'POST',
url: 'https://api.example.com/login',
body: {
email: 'user@example.com',
password: 'secret'
}
}).then((response) => {
Cypress.env('authToken', response.body.token)
})
})
it('fetches the profile', () => {
cy.request({
method: 'GET',
url: 'https://api.example.com/profile',
headers: {
Authorization: `Bearer ${Cypress.env('authToken')}`
}
}).then((response) => {
expect(response.status).to.eq(200)
})
})
})
Este patrón es útil cuando una llamada alimenta datos a la siguiente, como en una prueba de integración de API.
Usar cy.intercept() para stubbing
cy.request() llama a la API real. En cambio, cy.intercept() intercepta solicitudes que tu aplicación front-end hace desde el navegador.
La diferencia es importante:
-
cy.request()prueba la API directamente. -
cy.intercept()observa o simula las solicitudes del navegador. -
cy.intercept()no interceptacy.request(), porquecy.request()no pasa por el navegador.
Usa cy.intercept() cuando quieres probar cómo reacciona la UI ante una respuesta específica de la API.
Ejemplo de stub:
cy.intercept('GET', '/api/users', {
statusCode: 200,
body: [{ id: 1, name: 'Ada' }]
})
Ahora cualquier solicitud del navegador a /api/users devolverá esa respuesta fija.
Esto es útil para probar casos difíciles de reproducir contra un backend real:
- Lista vacía.
- Error
500. - Respuesta lenta.
- Payload con valores límite.
Ejemplo con error:
it('shows an error banner when the API fails', () => {
cy.intercept('GET', '/api/users', {
statusCode: 500,
body: { message: 'Server error' }
}).as('getUsers')
cy.visit('/dashboard')
cy.wait('@getUsers')
.its('response.statusCode')
.should('eq', 500)
cy.contains('Something went wrong').should('be.visible')
})
Configura siempre la intercepción antes de la acción que dispara la solicitud. Si llamas a cy.intercept() después de cy.visit() o después del clic que inicia la petición, puede que Cypress no capture nada.
Si estás decidiendo cuándo simular una respuesta o un servicio completo, revisa estas guías sobre simulación de API y stubbing de API vs. mocking de API.
Cuándo usar Cypress para pruebas de API
Cypress encaja bien cuando las verificaciones de API forman parte de una suite de UI.
Úsalo para:
- Preparar datos antes de una prueba e2e.
- Verificar endpoints de los que depende la interfaz.
- Hacer smoke tests rápidos de API.
- Simular respuestas con
cy.intercept()para validar estados de UI. - Reutilizar el mismo runner y la misma pipeline de CI.
Ejemplo típico: crear un usuario vía API y luego verificarlo en la UI.
it('creates a user through API and verifies it in the UI', () => {
cy.request({
method: 'POST',
url: 'https://api.example.com/users',
body: {
name: 'Ada Lovelace',
email: 'ada@example.com'
}
}).then((response) => {
expect(response.status).to.eq(201)
cy.visit(`/users/${response.body.id}`)
cy.contains('Ada Lovelace').should('be.visible')
cy.contains('ada@example.com').should('be.visible')
})
})
Cuándo una herramienta nativa de API encaja mejor
Cypress se diseñó principalmente para pruebas en navegador. Aunque cy.request() es útil, una suite grande e independiente de API puede volverse incómoda.
Limitaciones comunes:
- No hay constructor visual de solicitudes: cada request se escribe como código.
- Gestionar headers, bodies y query params a mano se vuelve repetitivo con muchos endpoints.
- Para pipelines solo de API, Cypress añade sobrecarga porque sigue siendo una herramienta orientada al navegador.
- No hay una definición compartida de API integrada para diseño, documentación y pruebas.
Aquí puede encajar mejor una herramienta nativa de API. Apidog está construido alrededor de la API: diseñas endpoints, creas escenarios de prueba, defines entornos, configuras autenticación y haces aserciones visuales para los casos comunes.
Para CI, la CLI de Apidog ejecuta escenarios guardados sin interfaz gráfica:
npm install -g apidog-cli
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
Parámetros principales:
-
-t: escenario o suite guardado. -
-e: entorno. -
-r: formatos de reporte (cli,html,json,junit).
La salida JUnit se integra con la mayoría de paneles de CI. También puedes añadir:
-
-do--iteration-data: ejecutar con datos desde un archivo. -
--upload-report: subir resultados al espacio de trabajo.
La CLI ejecuta escenarios guardados; no es un cliente interactivo para enviar solicitudes manuales.
Una regla práctica:
- Usa
cy.request()cuando las pruebas de API apoyan tus pruebas de navegador. - Usa una herramienta nativa de API cuando las pruebas de API son el foco principal.
Si estás comparando opciones, revisa estas listas de herramientas de automatización de pruebas de API que se ejecutan en CI/CD y las 30 mejores herramientas de prueba de API.
Preguntas frecuentes
¿cy.request() se ejecuta en el navegador?
No. cy.request() se ejecuta desde el proceso de Node de Cypress, fuera del navegador. Por eso no está bloqueado por CORS ni por la política de mismo origen.
También por eso cy.intercept() no puede interceptarlo. Si necesitas capturar una solicitud del navegador, dispara la acción desde tu aplicación y usa cy.intercept().
¿Cómo pruebo una respuesta 400 o 404 sin que Cypress falle?
Usa failOnStatusCode: false:
cy.request({
method: 'GET',
url: 'https://api.example.com/missing-resource',
failOnStatusCode: false
}).then((response) => {
expect(response.status).to.eq(404)
})
Sin esa opción, Cypress falla automáticamente con cualquier respuesta que no sea 2xx o 3xx.
¿Puedo usar cy.request() para iniciar sesión antes de una prueba de UI?
Sí. Es un patrón común para acelerar pruebas.
Puedes enviar un POST al endpoint de login, leer el token desde response.body y guardarlo en Cypress.env(), localStorage o una cookie. Así evitas pasar por el formulario de login en cada prueba.
cy.request({
method: 'POST',
url: 'https://api.example.com/login',
body: {
email: 'user@example.com',
password: 'secret'
}
}).then((response) => {
window.localStorage.setItem('token', response.body.token)
})
¿Cuál es la diferencia entre cy.request() y cy.intercept()?
cy.request() envía una solicitud HTTP real desde Node y devuelve la respuesta real. Úsalo para probar la API o preparar datos.
cy.intercept() observa o simula solicitudes que el front-end hace desde el navegador. Úsalo para controlar lo que recibe la UI durante una prueba.
¿Debo usar Cypress o una herramienta dedicada para pruebas de API?
Usa Cypress cuando las verificaciones de API apoyan una suite de pruebas de navegador existente.
Para una suite grande de API, pipelines dedicadas de API o una definición compartida entre diseño, documentación y pruebas, una herramienta nativa de API como Apidog suele encajar mejor. También puedes revisar estas mejores prácticas de pruebas de API para estructurar tu estrategia.
Top comments (0)