Skip to main content

kickjs-write-controller-test

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

معلومات المصدر

المستودع
forinda/sdeploy
آخر نشاط في المصدر
٢٢ سبتمبر ٢٠٢٦ في ١٩:٥٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٠
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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.
عرض على GitHub