Skills Agentes

Gate Tests

Cómo usar las directivas de test @gate / @force-gate en lugar de it.skip o patrones de skip falso-verde, con las condiciones, el patrón de axis y los comandos de verificación.

Oficial

Reemplaza a: it.skip('...') para fallos conocidos, if (isNextDev) { ...; return } para saltar en modo dev, describe.skip condicionado a process.env

Estrellas
142k

en todo el repo

Actividad
62

0–100, la ruta de este skill

Actualizado
hace 4 días

último commit aquí

Commits
2

últimos 90 días

Contexto
2.7k tok

140 tok en reposo

Paquete
1 archivo

10 KB

Instalar

Funciona con cualquier agente que lea SKILL.md

npx -y skills add vercel/next.js --skill gate-tests --agent claude-code

Se instala solo en este repositorio.

Qué hace

  • Sustituye it.skip y patrones de skip falso-verde por directivas @gate o @force-gate
  • Explica cómo elegir entre @gate, @force-gate estático y @force-gate perezoso según el caso
  • Describe el patrón de fixture con __NEXT_TEST_AXIS para cubrir ambos estados de un flag experimental
  • Detalla los comandos para verificar una suite gateada en cada estado (plano, axis, dev)

Úsalo cuando

  • Un test falla de forma conocida bajo alguna dimensión de la matriz (modo dev, un bundler, un flag experimental como cacheComponents)
  • Se está convirtiendo un guard if (isNextDev) return o un describe.skip basado en una variable de entorno
  • Se añade una condición nueva a test/lib/gate/conditions.ts
  • Se necesita mapear el flag experimental de un fixture a una letra de __NEXT_TEST_AXIS

