Test from target (class or method)
Given a target (class or class.method), an optional source file path, and a test file path, produce or update a Mocha-style test suite (TypeScript .test.ts) aligned with project patterns. Focus on full logical branch coverage, validation, and error propagation. Source lives under src/; tests run with npm test or npm run test:all (Mocha + --require tsx/cjs).
Input parameters
Supply as ordered lines (one per line, no prefixes):
- TARGET_NAME (${targetCode}) — Fully qualified target to test: Class or Class.method. Examples:
UsersModel.getActiveUsers, AuthController.login. Use the real method name (no __ prefix); controllers expose private methods without __.
- TEST_FILE_PATH (${testFile}) — Repo-relative path to the test file to create or update (must end with
.test.ts).
- (Optional) SOURCE_FILE_PATH (${sourceFile}) — Repo-relative path to the implementation file (e.g.
src/controllers/auth.controller.ts) for context and import resolution.
Example:
AuthController.login
test/controllers/auth.controller.test.ts
src/controllers/auth.controller.ts
Output
- Markdown-fenced TypeScript test content (or delta additions) only.
- Apply changes directly to ${testFile} in the workspace (create/update the file). Chat output must match the saved file. Do not only suggest edits in chat.
- Never modify the production file (${sourceFile}) when generating tests. Do not add factories or hooks in production to inject mocks.
Context linking
If ${sourceFile} is supplied, output (before the code block) two plain lines:
Implementation: ${sourceFile}
Test File: ${testFile}
If not supplied, skip these lines; do not guess paths. Relative imports in code are inferred from the provided source path.
Golden rules
- TypeScript/ESM:
import ... from '...'. Test files are .test.ts; source under src/ (e.g. src/controllers/, src/lib/, src/model/).
- Structure: Each class gets a top-level
describe('<ClassName>'). Each method gets a nested describe('<methodName>') — use the real method name (e.g. login, getNations), not __methodName.
- Organization: Inside each method block use optional
describe('Success') / describe('Error') when branches > 2; else individual it cases.
- Sinon: Use for stubs/spies; prefer
sinon.assert.calledWith over manual argument inspection.
- Async errors: No chai-as-promised; use try/catch for async error assertions.
- Controller private methods: Call via
(controller as any).methodName(...). Stub with sinon.stub(controller as any, 'methodName') (real name, no __).
- Secrets/config: Never import production secrets or mutate real environment configs.
- No obsolete refs: Do not reference removed or project-specific instruction files; integrate any needed logic into the test design.
- SQL: Do not assert on raw SQL strings; only assert that the query method was called with objects of the expected shape (e.g. replacements). Use
transactionClient in assertions (not transaction). Stub queryReturnFirst when the controller uses it; stub query when it expects { rows }.
- File writes: Always update ${testFile} on disk; chat output must mirror the saved content.
- Production code: Never modify ${sourceFile}. Prefer: (a) complete mock config so constructors do not throw (e.g. pubSub options, getstream, sms), (b) minimal fake env when config is missing, (c) local HTTP server or fixtures under
test/ only.
- Run tests (entire file, mandatory): After writing tests, always run the full
${testFile} suite (e.g. npm test -- ${testFile}), not just newly added tests or filtered describe/it blocks. Iterate until all tests in that file pass. Fix failures by changing test code only, not production.
- ESM stubs: Do not stub immutable ES Module default exports; Sinon cannot stub ESM bindings. Use HTTP server in test or indirection under
test/fixtures/ only if that pattern exists (do not edit production).
- Static utils: When encrypt/decrypt or similar static utilities are used, stub only those static methods (e.g.
Crypt.encryptAES); do not alter the class file.
- Unreachable branches: If a branch is impossible to cover without changing production, add
// TODO: unreachable branch without code change instead of changing production.
- PubSub/Notifications: Do not stub constructors or add production hooks. In the mock env provide config (e.g.
config.pubSubOptions with topicId and authentication: { projectId, credentials }) so new NotificationsManager(env) (and any internal PubSub client) does not throw. Add mockNotificationManager.store.resolves() and mockNotificationManager.publish.resolves() so async flow completes. For other deps (e.g. Getstream, SMS), provide the corresponding config entries so constructors do not read undefined.
- Rollback: If the controller does not wrap
rollback in try/catch, when rollback rejects, next is called with the rollback error. Assert next(rollbackError) and do not expect logger.error for rollback in that case.
- Logger: If the code under test uses
this.env.logger.warning, the mock env must provide logger.warning (not only logger.warn).
Coverage expectations
Cover: happy path, each conditional branch, invalid parameters, edge values (0, empty array, null, undefined), error propagation (next(error) in controllers, thrown errors in models/libs). Validate:
- HTTP status codes and response methods (
send, sendStatus, json, cookie, clearCookie).
- Sequence and arguments of model/DB operations.
- Side effects: cookie set/cleared, session manager calls, grants updated, data transformations.
Folder-specific directives
Controllers (test/controllers/*.test.ts)
- Mock env with: session config, getstream/sms (or equivalent) config,
pgConnection, pgModels, session (and sessionManager if used), and any other connections the controller uses (e.g. documentsConnection).
- For code that builds a notifications/pub-sub manager, provide config (e.g.
config.pubSubOptions with topicId and authentication: { projectId, credentials }) so the constructor does not throw; add store.resolves() and publish.resolves() on the mock where needed.
- Stub
env.session.checkAuthentication() to return a pass-through middleware when needed.
- Call controller methods via
(controller as any).methodName(request, response, next) — real method name.
- For methods that set cookies: assert the third argument of
response.cookie (options object); use sinon.match.object or check for expires when testing persistent sessions.
- Transactions: Stub
pgConnection.startTransaction with .resolves(t) and use the same t for commit(t) / rollback(t). In assertions use transactionClient (not transaction). For updateByKey, keys are an array (e.g. ["id_us"], ['id_up']); payload may include fields from request.session (e.g. id_last_updater_up).
- Error path: ensure
next(error) is called with the correct error (original or rollback error if rollback rejects and controller does not wrap it).
- Assert only externally observable behavior (responses and env calls), not implementation details.
Lib utilities (test/lib/*.test.ts)
- Use Node
assert or chai.expect for pure functions; exhaustive yet concise.
- Cover boundaries: empty arrays, null/undefined, formatting edge cases.
- For validators: valid value, invalid formats, null, undefined, empty, malformed.
- Stub only when the function uses time or randomness (e.g.
sinon.useFakeTimers()).
- Import paths: From
test/lib/ use ../../src/... (two levels to project root). From test/lib/notifications/ use ../../../src/... and ../../../config/... (three levels).
- For classes with private methods: call via
(instance as any).methodName(...); stub with sinon.stub(instance as any, 'methodName'). If the class has a single-argument constructor (e.g. options object), use that; method names are real (e.g. sendRequest), not prefixed with __.
Postgres models (test/model/postgres/*.test.ts or test/pg-models/*.test.ts)
- Mock connection with stubbed methods:
query, queryReturnFirst, queryPaged, insert, updateByKey, startTransaction, commit, rollback as used. Use .resolves(t) for startTransaction so the same t is used for commit/rollback.
- Stub return shapes to match the actual API:
queryPaged returns { totalRowCount, rows } or { total, rows }; query returns { rows }. Use aliased column names in mock rows when the SQL uses AS.
- For each method: assert correct
replacements and optionally sinon.match({ sql: sinon.match(/select/), replacements: [...] }). Use transactionClient when the method passes a transaction.
- Simulate DB responses:
{ rows: [...] }, { rows: [] }, null, rejection. Align stub with how the model uses the result (e.g. result?.rows ?? [] or throw when null).
- Error path must bubble the same Error instance.
- Transactional flows: assert order
startTransaction → updates/inserts → commit; error branch triggers rollback.
Notifications / domain logic (test/lib/notifications/*.test.ts, test/lib/*-notifications.test.ts)
- Do not change production to inject mocks. Provide mock config so the notifications/pub-sub manager constructor does not throw (e.g.
config.pubSubOptions with topicId and authentication: { projectId, credentials }).
- Add
mockNotificationManager.store.resolves() and mockNotificationManager.publish.resolves() so async flow completes.
- Call private methods via
(notifications as any).methodName(...); use describe('methodName', ...).
- Assert payload structure and invocation count on store/publish mocks. Include failure of underlying store and error propagation.
- Import paths: From
test/lib/notifications/ use ../../../src/... and ../../../config/... (three levels).
External service classes (e.g. Bridge, Getstream)
- If the class constructor takes a single options object and has a private method like
sendRequest, stub with sinon.stub(instance as any, 'sendRequest').
- If the class needs DB/config/logger, provide a complete mock (e.g.
pgConnection.queryReturnFirst, config.getstream) so constructors do not throw.
- Restore stubs in
afterEach: sinon.restore().
Export / batch utilities
- Use a minimal fake env (e.g. stubbed
pgConnection, pgModels) instead of a full real Environment when config is missing or incomplete.
- For helpers with private methods, call via
(helper as any).methodName(...).
- If file writes or streams occur, stub fs or stream constructors. Validate produced output (e.g. CSV) with a sample subset.
- Include an edge case for larger input (e.g. 1000 items) to ensure no throw and transformation called per item.
Assertion strategy
sinon.assert.calledOnce(stub), sinon.assert.calledWith(stub, expectedArgs...)
sinon.match for partial object or regex match of SQL. For pgConnection.query / updateByKey, use transactionClient in expected args (not transaction).
- For query calls, assert the shape passed by the code: e.g.
{ sql, replacements } or { sql, replacements, transactionClient }.
updateByKey: keys are an array; payload may include session-derived fields.
- For arrays and order-sensitive logic, use deep equality.
- For dates:
sinon.match.date or instanceof Date.
- Session/cookie: assert the third argument of
response.cookie (options object); use sinon.match.object or check expires for persistent sessions.
Error assertion pattern (async)
try {
await subject.method(args);
assert.fail('Expected method to throw');
} catch (err) {
assert.strictEqual(err, expectedError); // or shape assertions
}
Edge cases checklist
- Null / undefined inputs
- Empty arrays / empty objects
- Boundary numerics: 0, -1 (if invalid), large numbers
- Missing required properties
- Duplicate entries (where uniqueness applies)
- Partial updates (optional fields omitted)
- Upstream failure (e.g. token generation, notification push)
Session and auth
When controller endpoints require auth:
- Stub
env.session.checkAuthentication to return (req, res, next) => next().
- Test unauthenticated path only if the controller itself branches on session absence; otherwise rely on middleware coverage elsewhere.
Generated file behavior
- If ${testFile} exists: Merge new test blocks without duplicating existing method
describe. If the method block already exists, add only missing branches/cases. Do not remove or rename existing tests.
- If ${testFile} does not exist: Generate full skeleton (imports, top-level describe, method-level describes, coverage template). Use
// TODO for logic that cannot be inferred.
In all cases, update the real ${testFile} on disk to match the produced output.
Import paths
- From
test/ or test/controllers/ or test/lib/: ../../src/... (two levels to project root).
- From
test/lib/notifications/: ../../../src/... and ../../../config/... (three levels).
Use static imports where possible. If loading in a hook, require('../../src/lib/...') with tsx/cjs resolves correctly. Use the project’s shared types/constants package (e.g. HttpResponseStatus) when the codebase does.
Output format
Provide only the test file content inside a fenced ```ts or ```typescript block. When updating, show only new or changed blocks preceded by a brief comment // Added tests for <method>.
Parameter mapping
- ${targetCode}: Class or Class.method to test. Use the real method name. If only Class.method is supplied, generate tests for that method but keep the class-level and method-level
describe hierarchy.
- ${testFile}: Must end with
.test.ts. Drives import depth: two levels (../../) from test/, test/controllers/, or test/lib/; three levels (../../../) from test/lib/notifications/.
- ${sourceFile}: Optional; use to compute relative import path. Source under
src/; use .ts or no extension per project resolution. Do not use .mjs.
Quality gates (self-check)
When information is ambiguous
Insert a // TODO: comment with a concise note (max 60 chars) rather than guessing behavior that cannot be inferred from the code.
Return only the test code per the instructions above — no extra commentary beyond mandated context lines and added-block comments.
END OF SKILL.
1---2name: test-from-target3description: Generates or updates Mocha-style test suites (.test.ts) from a target class or method. Use when writing tests from controller/model/lib code, when the user asks to test a class or method, or when adding test coverage for a specific target. Assumes TypeScript, ESM, Mocha with tsx/cjs, source under src/, tests under test/.4---56# Test from target (class or method)78Given a **target** (class or class.method), an optional **source file** path, and a **test file** path, produce or update a Mocha-style test suite (TypeScript `.test.ts`) aligned with project patterns. Focus on full logical branch coverage, validation, and error propagation. Source lives under **`src/`**; tests run with **`npm test`** or **`npm run test:all`** (Mocha + **`--require tsx/cjs`**).910## Input parameters1112Supply as ordered lines (one per line, no prefixes):13141. **TARGET_NAME** (${targetCode}) — Fully qualified target to test: Class or Class.method. Examples: `UsersModel.getActiveUsers`, `AuthController.login`. Use the **real method name** (no `__` prefix); controllers expose private methods without `__`.152. **TEST_FILE_PATH** (${testFile}) — Repo-relative path to the test file to create or update (must end with `.test.ts`).163. **(Optional) SOURCE_FILE_PATH** (${sourceFile}) — Repo-relative path to the implementation file (e.g. `src/controllers/auth.controller.ts`) for context and import resolution.1718Example:1920```21AuthController.login22test/controllers/auth.controller.test.ts23src/controllers/auth.controller.ts24```2526## Output2728- **Markdown-fenced TypeScript** test content (or delta additions) only.29- **Apply changes directly** to ${testFile} in the workspace (create/update the file). Chat output must match the saved file. Do **not** only suggest edits in chat.30- **Never modify** the production file (${sourceFile}) when generating tests. Do not add factories or hooks in production to inject mocks.3132## Context linking3334If ${sourceFile} is supplied, output (before the code block) two plain lines:3536- `Implementation: ${sourceFile}`37- `Test File: ${testFile}`3839If not supplied, skip these lines; do not guess paths. Relative imports in code are inferred from the provided source path.4041---4243## Golden rules44451. **TypeScript/ESM:** `import ... from '...'`. Test files are `.test.ts`; source under **`src/`** (e.g. `src/controllers/`, `src/lib/`, `src/model/`).462. **Structure:** Each **class** gets a top-level `describe('<ClassName>')`. Each **method** gets a nested `describe('<methodName>')` — use the **real method name** (e.g. `login`, `getNations`), **not** `__methodName`.473. **Organization:** Inside each method block use optional `describe('Success')` / `describe('Error')` when branches > 2; else individual `it` cases.484. **Sinon:** Use for stubs/spies; prefer `sinon.assert.calledWith` over manual argument inspection.495. **Async errors:** No chai-as-promised; use try/catch for async error assertions.506. **Controller private methods:** Call via `(controller as any).methodName(...)`. Stub with `sinon.stub(controller as any, 'methodName')` (real name, no `__`).517. **Secrets/config:** Never import production secrets or mutate real environment configs.528. **No obsolete refs:** Do not reference removed or project-specific instruction files; integrate any needed logic into the test design.539. **SQL:** Do not assert on raw SQL strings; only assert that the query method was called with objects of the expected shape (e.g. replacements). Use **`transactionClient`** in assertions (not `transaction`). Stub **`queryReturnFirst`** when the controller uses it; stub **`query`** when it expects `{ rows }`.5410. **File writes:** Always update ${testFile} on disk; chat output must mirror the saved content.5511. **Production code:** Never modify ${sourceFile}. Prefer: (a) **complete mock config** so constructors do not throw (e.g. pubSub options, getstream, sms), (b) minimal fake env when config is missing, (c) local HTTP server or fixtures under `test/` only.5612. **Run tests (entire file, mandatory):** After writing tests, **always run the full `${testFile}` suite** (e.g. `npm test -- ${testFile}`), not just newly added tests or filtered `describe/it` blocks. Iterate until **all tests in that file pass**. Fix failures by changing **test code only**, not production.5713. **ESM stubs:** Do not stub immutable ES Module default exports; Sinon cannot stub ESM bindings. Use HTTP server in test or indirection under `test/fixtures/` only if that pattern exists (do not edit production).5814. **Static utils:** When encrypt/decrypt or similar static utilities are used, stub only those static methods (e.g. `Crypt.encryptAES`); do not alter the class file.5915. **Unreachable branches:** If a branch is impossible to cover without changing production, add `// TODO: unreachable branch without code change` instead of changing production.6016. **PubSub/Notifications:** Do not stub constructors or add production hooks. In the mock env provide **config** (e.g. `config.pubSubOptions` with `topicId` and `authentication: { projectId, credentials }`) so `new NotificationsManager(env)` (and any internal PubSub client) does not throw. Add `mockNotificationManager.store.resolves()` and `mockNotificationManager.publish.resolves()` so async flow completes. For other deps (e.g. Getstream, SMS), provide the corresponding **config** entries so constructors do not read `undefined`.6117. **Rollback:** If the controller does **not** wrap `rollback` in try/catch, when `rollback` rejects, `next` is called with the **rollback error**. Assert `next(rollbackError)` and do not expect logger.error for rollback in that case.6218. **Logger:** If the code under test uses `this.env.logger.warning`, the mock env must provide `logger.warning` (not only `logger.warn`).6364---6566## Coverage expectations6768Cover: happy path, each conditional branch, invalid parameters, edge values (0, empty array, null, undefined), error propagation (`next(error)` in controllers, thrown errors in models/libs). Validate:6970- HTTP status codes and response methods (`send`, `sendStatus`, `json`, `cookie`, `clearCookie`).71- Sequence and arguments of model/DB operations.72- Side effects: cookie set/cleared, session manager calls, grants updated, data transformations.7374---7576## Folder-specific directives7778### Controllers (`test/controllers/*.test.ts`)7980- Mock **env** with: session config, getstream/sms (or equivalent) config, `pgConnection`, `pgModels`, `session` (and `sessionManager` if used), and any other connections the controller uses (e.g. `documentsConnection`).81- For code that builds a notifications/pub-sub manager, provide **config** (e.g. `config.pubSubOptions` with `topicId` and `authentication: { projectId, credentials }`) so the constructor does not throw; add `store.resolves()` and `publish.resolves()` on the mock where needed.82- Stub `env.session.checkAuthentication()` to return a pass-through middleware when needed.83- **Call controller methods** via `(controller as any).methodName(request, response, next)` — real method name.84- For methods that set cookies: assert the **third argument** of `response.cookie` (options object); use `sinon.match.object` or check for `expires` when testing persistent sessions.85- **Transactions:** Stub `pgConnection.startTransaction` with `.resolves(t)` and use the same `t` for `commit(t)` / `rollback(t)`. In assertions use **`transactionClient`** (not `transaction`). For **`updateByKey`**, keys are an **array** (e.g. `["id_us"]`, `['id_up']`); payload may include fields from `request.session` (e.g. `id_last_updater_up`).86- Error path: ensure `next(error)` is called with the correct error (original or **rollback error** if rollback rejects and controller does not wrap it).87- Assert only externally observable behavior (responses and env calls), not implementation details.8889### Lib utilities (`test/lib/*.test.ts`)9091- Use Node `assert` or `chai.expect` for pure functions; exhaustive yet concise.92- Cover boundaries: empty arrays, null/undefined, formatting edge cases.93- For validators: valid value, invalid formats, null, undefined, empty, malformed.94- Stub only when the function uses time or randomness (e.g. `sinon.useFakeTimers()`).95- **Import paths:** From `test/lib/` use **`../../src/...`** (two levels to project root). From **`test/lib/notifications/`** use **`../../../src/...`** and **`../../../config/...`** (three levels).96- For classes with private methods: call via `(instance as any).methodName(...)`; stub with `sinon.stub(instance as any, 'methodName')`. If the class has a single-argument constructor (e.g. options object), use that; method names are real (e.g. `sendRequest`), not prefixed with `__`.9798### Postgres models (`test/model/postgres/*.test.ts` or `test/pg-models/*.test.ts`)99100- Mock connection with stubbed methods: `query`, `queryReturnFirst`, `queryPaged`, `insert`, `updateByKey`, `startTransaction`, `commit`, `rollback` as used. Use `.resolves(t)` for `startTransaction` so the same `t` is used for `commit`/`rollback`.101- Stub return shapes to match the actual API: **`queryPaged`** returns `{ totalRowCount, rows }` or `{ total, rows }`; **`query`** returns `{ rows }`. Use **aliased column names** in mock rows when the SQL uses `AS`.102- For each method: assert correct `replacements` and optionally `sinon.match({ sql: sinon.match(/select/), replacements: [...] })`. Use **`transactionClient`** when the method passes a transaction.103- Simulate DB responses: `{ rows: [...] }`, `{ rows: [] }`, `null`, rejection. Align stub with how the model uses the result (e.g. `result?.rows ?? []` or throw when null).104- Error path must bubble the same Error instance.105- Transactional flows: assert order `startTransaction` → updates/inserts → `commit`; error branch triggers `rollback`.106107### Notifications / domain logic (`test/lib/notifications/*.test.ts`, `test/lib/*-notifications.test.ts`)108109- Do not change production to inject mocks. Provide **mock config** so the notifications/pub-sub manager constructor does not throw (e.g. `config.pubSubOptions` with `topicId` and `authentication: { projectId, credentials }`).110- Add `mockNotificationManager.store.resolves()` and `mockNotificationManager.publish.resolves()` so async flow completes.111- Call **private methods** via `(notifications as any).methodName(...)`; use `describe('methodName', ...)`.112- Assert payload structure and invocation count on store/publish mocks. Include failure of underlying store and error propagation.113- **Import paths:** From **`test/lib/notifications/`** use **`../../../src/...`** and **`../../../config/...`** (three levels).114115### External service classes (e.g. Bridge, Getstream)116117- If the class constructor takes a **single** options object and has a private method like `sendRequest`, stub with `sinon.stub(instance as any, 'sendRequest')`.118- If the class needs DB/config/logger, provide a **complete mock** (e.g. `pgConnection.queryReturnFirst`, `config.getstream`) so constructors do not throw.119- Restore stubs in `afterEach`: `sinon.restore()`.120121### Export / batch utilities122123- Use a **minimal fake env** (e.g. stubbed `pgConnection`, `pgModels`) instead of a full real Environment when config is missing or incomplete.124- For helpers with private methods, call via `(helper as any).methodName(...)`.125- If file writes or streams occur, stub fs or stream constructors. Validate produced output (e.g. CSV) with a sample subset.126- Include an edge case for larger input (e.g. 1000 items) to ensure no throw and transformation called per item.127128---129130## Assertion strategy131132- `sinon.assert.calledOnce(stub)`, `sinon.assert.calledWith(stub, expectedArgs...)`133- **`sinon.match`** for partial object or regex match of SQL. For `pgConnection.query` / `updateByKey`, use **`transactionClient`** in expected args (not `transaction`).134- For **query** calls, assert the shape passed by the code: e.g. `{ sql, replacements }` or `{ sql, replacements, transactionClient }`.135- **`updateByKey`:** keys are an **array**; payload may include session-derived fields.136- For arrays and order-sensitive logic, use deep equality.137- For dates: `sinon.match.date` or `instanceof Date`.138- **Session/cookie:** assert the third argument of `response.cookie` (options object); use `sinon.match.object` or check `expires` for persistent sessions.139140---141142## Error assertion pattern (async)143144```ts145try {146 await subject.method(args);147 assert.fail('Expected method to throw');148} catch (err) {149 assert.strictEqual(err, expectedError); // or shape assertions150}151```152153---154155## Edge cases checklist156157- Null / undefined inputs158- Empty arrays / empty objects159- Boundary numerics: 0, -1 (if invalid), large numbers160- Missing required properties161- Duplicate entries (where uniqueness applies)162- Partial updates (optional fields omitted)163- Upstream failure (e.g. token generation, notification push)164165---166167## Session and auth168169When controller endpoints require auth:170171- Stub `env.session.checkAuthentication` to return `(req, res, next) => next()`.172- Test unauthenticated path only if the controller itself branches on session absence; otherwise rely on middleware coverage elsewhere.173174---175176## Generated file behavior177178- **If ${testFile} exists:** Merge new test blocks without duplicating existing method `describe`. If the method block already exists, add only missing branches/cases. Do not remove or rename existing tests.179- **If ${testFile} does not exist:** Generate full skeleton (imports, top-level describe, method-level describes, coverage template). Use `// TODO` for logic that cannot be inferred.180181In all cases, **update the real ${testFile} on disk** to match the produced output.182183---184185## Import paths186187- From `test/` or `test/controllers/` or `test/lib/`: **`../../src/...`** (two levels to project root).188- From **`test/lib/notifications/`**: **`../../../src/...`** and **`../../../config/...`** (three levels).189190Use **static imports** where possible. If loading in a hook, `require('../../src/lib/...')` with tsx/cjs resolves correctly. Use the project’s shared types/constants package (e.g. `HttpResponseStatus`) when the codebase does.191192---193194## Output format195196Provide only the test file content inside a fenced ` ```ts ` or ` ```typescript ` block. When updating, show only new or changed blocks preceded by a brief comment `// Added tests for <method>`.197198---199200## Parameter mapping201202- **${targetCode}:** Class or Class.method to test. Use the **real method name**. If only Class.method is supplied, generate tests for that method but keep the class-level and method-level `describe` hierarchy.203- **${testFile}:** Must end with **`.test.ts`**. Drives import depth: **two levels** (`../../`) from `test/`, `test/controllers/`, or `test/lib/`; **three levels** (`../../../`) from `test/lib/notifications/`.204- **${sourceFile}:** Optional; use to compute relative import path. Source under **`src/`**; use **`.ts`** or no extension per project resolution. Do not use `.mjs`.205206---207208## Quality gates (self-check)209210- [ ] All new describe blocks follow the pattern.211- [ ] No references to removed or project-specific instruction files.212- [ ] Sinon assertions used consistently.213- [ ] No hardcoded secrets or environment leakage.214- [ ] Edge cases addressed.215- [ ] Tests run and pass after writing.216217---218219## When information is ambiguous220221Insert a `// TODO:` comment with a concise note (max 60 chars) rather than guessing behavior that cannot be inferred from the code.222223Return only the test code per the instructions above — no extra commentary beyond mandated context lines and added-block comments.224225END OF SKILL.