# Configuración del reporter de Vitest

> Cada opción de @probara/vitest-reporter con su variable de entorno, su tipo y su valor por defecto, cómo se combinan, y cómo se comporta el reporter en la red y en modo watch.

Cada ajuste de `@probara/vitest-reporter` es una opción del reporter en la configuración de Vitest,
y la mayoría tiene también una variable de entorno `PROBARA_*`. Guarda el token en el entorno, el
proyecto en la configuración (o en el entorno), y el resto donde encaje en tu pipeline.

## Camino rápido

1. Crea un token de aplicación desde la tarjeta **Vitest** en **Workspace › Integraciones**
   ([primeros pasos](https://docs.probara.net/es/developers/ci-integrations/vitest/#1-crea-un-token-de-aplicación)) y
   guárdalo como un secreto de CI llamado `PROBARA_API_TOKEN` (cada
   [proveedor de CI](https://docs.probara.net/es/developers/ci-integrations/vitest/ci-providers/) indica dónde).
2. Define el ID del Proyecto: `projectId` en las opciones del reporter, o `PROBARA_PROJECT`. Un ID
   del Proyecto es una letra mayúscula seguida de mayúsculas o dígitos (`SHOP`, `E2E`): cualquier
   otro valor desactiva el envío con un error.
3. Todo lo demás tiene un valor por defecto. La ejecución toma el nombre del build de CI, y su rama,
   su commit y la URL del build llegan solos desde el CI.

```ts
// vitest.config.mts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    reporters: ['default', ['@probara/vitest-reporter', { projectId: 'SHOP' }]],
  },
});
```

Mantén `'default'` en la lista: una lista `reporters` sustituye a la del propio Vitest, y `default`
es el que lees en la terminal. La entrada del reporter es la misma en cualquier archivo del que
Vitest lea su configuración (`vitest.config.ts`, la sección `test` de `vite.config.ts`...). El
reporter añade su propio archivo de setup y su runner a cada proyecto de Vitest de la
configuración, así que no hay nada que añadir a `setupFiles` ni a `runner`.

No pongas el token en la configuración de Vitest: la configuración se sube al repositorio.
`apiToken` existe para el código que lee el token de su propio almacén de secretos.

## Fuentes y precedencia

Gana la primera fuente que define un valor:

| Orden | Fuente                                                | Ejemplo                                           |
| ----- | ----------------------------------------------------- | ------------------------------------------------- |
| 1     | Una opción del reporter en la configuración de Vitest | `{ run: { name: 'Release 2.4' } }`                |
| 2     | Una variable `PROBARA_*`                              | `PROBARA_RUN_NAME=Nightly`                        |
| 3     | La detección del CI                                   | `CI #42` a partir del workflow y el número de run |
| 4     | El valor por defecto                                  | `Automated run 2026-09-29 14:05 UTC`              |

- Una opción con valor `undefined` nunca oculta su variable, y una variable vacía cuenta como no
  definida. Para que una variable pueda sustituir a una opción, omite la opción (o pasa
  `process.env.X ?? default`).
- Los booleanos aceptan `true`, `1`, `yes`, `on` y `false`, `0`, `no`, `off`. Las listas se separan
  con comas en las variables (`PROBARA_RUN_TAGS=nightly,smoke`).
- La detección del CI solo rellena el nombre de la ejecución y su origen (rama, commit, URL del
  build, y en GitHub Actions la ejecución del workflow que agrupa los jobs en paralelo). Lo que rellena cada CI está en
  [Proveedores de CI](https://docs.probara.net/es/developers/ci-integrations/vitest/ci-providers/).

Las opciones y las variables se pueden combinar. Esta configuración define el proyecto y las
etiquetas:

```ts
reporters: [
  'default',
  ['@probara/vitest-reporter', { projectId: 'SHOP', run: { tags: ['unit', 'nightly'] } }],
],
```

y el pipeline añade el entorno y el nombre de la ejecución:

```bash
PROBARA_ENVIRONMENT=staging PROBARA_RUN_NAME=Nightly npx vitest run
```

## Opciones

| Opción                   | Variable                       | Tipo                                    | Valor por defecto                                             | Qué hace                                                                                                                                                                                                   |
| ------------------------ | ------------------------------ | --------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                | `PROBARA_ENABLED`              | `boolean`                               | activado                                                      | `false` desactiva el envío: no se envía ni se registra nada                                                                                                                                                |
| `apiToken`               | `PROBARA_API_TOKEN`            | `string`                                | ninguno (obligatorio)                                         | El token de aplicación. Guárdalo en el entorno                                                                                                                                                             |
| `projectId`              | `PROBARA_PROJECT`              | `string`                                | ninguno (obligatorio)                                         | El ID del Proyecto (mayúsculas y dígitos), por ejemplo `SHOP`                                                                                                                                              |
| `baseUrl`                | `PROBARA_BASE_URL`             | `string`                                | `https://app.probara.net`                                     | El Probara al que se envía ([autoalojado](#probara-autoalojado))                                                                                                                                           |
| `run.ulid`               | `PROBARA_RUN_ULID`             | `string`                                | ninguno: una ejecución nueva                                  | Reportar en una ejecución existente ([una ejecución existente](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#una-ejecución-existente))                                                        |
| `run.name`               | `PROBARA_RUN_NAME`             | `string`                                | el nombre del build de CI, si no `Automated run <date>`       | Nombre de una ejecución nueva ([la ejecución](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#la-ejecución))                                                                                    |
| `run.description`        | `PROBARA_RUN_DESCRIPTION`      | `string`                                | ninguno                                                       | Descripción de una ejecución nueva                                                                                                                                                                         |
| `run.environment`        | `PROBARA_ENVIRONMENT`          | `string`                                | ninguno                                                       | Entorno de una ejecución nueva por nombre, creado si no coincide ninguno                                                                                                                                   |
| `run.environmentId`      | `PROBARA_ENVIRONMENT_ID`       | `string`                                | ninguno                                                       | Entorno de una ejecución nueva por ULID                                                                                                                                                                    |
| `run.milestone`          | `PROBARA_MILESTONE`            | `string`                                | ninguno                                                       | Hito de una ejecución nueva por ID visible (`M-3`) o nombre                                                                                                                                                |
| `run.milestoneId`        | `PROBARA_MILESTONE_ID`         | `string`                                | ninguno                                                       | Hito de una ejecución nueva por ULID                                                                                                                                                                       |
| `run.plan`               | `PROBARA_PLAN`                 | `string`                                | ninguno                                                       | Plan de pruebas de una ejecución nueva por ID visible (`PLAN-2`) o nombre: la ejecución empieza con sus casos                                                                                              |
| `run.configurations`     | `PROBARA_CONFIGURATIONS`       | `{ group, name }[]`                     | ninguno                                                       | Configuraciones de una ejecución nueva por nombre (`Browser=Chrome,OS=Linux`), cada grupo una vez                                                                                                          |
| `run.configurationUlids` | `PROBARA_CONFIGURATION_ULIDS`  | `string[]`                              | ninguno                                                       | Configuraciones de una ejecución nueva por ULID                                                                                                                                                            |
| `run.tags`               | `PROBARA_RUN_TAGS`             | `string[]`                              | ninguno                                                       | Etiquetas de una ejecución nueva                                                                                                                                                                           |
| `run.ulids`              | `PROBARA_RUN_ULIDS`            | `Record<string, string>`                | ninguno                                                       | La ejecución que se reutiliza en cada proyecto (`WEB=<ulid>,API=<ulid>`)                                                                                                                                   |
| `projects`               | `PROBARA_PROJECTS`             | `string[]`                              | ninguno                                                       | Otros proyectos a los que pueden ir los resultados (`WEB,API`) ([varios proyectos](https://docs.probara.net/es/developers/ci-integrations/vitest/sharding/#varios-proyectos-de-probara))                                           |
| `source`                 | —                              | `false \| objeto (campos GitHub abajo)` | detectado del CI                                              | `false` no envía origen; un objeto sustituye los campos detectados uno a uno ([origen](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#origen-de-la-ejecución))                                 |
| `source.branch`          | `PROBARA_BRANCH`               | `string`                                | detectado del CI                                              | Rama del origen de la ejecución                                                                                                                                                                            |
| `source.commit`          | `PROBARA_COMMIT`               | `string`                                | detectado del CI                                              | Commit del origen de la ejecución                                                                                                                                                                          |
| `source.buildUrl`        | `PROBARA_BUILD_URL`            | `string`                                | detectado del CI                                              | URL del build de CI del origen de la ejecución                                                                                                                                                             |
| `createMissingCases`     | `PROBARA_CREATE_MISSING_CASES` | `boolean`                               | `true`                                                        | Crear un caso para una prueba que no coincide con ninguno                                                                                                                                                  |
| `suiteUlid`              | `PROBARA_SUITE_ULID`           | `string`                                | la raíz del proyecto                                          | Suite bajo la que van los casos creados                                                                                                                                                                    |
| `closeRun`               | `PROBARA_CLOSE_RUN`            | `boolean`                               | `true` para una ejecución nueva, `false` para una reutilizada | Cerrar la ejecución al final (nunca en modo watch) ([cierre](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#cierre))                                                                           |
| `closeRuns`              | —                              | `Record<string, boolean>`               | ninguno                                                       | Cerrar la ejecución de cada proyecto (`{ SHOP: true, WEB: false }`) cuando `closeRun` no está definido                                                                                                     |
| `uploadAttachments`      | `PROBARA_UPLOAD_ATTACHMENTS`   | `boolean`                               | `true`                                                        | `false` no sube ningún archivo ([adjuntos](https://docs.probara.net/es/developers/ci-integrations/vitest/steps-and-attachments/#probaraattach))                                                                                    |
| `keyIncludesFile`        | `PROBARA_KEY_INCLUDES_FILE`    | `boolean`                               | `true`                                                        | Empezar cada clave de automatización con el archivo de prueba ([`keyIncludesFile`](#keyincludesfile))                                                                                                      |
| `captureOutput`          | `PROBARA_CAPTURE_OUTPUT`       | `boolean`                               | `false`                                                       | Adjuntar la salida de consola de cada intento como `stdout.log` y `stderr.log` ([`captureOutput`](#captureoutput))                                                                                         |
| `attachScreenshots`      | `PROBARA_ATTACH_SCREENSHOTS`   | `boolean`                               | `true`                                                        | Adjuntar a su intento las capturas de pantalla de los fallos de una prueba de navegador; `false` las desactiva ([`attachScreenshots`](#attachscreenshots))                                                 |
| `issueUrlTemplate`       | `PROBARA_ISSUE_URL_TEMPLATE`   | `string`                                | ninguno                                                       | La URL en la que se convierte cada `probara.issue(id)`, con `%s` para el ID ([`issueUrlTemplate`](#issueurltemplate))                                                                                      |
| `runCasesOnly`           | `PROBARA_RUN_CASES_ONLY`       | `boolean`                               | `false`                                                       | Ejecutar solo las pruebas de los casos de `run.ulid` ([`runCasesOnly`](#runcasesonly))                                                                                                                     |
| `statusMapping`          | `PROBARA_STATUS_MAPPING`       | `{ passed, failed, skipped, blocked }`  | ninguno                                                       | Enviar un estado como otro (`failed=blocked`) ([estados](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#mapeo-y-filtro-de-estados))                                                            |
| `statusFilter`           | `PROBARA_STATUS_FILTER`        | `string[]`                              | ninguno                                                       | No enviar ningún resultado con estos estados, después del mapeo (`skipped`)                                                                                                                                |
| `resultsFile`            | `PROBARA_RESULTS_FILE`         | `string`                                | ninguno                                                       | Archivo JSON para lo que no se pudo enviar ([archivo de resultados](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#archivo-de-resultados))                                                     |
| `assignFailedTo`         | `PROBARA_ASSIGN_FAILED_TO`     | `string[]`                              | ninguno                                                       | Asignar cada resultado fallido sin responsable a uno de estos miembros, por turnos ([asignar resultados fallidos](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#asignar-resultados-fallidos)) |
| `debug`                  | `PROBARA_DEBUG`                | `boolean`                               | `false`                                                       | Registrar cada petición ([`PROBARA_DEBUG`](https://docs.probara.net/es/developers/ci-integrations/vitest/troubleshooting/#probara_debug))                                                                                          |
| `rootDir`                | —                              | `string`                                | la raíz de Vitest                                             | Directorio respecto al que se expresan las rutas de las claves de automatización                                                                                                                           |
| `chunkSize`              | —                              | `number`                                | `500`                                                         | Resultados por petición de informe, de 1 a 500                                                                                                                                                             |
| `timeoutMs`              | —                              | `number`                                | `30000`                                                       | Tiempo máximo de un intento HTTP, en milisegundos, de 1 a 600000 ([tiempos máximos](#tiempos-máximos))                                                                                                     |
| `maxRetries`             | —                              | `number`                                | `4`                                                           | Reintentos de una petición fallida, de 0 a 10 ([reintentos y backoff](#reintentos-y-backoff))                                                                                                              |
| `attachmentConcurrency`  | —                              | `number`                                | `2`                                                           | Resultados cuyos adjuntos se suben a la vez, de 1 a 8                                                                                                                                                      |

`rootDir` toma por defecto el `root` de Vitest, que es el directorio en el que se ejecuta `vitest`
salvo que la configuración o `--root` definan otro.

En GitHub Actions el origen también recibe estos campos, detectados de las variables `GITHUB_*`:

| Opción                     | Variable | Tipo     | Por defecto                 | Qué hace                                                                        |
| -------------------------- | -------- | -------- | --------------------------- | ------------------------------------------------------------------------------- |
| `source.provider`          | —        | `string` | detectado de GitHub Actions | `github_actions` (detectado) u `other`                                          |
| `source.repository`        | —        | `string` | detectado de GitHub Actions | Repositorio del origen de la ejecución, `owner/name`                            |
| `source.commitAuthor`      | —        | `string` | detectado de GitHub Actions | Quién activó el build                                                           |
| `source.pullRequestNumber` | —        | `number` | detectado de GitHub Actions | Pull request del build                                                          |
| `source.workflow`          | —        | `string` | detectado de GitHub Actions | Workflow de CI del origen de la ejecución                                       |
| `source.ciRunId`           | —        | `string` | detectado de GitHub Actions | Id de la ejecución de CI: los jobs de un mismo workflow comparten una ejecución |
| `source.ciRunAttempt`      | —        | `number` | detectado de GitHub Actions | Intento de la ejecución de CI: una re-ejecución va a una ejecución propia       |
| `source.ciJob`             | —        | `string` | detectado de GitHub Actions | Job de CI del origen de la ejecución                                            |

### Opciones de runtime

Son puntos de extensión para código (una prueba del reporter, un logger propio), no ajustes de un
job. No tienen variable:

| Opción   | Tipo                           | Valor por defecto            | Qué hace                                                            |
| -------- | ------------------------------ | ---------------------------- | ------------------------------------------------------------------- |
| `logger` | `{ debug, info, warn, error }` | líneas `[probara]` en stderr | Dónde registra el reporter                                          |
| `env`    | `Record<string, string>`       | `process.env`                | De dónde se leen las variables `PROBARA_*` y las del CI             |
| `fetch`  | `function`                     | el `fetch` global            | El cliente HTTP ([tu propio cliente HTTP](#tu-propio-cliente-http)) |
| `sleep`  | `function`                     | `setTimeout`                 | Las esperas entre reintentos                                        |
| `random` | `function`                     | `Math.random`                | La variación aleatoria del backoff                                  |
| `now`    | `function`                     | la hora actual               | El reloj del nombre por defecto y de las fechas de `Retry-After`    |

El logger por defecto escribe a través del propio logger de Vitest, en stderr: stdout sigue siendo
de Vitest, así que un reporter que imprime JSON ahí nunca recibe una línea del reporter.

### Opciones desconocidas

Una opción que el reporter no conoce se omite con una advertencia, y la ejecución se reporta igual:

```ts
reporters: ['default', ['@probara/vitest-reporter', { captureOutputs: true }]],
```

```text
$ npx vitest run
[probara] Ignored the unknown option "captureOutputs" of @probara/vitest-reporter
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1
```

## Ajustes propios del reporter de Vitest

### `keyIncludesFile`

Cada prueba se asocia a su caso por una clave de automatización: el archivo de prueba relativo a
`rootDir` (la raíz de Vitest), y después los bloques `describe` y el título, cada uno tras `>`
entre espacios, sin los IDs de caso: `tests/cart.test.ts > cart > adds an item`. Es la clave que
`probara import junit` da a la misma prueba sobre la salida JUnit de Vitest, que siempre nombra el
archivo.

`keyIncludesFile: false` (`PROBARA_KEY_INCLUDES_FILE=false`) omite el archivo en todas las claves.
Úsalo cuando tus casos ya tengan claves sin el archivo, creadas a mano o por otra herramienta, para
que cada prueba conserve su caso. Una prueba recibe entonces la misma clave que otra con los mismos
bloques `describe` y el mismo título en otro archivo.

```ts
reporters: ['default', ['@probara/vitest-reporter', { keyIncludesFile: false }]],
```

```json
[
  { "automationKey": "cart > adds an item", "caseDisplayId": "SHOP-12" },
  { "automationKey": "cart > removes an item" },
  { "automationKey": "login > logs in with a valid password" }
]
```

Cambiar `keyIncludesFile` cambia todas las claves: las pruebas que no nombran ningún caso en sus
títulos crean entonces casos nuevos. Un caso que crea el informe va a una suite con el nombre del
archivo de prueba o, con `keyIncludesFile: false`, con el de su `describe` más externo, si lo tiene.
Los proyectos de Vitest no añaden nada a la clave
([vincular](https://docs.probara.net/es/developers/ci-integrations/vitest/linking/#claves-de-automatización)).

### `captureOutput`

`captureOutput: true` (`PROBARA_CAPTURE_OUTPUT=true`) adjunta lo que cada intento escribe con
`console.log`, `console.info` y `console.debug` como `stdout.log`, y con `console.warn` y
`console.error` como `stderr.log`. Vitest sigue imprimiendo la salida como siempre. No necesita
nada más: ni archivo de setup ni cambios en las pruebas.

```ts
reporters: ['default', ['@probara/vitest-reporter', { captureOutput: true }]],
```

Lo que se captura y lo que no está en
[salida de consola](https://docs.probara.net/es/developers/ci-integrations/vitest/steps-and-attachments/#salida-de-consola).

### `attachScreenshots`

En modo navegador, Vitest toma una captura de pantalla cuando una prueba falla, y el reporter la
adjunta al intento fallido, como `image/png`. `attachScreenshots: false`
(`PROBARA_ATTACH_SCREENSHOTS=false`) deja fuera las capturas. Una prueba que se ejecuta en Node no
tiene ninguna
([capturas de pantalla de los fallos](https://docs.probara.net/es/developers/ci-integrations/vitest/steps-and-attachments/#capturas-de-pantalla-de-los-fallos)).

### `issueUrlTemplate`

`probara.issue(id)` nombra una incidencia de tu gestor: `issueUrlTemplate` la convierte en un enlace
del resultado, con el ID como nombre y el ID codificado para URL en lugar de `%s`
(`https://jira.example.com/browse/%s`). La plantilla es una URL `http` o `https` con `%s`; cualquier
otro valor desactiva el envío con un error. Sin plantilla, las incidencias se omiten con una
advertencia
([enlaces e incidencias](https://docs.probara.net/es/developers/ci-integrations/vitest/metadata/#enlaces-e-incidencias)).

### `runCasesOnly`

`runCasesOnly: true` (o `PROBARA_RUN_CASES_ONLY=true`) ejecuta solo las pruebas de los casos de la
ejecución `run.ulid` (`PROBARA_RUN_ULID`), y reporta en esa ejecución, dejándola abierta. No va
nada más en la configuración: el archivo de setup que el reporter añade a cada proyecto de Vitest
se encarga de omitir las demás. Actívalo en cada job con las variables en lugar de en la
configuración: con la opción en la configuración, cada job sin un ULID de ejecución advierte y
ejecuta todas las pruebas.
[Selección de pruebas](https://docs.probara.net/es/developers/ci-integrations/vitest/run-selection/) tiene las reglas de
asociación y todos los casos en los que no selecciona, incluidos el modo navegador y los shards que
escriben un blob.

## Qué pasa con cada configuración

| Configuración                                     | Qué hace el reporter                                                                           |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Sin token ni proyecto, o con `enabled: false`     | Queda desactivado y en silencio: no se envía ni se registra nada (salvo en debug).             |
| Solo uno de los dos, o un valor no válido         | El envío queda desactivado; se registra cada problema, y las pruebas se ejecutan como siempre. |
| Un token y un proyecto, todos los valores válidos | Reporta.                                                                                       |

Un valor del tipo incorrecto (como `run.tags: 'nightly'` en lugar de una lista) es un valor no
válido:

```ts
reporters: ['default', ['@probara/vitest-reporter', { run: { tags: 'nightly' } }]],
```

```text
$ npx vitest run
[probara] Probara reporting is off: run.tags must be a list of strings
```

Los problemas nombran la opción o la variable afectada, nunca su valor, así que un token nunca
aparece. El reporter nunca hace fallar la ejecución: cualquier cosa que salga mal al reportar es
una línea `[probara]` en stderr, y el código de salida de `vitest` sigue siendo el que dan las
pruebas.

## Desactivar el envío

Define `enabled: false` o `PROBARA_ENABLED=false`, u omite el token: el reporter no envía nada y
queda en silencio. Los builds de pull requests desde forks no reciben secretos, así que no reportan
nada por sí solos. El reporter sigue añadiendo su archivo de setup, así que los helpers
`probara.*` siguen registrando y no se envía nada
([cómo viajan los metadatos](https://docs.probara.net/es/developers/ci-integrations/vitest/metadata/#cómo-viajan-los-metadatos)).
Para conservar lo que una ejecución no pudo enviar, incluso con el envío desactivado, define un
[archivo de resultados](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#archivo-de-resultados).

## Probara autoalojado

Apunta el reporter a otro Probara con `baseUrl` o `PROBARA_BASE_URL`: la URL de la aplicación, sin
ruta. Las peticiones van a ese host y a ningún otro. Para proxies y autoridades de certificación
privadas, consulta [red](#red).

## Red

El reporter se comunica por HTTPS con un único host, la URL base (`https://app.probara.net` por
defecto), desde el proceso principal de Vitest: ni los workers de prueba ni los navegadores del
modo navegador llaman nunca a Probara.

### Cuándo se hacen las peticiones

| Cuándo                                                                                    | Peticiones                                                                                       |
| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Al empezar una ejecución, antes de que se ejecute ningún archivo, solo con `runCasesOnly` | `GET` de las claves de casos de la ejecución, 200 casos por página hasta la última               |
| Al terminar la ejecución, después del último archivo de prueba                            | Los informes, después la subida de adjuntos, y después el cierre de la ejecución (si hace falta) |

No se envía nada mientras se ejecutan las pruebas: el reporter reúne los resultados y los envía
cuando Vitest termina. Vitest espera al reporter antes de salir, así que el tiempo de las
peticiones, reintentos incluidos, forma parte del comando `vitest run`. En [modo watch](#modo-watch),
cada nueva ejecución de las pruebas hace sus propias peticiones al terminar. Un shard que escribe
un blob no envía nada: la ejecución de `vitest --merge-reports` hace las peticiones de todos los
shards ([sharding](https://docs.probara.net/es/developers/ci-integrations/vitest/sharding/)).

Con `runCasesOnly`, las claves de casos se leen una vez por ejecución (y una vez por cada nueva
ejecución en modo watch). Si no se pueden leer tras los reintentos, todas las pruebas se ejecutan y
se reportan, con una advertencia
([selección de pruebas](https://docs.probara.net/es/developers/ci-integrations/vitest/run-selection/)); los reintentos de
esa lectura solo se registran en debug.

### Tiempos máximos

| Ajuste      | Valor por defecto                    | Rango      | Qué limita                                                                   |
| ----------- | ------------------------------------ | ---------- | ---------------------------------------------------------------------------- |
| `timeoutMs` | 30000 ms                             | 1 a 600000 | Un intento de una petición, incluido el cuerpo de la respuesta               |
| subidas     | 120000 ms, o `timeoutMs` si es mayor | —          | Un intento de subida de un adjunto (un archivo grande en una conexión lenta) |

Un intento que agota su tiempo se reintenta como un error de red.

### Reintentos y backoff

| Respuesta                                                       | Qué pasa                                            |
| --------------------------------------------------------------- | --------------------------------------------------- |
| Error de red, tiempo agotado, 408, 429, 500, 502, 503, 504      | Se reintenta                                        |
| 409 con `Retry-After` (la misma petición sigue en curso)        | Se reintenta                                        |
| Un `201` cuyo cuerpo nunca llegó                                | Se reintenta; la clave de idempotencia lo reproduce |
| Cualquier otra respuesta (400, 401, 403, 404, 409, 413, 422...) | No se reintenta: la petición falla                  |

- `maxRetries` (de 0 a 10, 4 por defecto) define los reintentos después del primer intento: 5
  intentos en total por defecto.
- La espera antes del reintento _n_ es 1 s × 2ⁿ⁻¹, como máximo 30 s, más hasta un 20 % de variación
  aleatoria. El backoff es fijo: ninguna opción lo cambia.
- Una cabecera `Retry-After` (en segundos o como fecha HTTP) sustituye esa espera, con un máximo de
  120 s.
- Cada reintento se registra, con el intento y la espera:
  `Report attempt 1 of 5 got 503; retrying in 1000 ms`.

Con los valores por defecto, un informe que sigue fallando se rinde tras unos 15 s de espera
(1 + 2 + 4 + 8 s, hasta 18 s con la variación), más los propios intentos, cada uno de como máximo
`timeoutMs` (30 s por defecto). El peor caso es un `Retry-After` en cada respuesta: 120 s antes de
cada reintento, es decir, 8 minutos de espera con los 4 reintentos por defecto (20 minutos con
`maxRetries: 10`), más hasta 5 intentos de 30 s. Eso es por petición, y un informe fallido detiene
los siguientes de su proyecto. Vitest espera al reporter antes de salir: reduce `maxRetries` o
`timeoutMs` para acotar un paso de CI.

### Límite de peticiones

Probara limita las peticiones a la API por organización (60 peticiones por minuto en Free, 1.200 en Pro y 3.000 en Enterprise), para todos los tokens de la organización en conjunto. Lo que cuesta una ejecución:

| Petición                 | Cuántas                                                                        |
| ------------------------ | ------------------------------------------------------------------------------ |
| Claves de casos          | 1 por cada 200 casos de la ejecución, solo con `runCasesOnly`                  |
| Informe                  | 1 por bloque de hasta 500 resultados (`chunkSize`)                             |
| Preparación de adjuntos  | 1 por resultado con archivos (por cada 20 archivos o 64 MiB)                   |
| Confirmación de adjuntos | 1 por resultado con archivos                                                   |
| Cierre                   | 1, cuando se encolaron adjuntos (si no, el último informe cierra la ejecución) |

Una ejecución de 2000 intentos sin archivos cuesta 4 peticiones; una en la que 100 intentos adjuntan
un archivo (o su salida de consola, con `captureOutput`) cuesta unas 200 más. Las respuestas `429`
se reintentan después de su `Retry-After`. Para repartir las subidas, reduce
`attachmentConcurrency`; para enviar menos archivos, adjunta solo lo importante, o define
`uploadAttachments: false`.

### Bloques y orden

- Los resultados salen en bloques de `chunkSize` (de 1 a 500, 500 por defecto), **uno tras otro**,
  en el orden de los archivos de prueba de Vitest, con los intentos de cada archivo en orden. Un
  caso de la ejecución conserva el último resultado registrado, así que el orden importa. Un bloque
  también respeta los totales de pasos y etiquetas por informe de Probara.
- El primer bloque crea la ejecución (salvo que `run.ulid` nombre una); los demás la reutilizan.
- Cuando un bloque falla tras sus reintentos, los bloques siguientes de ese proyecto no se envían y
  la ejecución queda abierta; un
  [archivo de resultados](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/#archivo-de-resultados)
  los conserva.
- Las subidas empiezan cuando su informe queda registrado, `attachmentConcurrency` resultados a la
  vez (de 1 a 8, 2 por defecto), y la ejecución se cierra después de las subidas.

### Idempotencia

Cada informe, creación de ejecución, cierre de ejecución y confirmación de adjuntos lleva una
[`Idempotency-Key`](https://docs.probara.net/es/developers/api/idempotency/), la misma en cada reintento de esa petición. Un
informe reintentado cuyo primer intento sí se registró lo reproduce Probara, nunca se registra dos
veces. Volver a ejecutar `vitest` es una ejecución nueva, con todos los resultados registrados de
nuevo.

### Proxies

El reporter usa el `fetch` integrado de Node y no tiene opción de proxy propia:

| Node.js                           | Soporte de proxy                                                                          |
| --------------------------------- | ----------------------------------------------------------------------------------------- |
| 22.21 o posterior, 24 o posterior | Define `NODE_USE_ENV_PROXY=1` con `HTTPS_PROXY` (y `NO_PROXY`); `fetch` pasa por el proxy |
| 22.12 a 22.20                     | Sin soporte: `fetch` ignora `HTTPS_PROXY` y `HTTP_PROXY`                                  |

```bash
NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://proxy.example.com:8080 npx vitest run
```

Node añadió el soporte de `NODE_USE_ENV_PROXY` para `fetch` en
[22.21.0](https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V22.md#22.21.0) y 24.0.0
([documentación de Node](https://nodejs.org/api/cli.html#node_use_env_proxy1)). Las variables llegan
también a los workers de Vitest: añade `localhost` a `NO_PROXY` si tus pruebas acceden a un servidor
local con `fetch`. En versiones anteriores de Node, actualiza Node, pasa al reporter un `fetch`
propio ([abajo](#tu-propio-cliente-http)) o permite la URL base en el firewall.

### Autoridades de certificación propias

Para un Probara autoalojado detrás de una autoridad de certificación privada, pasa a Node el
certificado de la CA (PEM) al arrancar:

```bash
NODE_EXTRA_CA_CERTS=/etc/ssl/certs/company-ca.pem npx vitest run
```

Node lee `NODE_EXTRA_CA_CERTS` una sola vez al arrancar, así que defínela en el entorno del paso. En
Node 22.19 y posteriores, `NODE_USE_SYSTEM_CA=1` confía en cambio en el almacén de certificados del
sistema operativo. No hay ninguna opción para desactivar la verificación TLS.

### Tu propio cliente HTTP

`fetch` sustituye el cliente HTTP: una función con la firma del `fetch` global, por la que pasan
todas las peticiones del reporter. Úsala para lo que las variables de entorno anteriores no pueden
hacer, como una biblioteca de proxy o una cabecera que pide el gateway de tu empresa:

```ts
// vitest.config.mts
import { defineConfig } from 'vitest/config';

/** The global fetch, with the header the company gateway asks for. */
const gatewayFetch: typeof fetch = (input, init) => {
  // Headers acepta cualquier forma de init.headers: un objeto, un Headers o una lista de pares.
  const headers = new Headers(init?.headers);
  headers.set('X-Gateway', 'ci');
  return fetch(input, { ...init, headers });
};

export default defineConfig({
  test: {
    reporters: [
      'default',
      ['@probara/vitest-reporter', { projectId: 'SHOP', fetch: gatewayFetch }],
    ],
  },
});
```

El reporter sigue definiendo los tiempos máximos, los reintentos y sus propias cabeceras (el token,
la `Idempotency-Key`); consérvalas tal como llegan a tu función.

### No disponible: un perfilador de red

El perfilador de red de Qase registra las peticiones HTTP que hace una prueba como pasos de su
resultado. El reporter no registra peticiones: llenarían cada resultado de pasos sin valor, hasta el
límite de pasos, y no se pueden distinguir cuando las pruebas se ejecutan en paralelo. Adjunta lo
importante con
[`probara.attach()`](https://docs.probara.net/es/developers/ci-integrations/vitest/steps-and-attachments/#probaraattach).
Lo que otras herramientas tienen y el reporter no está en
[lo que el reporter no admite](https://docs.probara.net/es/developers/ci-integrations/vitest/migrating/#lo-que-el-reporter-no-admite).

## Modo watch

`vitest --watch` (y `vitest` a secas en una terminal, que inicia el modo watch) vuelve a ejecutar
las pruebas a medida que guardas archivos. El reporter da a toda la sesión **una** ejecución de
Probara: la primera ejecución de las pruebas la crea, cada nueva ejecución reporta en ella, y queda
abierta, porque una ejecución cerrada rechazaría la siguiente.

```text
$ npx vitest --watch
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (open): https://app.probara.net/projects/SHOP/runs/R-1
[probara] Watch mode: every re-run reports into R-1 of SHOP, which stays open: close it in Probara, or with probara run close --project SHOP --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3
[probara] Sending 2 results of 2 tests (2 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 2 results (0 new cases, 0 unmatched) in R-1 (open): https://app.probara.net/projects/SHOP/runs/R-1
```

Arriba, la primera ejecución creó `R-1` y lo dijo una vez; después se guardó `tests/cart.test.ts`,
y la nueva ejecución de sus 2 pruebas reportó en la misma ejecución. Cada línea `Sending` cuenta su
propia ejecución.

| En una sesión watch                                      | Qué hace el reporter                                                              |
| -------------------------------------------------------- | --------------------------------------------------------------------------------- |
| La primera ejecución (o nueva ejecución) con resultados  | Crea la ejecución, y registra la línea `Watch mode` con el comando que la cierra  |
| Cada nueva ejecución posterior                           | Reporta en esa ejecución las pruebas que ejecutó, y las cuenta en su propia línea |
| Un cambio en la configuración de Vitest                  | Vitest se reinicia, y la sesión conserva su ejecución                             |
| El final de la sesión (`q`, `Ctrl+C`)                    | Nada: la ejecución queda abierta. Ciérrala en Probara o con el comando registrado |
| `closeRun`, `closeRuns`                                  | Se ignoran: una sesión watch nunca cierra sus ejecuciones                         |
| `run.ulid` (`PROBARA_RUN_ULID`)                          | Cada nueva ejecución reporta en esa ejecución, que queda abierta                  |
| `projects`                                               | Una ejecución por proyecto de Probara, creada con su primer resultado             |
| `runCasesOnly`                                           | Los casos de la ejecución se vuelven a leer antes de cada nueva ejecución         |
| Una advertencia sobre las pruebas de una nueva ejecución | Se registra una vez en esa nueva ejecución                                        |

Cierra la ejecución de la sesión cuando termines:

```bash
npx @probara/cli run close --project SHOP --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3
```

El modo watch es para tu propia máquina: el reporter solo reporta con un token y un proyecto, así que
una sesión local no envía nada salvo que los definas. Los helpers `probara.*` y el archivo de setup
funcionan en modo watch como en cualquier ejecución. Con
[varios proyectos de Probara](https://docs.probara.net/es/developers/ci-integrations/vitest/sharding/#varios-proyectos-de-probara),
cada proyecto tiene su propia ejecución, creada con su primer resultado de la sesión, y su propia
línea `Watch mode`; un proyecto cuyas pruebas aún no han reportado no tiene ejecución hasta que lo
hacen.

### Cuando se cierra la ejecución durante la sesión

Alguien puede cerrar (o eliminar) la ejecución de la sesión en Probara mientras sigues trabajando. La
siguiente nueva ejecución se rechaza, así que el reporter envía en ese momento sus resultados a una
ejecución nueva, y cada nueva ejecución posterior reporta en la nueva:

```text
$ npx vitest --watch
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (open): https://app.probara.net/projects/SHOP/runs/R-1
[probara] Watch mode: every re-run reports into R-1 of SHOP, which stays open: close it in Probara, or with probara run close --project SHOP --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3
[probara] Sending 2 results of 2 tests (2 passed, 0 failed, 0 skipped, 0 blocked)
[probara] 2 results were not sent: Probara answered 409 conflict: <message from Probara>. No run was created or updated
[probara] The run R-1 of SHOP was closed: sent the 2 results of this re-run into a new run
[probara] Recorded 2 results (0 new cases, 0 unmatched) in R-2 (open): https://app.probara.net/projects/SHOP/runs/R-2
[probara] Watch mode: every re-run reports into R-2 of SHOP, which stays open: close it in Probara, or with probara run close --project SHOP --run-ulid 01J9Z3M8Q2R4T6V8X0Y2Z4A6B8
```

- **Solo un rechazo mueve la sesión.** Una ejecución cerrada (`409 conflict`) o eliminada
  (`404 not_found`) rechaza la nueva ejecución de forma definitiva, así que sus resultados van a una
  ejecución nueva. Cualquier otro fallo (Probara inalcanzable, un `409` reintentado porque el mismo
  informe seguía en curso) puede haber registrado los resultados de todos modos: nunca se envían dos
  veces, y la sesión conserva su ejecución.
- **Una ejecución cerrada a mitad de una nueva ejecución.** Si la ejecución rechaza una nueva
  ejecución de las pruebas después de registrar parte de ella, solo los resultados que no registró
  van a la ejecución nueva; el resto queda en la anterior, y la línea del registro nombra ambas.
- **Con un archivo de resultados**, una nueva ejecución rechazada se guarda en el archivo, que sigue
  nombrando la ejecución que la rechazó, y la siguiente reporta en una ejecución nueva. La línea del
  registro da el comando que envía el archivo a una ejecución abierta (`--run-ulids WEB=<ulid>` para
  otro proyecto). Si el archivo no se puede escribir, la nueva ejecución va a una ejecución nueva
  como arriba.

```ts
reporters: ['default', ['@probara/vitest-reporter', { resultsFile: 'probara-results.json' }]],
```

```text
$ npx vitest --watch
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (open): https://app.probara.net/projects/SHOP/runs/R-1
[probara] Watch mode: every re-run reports into R-1 of SHOP, which stays open: close it in Probara, or with probara run close --project SHOP --run-ulid 01J9Z3K4M5N6P7Q8R9S0T1V2W3
[probara] Sending 2 results of 2 tests (2 passed, 0 failed, 0 skipped, 0 blocked)
[probara] 2 results were not sent: Probara answered 409 conflict: <message from Probara>. No run was created or updated
[probara] Wrote the 2 results that were not sent to /work/shop/probara-results.json: send them with probara import results /work/shop/probara-results.json
[probara] The run R-1 of SHOP was closed: the results file /work/shop/probara-results.json keeps this re-run, but names R-1, which refuses it: send it with probara import results /work/shop/probara-results.json --run-ulid <ulid of an open run>; the next re-run reports into a new run
```

Relacionado: [Primeros pasos](https://docs.probara.net/es/developers/ci-integrations/vitest/) ·
[Resultados y reintentos](https://docs.probara.net/es/developers/ci-integrations/vitest/results-and-retries/) ·
[Solución de problemas](https://docs.probara.net/es/developers/ci-integrations/vitest/troubleshooting/) · Fuente:
[configuration.md](https://github.com/cynch-me/probara-sdk/blob/main/packages/vitest-reporter/docs/configuration.md),
[network.md](https://github.com/cynch-me/probara-sdk/blob/main/packages/vitest-reporter/docs/network.md),
[watch.md](https://github.com/cynch-me/probara-sdk/blob/main/packages/vitest-reporter/docs/watch.md)