No lo uses cuando

    Qué lo activa

    Di cualquiera de estas frases y el agente debería cargar este skill.

    • Convierte este it.skip en un @gate en lugar de saltarlo
    • ¿Cómo reemplazo este if (isNextDev) return por un @force-gate?
    • Necesito que este test cubra tanto el estado on como off de cacheComponents
    • Ayúdame a verificar esta suite gateada en modo dev y en el axis A

    SKILL.md

    En inglés

    Gating tests with @gate / @force-gate

    Full reference: test/lib/gate/README.md. This skill is the decision guide: which directive to reach for, the standard conversion patterns, and how to verify.

    Never write these — gate instead

    Anti-pattern Replacement
    it.skip('...') for a known failure // @gate <cond> (or @gate FIXME if no condition explains it)
    if (isNextDev) { test('skipped in dev mode', () => {}); return } // @force-gate prefetching (or !dev) on the describe
    (flagEnabled ? describe.skip : describe)(...) keyed on process.env // @force-gate <cond> (lazy) on the describe
    Duplicating a fixture directory per flag state one fixture keyed on __NEXT_TEST_AXIS + a @gate/@force-gate
    Branching expectations on process.env.__NEXT_CACHE_COMPONENTS if (await gate((c) => c.cacheComponents)) (gate from next-test-utils)

    The skip patterns are fake-greens: nothing tells you when the bug they hide is fixed. @gate still runs the body and fails the suite the day the "known failure" starts passing, so stale workarounds get deleted instead of rotting.

    Choosing the directive

    Ask what kind of difference you're encoding:

    1. A behavior change — both states assert something meaningful. Don't gate the test at all: fork inside the body with the runtime gate() — same condition registry, no inversion — which pinpoints exactly what differs, and also covers it.each, where a pragma cannot attach: if (await gate((c) => c.cacheComponents)) { ... } else { ... }. It mirrors React's gate(flags => ...); a pragma expression string works too (await gate('cacheComponents && !dev')). A suite-level pragma is too coarse here — it hides what is different between the states.
    2. A flag that changes the behavior of existing surface (cacheComponents, optimisticRouting) and the suite is written for one state. // @gate <cond> on the test or describe. The body runs; a false condition inverts the expectation (failure absorbed, a pass fails as "stale gate"). The off state fails for a meaningful reason — the behavior differs — so a pass is real information: the gate is stale, delete it.
    3. A new API — the off state proves nothing. Typically // @force-gate <cond> (lazy) on the describe. An API that throws when its flag is off — or is inert, like useOffline(), which compiles to a hook that always reports online — can only fail vacuously (often slowly, by timing out), and browser e2e time is considerable, so skip the run (and the fixture build) instead of paying for it. Working example: test/e2e/app-dir/use-offline/. This is discretion, not a rule: when the flag changes behavior the suite can observe, the off state is meaningful and @gate buys the staleness check.
    4. @force-gate <cond> also when running the body is impossible, not merely failing: prefetching is off in dev, deploy has no local build output, the fixture cannot even build under the condition.
      • Static condition (!dev, bundler…) → real Jest ○ skipped at collection.
      • Lazy condition on a describe → the fixture build is skipped when false; tests report passed-with-⚠ skipped by @force-gate (Jest cannot skip at runtime). Build-skipping covers start/dev suites where nextTestSetup owns the build — not skipStart suites, not deploy.
    5. Pragmas stack: a common pair is a static // @force-gate prefetching plus a lazy // @gate <flag> on the same describe.

    Is the off-state run worth its cost?

    Browser e2e time is not free, so weigh what the gated-off run buys. For a behavior flag it usually replaces a run that was already being paid for — a fixture that pins its flags runs identically with and without the axis set, so keying the flag on an axis converts a redundant duplicate into coverage — and it is what proves a pass isn't vacuous: a test that passes with the feature off wasn't testing the feature. Absorbed failures also fail fast, so the off-state run is cheaper than it sounds. For a new API the calculus flips: the off state can only throw, which proves nothing, so use a lazy // @force-gate <flag> on the describe — the fixture build is skipped too, so the off state costs almost nothing.

    Conditions

    Every name in a pragma must be declared in test/lib/gate/conditions.ts (typos fail the suite at collection). Two tiers:

    • static — the run's shape: dev, start, deploy, mode, turbopack, rspack, webpack, bundler, react18, wasm, ci, plus the always-false FIXME/TODO. prod and prefetching are semantic aliases for !dev — prefer the name that states why the suite cannot run.
    • lazy — a predicate over the fixture's resolved next.config (cacheComponents, ppr, useOffline, output, …).

    Adding one is a two-line change; follow the guidance at the top of conditions.ts. The rule that matters: lazy conditions read the resolved config, never process.env — env vars don't survive config resolution (__NEXT_CACHE_COMPONENTS only applies when the fixture doesn't set cacheComponents itself, and resolution implies flags the fixture never mentions).

    Pattern: cover both states of an experimental flag

    Instead of pinning a flag on (which makes the plain and axis runs identical), key it on a test axis and gate the suite. Axes are lettered (A, B, …) — a fixed enumeration, not a boolean and not a sharding bucket. Key the flag so it is enabled by default — then the suite exercises the feature in plain local runs with no special env, and the axis run covers the off state:

    // next.config.js — pin every dimension except the one under test
    const nextConfig = {
      cacheComponents: true,
      experimental: {
        concurrentRouterQueue: process.env.__NEXT_TEST_AXIS !== 'A',
      },
    }
    
    // @gate concurrentRouterQueue
    it('fails loudly on link navigation', async () => { ... })
    

    The plain run exercises the feature; the axis-A run covers the off state — the gated tests are expected to fail there, and the suite fails the day they start passing. Working example: test/e2e/app-dir/concurrent-router-queue/ (tests whose expectations hold in both states stay ungated). The same keying pairs with a lazy @force-gate when the off state proves nothing — test/e2e/app-dir/use-offline/ — which skips the redundant axis run (build included) instead of covering it. Axis A aliases __NEXT_CACHE_COMPONENTS for now (see scripts/run-jest.sh) — fine, because these fixtures pin cacheComponents explicitly, so that run's env default is a no-op for them.

    Keep exactly one flag varying per fixture. A red shard must attribute to a single dimension.

    Pitfalls

    • A pragma the transform can't attach is a hard error: a blank line between pragma and it(, it.each/it.failing, or a pragma inside a JSDoc block. Prose comments must not begin with @gate. A pragma on a skipped test (it.skip, xit, …) errors as ambiguous — remove the skip or the pragma. A skip without a pragma is respected.
    • A describe-level gate does not reach it.each tests.
    • Gated-false bodies that fail by stalling waste the full Jest timeout — and under a lazy gate they fail the suite anyway (the runtime inversion only absorbs thrown errors; a static gate rides Jest's native test.failing, which does absorb timeouts). Bodies that fail via retry() timeouts also make the off-state run slow; a fast first assertion is worth having.
    • Failures cascade in the off state: an absorbed failure mid-body skips the body's cleanup (e.g. a browser context left offline), so later tests may fail for cascade reasons. Acceptable for a tripwire, but don't puzzle over the individual failure messages in a gated-off run.
    • afterEach failures (e.g. redbox matchers) are not gated, only the body is. Hooks under a false lazy @force-gate are the exception: they are skipped with the suite instead of running against a fixture that was never booted.
    • jest.retryTimes(1) on non-dev CI means a flaky gated-false test passes whenever it happens to fail; the tripwire is only deterministic for deterministic tests.
    • Gated titles are unchanged in the Jest output; the ⚠ gated test failed as expected log line is the only signal.
    • pragma-transform.js bails out early on files containing neither @gate nor @force-gate as substrings — keep both checks if you touch it.

    Verify a gated suite in every state it can run in

    # plain run (flag on): expect normal passes, no warnings
    NEXT_SKIP_ISOLATE=1 pnpm test-start-webpack test/e2e/app-dir/<suite>/<suite>.test.ts
    
    # axis run (flag off): expect `⚠ gated test failed as expected (@gate …)`
    __NEXT_TEST_AXIS=A NEXT_SKIP_ISOLATE=1 pnpm test-start-webpack test/e2e/app-dir/<suite>/<suite>.test.ts
    
    # dev (static @force-gate !dev): expect `○ skipped` at collection, no fixture boot
    NEXT_SKIP_ISOLATE=1 pnpm test-dev-webpack test/e2e/app-dir/<suite>/<suite>.test.ts
    

    A suite with a lazy @force-gate on the describe should additionally show skipping build behavior (no next build) in the state where the condition is false.

    Unit tests for the infrastructure itself: pnpm test-unit test/unit/gate/.

    Related skills

    • $flags — adding the experimental flag itself (config-shared, schema, define-env)
    • $router-act — the prefetch-timing patterns most gated suites also use

    Reproducido de vercel/next.js bajo licencia MIT. Leer esta página en markdown.

    Archivos

    1 archivo en el paquete. Solo se lee SKILL.md al activarse — las referencias se cargan si el skill decide que las necesita.

    Antes de instalar

    Cada nombre usado en una pragma debe estar declarado en test/lib/gate/conditions.ts o la suite falla en la recolección.

    Detalles

    Creador
    vercel
    Categoría
    Testing y QA
    Licencia
    MIT
    Recursos incluidos
    Solo SKILL.md
    Repositorio
    vercel/next.js
    Código fuente
    Ver SKILL.md

    Etiquetas

    Más de vercel/next.js

    Este repo incluye 24 skills. Si instalas uno, normalmente ya tienes los demás. Ver el pack next.js entero y su comando de instalación

    Activa Cache Components en una app de Next.js y resuelve las rutas bloqueantes que surgen: el flag cacheComponents, errores de blocking-prerender/instant validation y el codemod cache-components-instant-false.

    Costo de contexto al activarse
    8.3k tok
    Tamaño del paquete
    3 archivos
    Última actualización
    hace 6 días
    Oficialherramientas desarrollo

    Lleva una ruta de Next.js a navegación instantánea bajo Cache Components o PPR mediante un bucle agéntico: codifica el objetivo como un e2e instant() en rojo y lo trabaja hasta verde, ruta a ruta.

    Costo de contexto al activarse
    6.3k tok
    Tamaño del paquete
    6 archivos
    Última actualización
    hace 10 días
    Oficialherramientas desarrollo

    Activa Partial Prefetching en una app Next.js y trabaja los insights que surge: flag `partialPrefetching`, `export const prefetch = 'partial'`, auditoría de `Link prefetch={true}` y tests `instant()`.

    Costo de contexto al activarse
    6.8k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 10 días
    Oficialherramientas desarrollo

    Verifica el comportamiento en runtime de Next.js tras editar código de la aplicación. Combina /_next/mcp, la visión de Next.js, con agent-browser, la del navegador. Requiere un next dev en marcha.

    Costo de contexto al activarse
    2k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 18 días
    Oficialtesting qa

    Valida el paquete de preview de Next.js específico de un commit y dispara manualmente toda la suite de tests de despliegue vía el workflow test_e2e_deploy_release.yml de GitHub Actions.

    Costo de contexto al activarse
    1.2k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 10 días
    Oficialdevops infraestructura

    Gestiona PRs apilados y parte el trabajo en ramas revisables con gh-stack: creación, visualización, edición, push, envío, sincronización, rebase, merge y checkout.

    Costo de contexto al activarse
    2.3k tok
    Tamaño del paquete
    4 archivos
    Última actualización
    hace 25 días
    Oficialherramientas desarrollo

    Skills relacionados

    Verifica el comportamiento en runtime de Next.js tras editar código de la aplicación. Combina /_next/mcp, la visión de Next.js, con agent-browser, la del navegador. Requiere un next dev en marcha.

    Costo de contexto al activarse
    2k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 18 días
    Oficialtesting qa

    Tría fallos de CI y comentarios de revisión de PR con scripts/pr-status.js: prioriza por bloqueo (build, lint, tipos, tests), empareja variables de CI para reproducir en local y distingue flakies.

    Costo de contexto al activarse
    596 tok
    Tamaño del paquete
    3 archivos
    Última actualización
    hace 3 meses
    Oficialtesting qa

    Cómo escribir tests end-to-end con createRouterAct y LinkAccordion. Úsalo al escribir tests que controlan el momento de las peticiones internas de Next.js, como los prefetches.

    Costo de contexto al activarse
    3.1k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 2 meses
    Oficialtesting qa