Files
the-collective-hub/.github/prompts/test-coverage.prompt.md
T
KungRaseri b192cd53ba docs(copilot): add Copilot instructions for The Collective Hub
- Add comprehensive project overview and core philosophy
- Document file structure reference for the codebase
- Create key files reference table for task-specific guidance
- Include multi-tenant guidelines and site resolution flow
2026-06-05 23:46:15 -07:00

191 lines
5.3 KiB
Markdown

---
agent: 'agent'
description: Analyse test coverage gaps for a file or directory and generate missing tests
---
You are performing test coverage analysis and generating missing tests for The Collective Hub project.
## Your task
The user has provided one or more source files or a directory to analyse. For each file:
1. Read the source file
2. Identify all exported functions, components, handlers, and branches that lack test coverage
3. Check whether a co-located test file already exists
4. Generate or extend the test file to cover the gaps
If the user has not specified a file, ask them to provide one before proceeding.
---
## Coverage analysis checklist
For each source file, enumerate all of the following that need tests:
### Server files (`*.server.ts`, `+server.ts`, `+page.server.ts`)
- [ ] Every exported `load` function — success path, unauthenticated redirect, DB error
- [ ] Every form `action` — valid input, `fail()` path, redirect path
- [ ] Every HTTP handler (`GET`, `POST`, `PATCH`, `DELETE`) — 2xx and 4xx/5xx paths
- [ ] Auth guard branches — unauthenticated (`locals.user` is null), insufficient role
- [ ] Query results — empty array, single result, multiple results
### Svelte components (`*.svelte`)
- [ ] Default render with required props
- [ ] Every `{#if}` branch (both true and false)
- [ ] Every `{#each}` branch — empty array, non-empty array
- [ ] User interactions — click, input, form submit
- [ ] Conditional class/style variations driven by props
- [ ] Slot/snippet presence and absence (note as limitation if not testable)
### Utility / library files (`*.ts`)
- [ ] Every exported function — happy path
- [ ] Edge cases: empty input, null/undefined, boundary values
- [ ] Error paths: thrown errors, returned error objects
---
## File placement rules
| Source file | Test file |
| ------------------------------------------- | -------------------------------------------------- |
| `src/lib/utils/format.ts` | `src/lib/utils/format.test.ts` |
| `src/lib/components/ui/ServiceCard.svelte` | `src/lib/components/ui/ServiceCard.svelte.test.ts` |
| `src/routes/api/contact/+server.ts` | `src/routes/api/contact/server.test.ts` |
| `src/routes/(app)/services/+page.server.ts` | `src/routes/(app)/services/page.server.test.ts` |
> **Drop the `+` prefix** for route test files — SvelteKit errors on `+server.test.ts` at build time.
> Server tests use `.test.ts`; component tests use `.svelte.test.ts`.
---
## Mocking rules
### Always mock the database
`vi.mock` is hoisted before `const` declarations. **Always use `vi.hoisted()`** for mock functions referenced inside `vi.mock` factories:
```ts
const { mockFindMany, mockInsert } = vi.hoisted(() => ({
mockFindMany: vi.fn(),
mockInsert: vi.fn()
}));
vi.mock('$lib/server/db', () => ({
db: {
query: {
services: { findMany: mockFindMany, findFirst: vi.fn() }
},
insert: mockInsert
}
}));
```
Reset mocks in `beforeEach`:
```ts
beforeEach(() => {
vi.clearAllMocks();
});
```
### Create a mock RequestEvent for +server.ts handlers
```ts
function mockEvent(overrides: Partial<RequestEvent> = {}): RequestEvent {
return {
request: new Request('http://localhost/api/resource', { method: 'GET' }),
locals: { user: { id: 'user-1', role: 'user' } },
params: {},
url: new URL('http://localhost/api/resource'),
...overrides
} as unknown as RequestEvent;
}
```
### Create a mock PageServerLoadEvent for load functions
```ts
function mockLoadEvent(overrides = {}) {
return {
locals: { user: { id: 'user-1', role: 'user' } },
params: {},
url: new URL('http://localhost/page'),
...overrides
} as any;
}
```
### Stub fetch for external API calls
```ts
vi.stubGlobal(
'fetch',
vi.fn().mockResolvedValue(new Response(JSON.stringify({ data: [] }), { status: 200 }))
);
```
---
## Test structure
```ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
// mocks before imports that use them
const { mockFn } = vi.hoisted(() => ({ mockFn: vi.fn() }));
vi.mock('$lib/server/db', () => ({ db: { query: { table: { findMany: mockFn } } } }));
import { myFunction } from './myModule';
describe('myFunction', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('returns expected result for valid input', async () => {
mockFn.mockResolvedValue([{ id: 1 }]);
const result = await myFunction('valid');
expect(result).toEqual({ id: 1 });
});
it('returns null when not found', async () => {
mockFn.mockResolvedValue([]);
const result = await myFunction('missing');
expect(result).toBeNull();
});
});
```
---
## requireAssertions rule
`expect.requireAssertions: true` is set globally. **Every `it` block must contain at least one `expect()`** or the test will fail even if no error is thrown.
---
## Coverage run command
After generating tests, remind the user they can check coverage with:
```sh
npm run test:run -- --coverage
```
The HTML report is written to `coverage/index.html`.
---
## Output format
For each source file analysed:
1. **Coverage gaps** — bullet list of untested functions/branches
2. **Test file path** — where the new/updated test file will go
3. **Generated test file** — full content, ready to save
If a test file already exists, show only the **new `it` blocks** to add, not the full file.