
Faasjs Unit Testing
- 2 installs
- 1 repo stars
- Updated February 18, 2026
- faasjs/faasjs-skills
Playbook for writing FaasJS unit tests using the test() entry from @faasjs/dev, shared mock setup, and a coverage matrix.
About
Guides writing and refactoring FaasJS unit tests around the test() helper, precise HTTP-style assertions, and shared mock lifecycles. A FaasJS developer applies it when authoring or reviewing tests to keep setup DRY and coverage consistent.
- Standardizes on test() from @faasjs/dev with precise assertions
- References test-only, shared-testing, and test-matrix guides
Faasjs Unit Testing by the numbers
- 2 all-time installs (skills.sh)
- Ranked #1,683 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Jul 13, 2026 (Skillselion catalog sync)
npx skills add https://github.com/faasjs/faasjs-skills --skill faasjs-unit-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 1 |
| Last updated | February 18, 2026 |
| Repository | faasjs/faasjs-skills ↗ |
What it does
Playbook for writing FaasJS unit tests using the test() entry from @faasjs/dev, shared mock setup, and a coverage matrix.
Files
Apply this skill when writing, refactoring, or reviewing unit tests in FaasJS projects.
Core rules
- Use
test()from@faasjs/devas the default test entry. - Keep test files in
__tests__/and name them*.test.ts. - Prefer precise assertions (
statusCode,data,error,headers) over broad truthy checks. - Extract repeated mock/setup logic into shared test helpers.
Guides
See Test-only workflow for:
- Standard
test(func)usage patterns - HTTP-style assertions via
JSONhandler - Non-HTTP assertions via
handler
See Shared testing kit for:
- Shared mock lifecycle for repeated module mocks
- Reusable caller helper to remove repeated request setup
- Recommended
shared/directory layout
See Test matrix for:
- Minimal behavior coverage checklist
- Incremental run strategy for fast feedback
Shared Testing Kit
When the same mock/setup appears in 2+ test files, extract it into shared helpers.
Recommended layout
src/pages/home/api/__tests__/
hello.test.ts
create-user.test.ts
shared/
mocks.ts
lifecycle.ts
call.tsshared/mocks.ts
Use one source of truth for module mocks and reset logic.
import { vi } from 'vitest'
export const sharedMocks = vi.hoisted(() => ({
query: vi.fn(),
transaction: vi.fn(),
now: vi.fn(() => '2026-02-17T00:00:00.000Z'),
}))
vi.mock('@faasjs/knex', () => ({
query: sharedMocks.query,
transaction: sharedMocks.transaction,
}))
export function resetSharedMocks(): void {
sharedMocks.query.mockReset()
sharedMocks.transaction.mockReset()
sharedMocks.now.mockReset()
}shared/lifecycle.ts
Provide one reusable lifecycle hook to keep cleanup consistent.
import { afterEach, beforeEach, vi } from 'vitest'
import { resetSharedMocks } from './mocks'
export function useSharedLifecycle(): void {
beforeEach(() => {
vi.clearAllMocks()
resetSharedMocks()
})
afterEach(() => {
vi.restoreAllMocks()
})
}shared/call.ts
Wrap repeated test(func).JSONhandler(...) options to reduce boilerplate.
import { test } from '@faasjs/dev'
import type { Func } from '@faasjs/func'
type JsonCallOptions = {
headers?: Record<string, string>
cookie?: Record<string, any>
session?: Record<string, any>
}
export function createJsonCaller(func: Func) {
const call = test(func)
return async function invoke(
body?: Record<string, unknown> | string | null,
options: JsonCallOptions = {}
) {
return await call.JSONhandler(body, {
headers: {
'x-request-id': 'unit-test',
...options.headers,
},
cookie: options.cookie,
session: options.session,
})
}
}Adoption rule
- Start local for a single file.
- Promote to
shared/once repeated in multiple files. - Keep shared helpers minimal and deterministic.
Test Matrix
Use this checklist when improving existing unit tests.
Minimum coverage matrix
1. Happy path
- Valid input returns expected
statusCodeanddata.
2. Input validation
- Invalid or missing params return stable validation error output.
3. Business error
- Domain failure path returns expected message/code.
4. Plugin side effects
- Verify cookie/session/database side effects when relevant.
5. Transport details
- Assert key headers/content behavior only when business-critical.
Shared-first refactor checklist
- Remove duplicated mocks into
shared/mocks.ts. - Remove duplicated
beforeEach/afterEachintoshared/lifecycle.ts. - Remove duplicated
JSONhandlersetup intoshared/call.ts. - Keep each test focused on one behavior.
Run strategy
Run incrementally for quick feedback, then full verification:
# target file or pattern first
mise exec -- npm run test -- path/to/file.test.ts
# full unit suite
mise exec -- npm run test
# ci mode with coverage
mise exec -- npm run ciTest-only Workflow
Use test() from @faasjs/dev as the first choice for FaasJS unit tests.
Why test()
- It is the stable public helper exposed for testing in
@faasjs/dev. - It already provides
handler()andJSONhandler()wrappers. - It keeps tests concise and avoids repeated wrapper binding code.
Basic pattern
import { test } from '@faasjs/dev'
import { func } from '../hello.func'
describe('home/api/hello', () => {
it('returns hello message', async () => {
const { statusCode, data } = await test(func).JSONhandler({ name: 'world' })
expect(statusCode).toEqual(200)
expect(data).toEqual({
message: 'Hello, world',
})
})
})Assertion rules
- HTTP-style functions: assert
statusCode+data/error+ key headers when needed. - Pure function logic: use
await test(func).handler(...)and assert domain output. - Error paths: assert specific message/code to avoid brittle snapshots.
Anti-patterns
- Do not assert full response objects when only one field matters.
- Do not couple test order; keep each case independently runnable.