Skip to main content

kickjs-write-controller-test

Use when adding a Vitest test that exercises an HTTP route or DI graph.

Datos de origen

Repositorio
forinda/sdeploy
Última actividad en el origen
22 de septiembre de 2026 a las 19:55
Idioma detectado de SKILL.md
inglés
Estrellas
0
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
kickjs-write-controller-test
description
Use when adding a Vitest test that exercises an HTTP route or DI graph.
<!-- Generated by `kick g agents` for sdeploy. Edits are overwritten on the next refresh; keep customisation in a SKILL.local.md alongside. --> **Template** (copy/paste, adjust): ```ts import { describe, it, expect, beforeEach } from 'vitest' import request from 'supertest' import { Container } from '@forinda/kickjs' import { createTestApp } from '@forinda/kickjs-testing' // Side-effect import — registers the env schema, exactly as src/index.ts does. // `createTestApp` never loads the entry file, so without this // `ConfigService.get('YOUR_KEY')` is undefined under test while `@Value()` // still appears to work via its process.env fallback — the two disagree only // in tests. import '@/config' describe('UserController', () => { beforeEach(() => Container.reset()) // isolate DI between tests it('returns users', async () => { // `createTestApp` takes an OPTIONS OBJECT and returns // `{ app, container }`. Passing a bare array throws // "this.options.modules is not iterable"; the result has no `.get()`. // // Drive `app.handle` rather than `expressApp`: it is the Application's // own Node listener, so the test runs on whichever runtime the app is // configured with. Pass `runtime` to `createTestApp` to match production. const { app } = await createTestApp({ // Matches this project's `modules.style`. modules: [UserModule()], }) const res = await request(app.handle.bind(app)).get('/api/v1/users') expect(res.status).toBe(200) }) }) ``` **Typed handler signature** — pair with `kick typegen` so `ctx.body` / `params` / `query` are typed by the route's Zod schema: ```ts @Post('/', { body: createTodoSchema }) async create(ctx: Ctx<KickRoutes.TodoController['create']>) { // ctx.body is typed from createTodoSchema; ctx.params from the route. // Returning (vs ctx.created) lets typegen infer the response type. return reply(201, await this.service.create(ctx.body)) } ``` **Red flags**: - `new Container()` — wrong; use `Container.reset()` in `beforeEach` or `Container.create()` for fully isolated graphs. - `Container.getInstance().reset()` — wrong; same fix. - Sharing a container instance across `it()` blocks — leaks registrations between tests. - Injecting a `Scope.REQUEST` service into a `SINGLETON` — container throws at resolve. Singletons must resolve request-scoped services explicitly per call. - Calling `getRequestValue<string>('traceId')` — the generic slot is the **key** type, not the value type; widens key and bypasses typed lookup. - Asserting on `res.body.requestId` when `requestId()` middleware isn't mounted in the test app — value will be `undefined`. - Using `Scope.REQUEST` services in a test without mounting `requestScopeMiddleware()` — `getRequestValue` silently returns `undefined`; `getRequestStore` throws. **Nuances**: - `@Inject` and `@Autowired` are interchangeable — same runtime, same types; pick by readability. - `@Value('MISSING_KEY')` with no default **throws on property access**, not at construction — tests that exercise the getter will surface the missing-env issue.
Ver en GitHub