| name | backend-testing |
| description | Run backend API tests, reset the database, or start the dev server for manual testing |
Backend Testing and Development
This skill covers running the Vitest API test suite, resetting the development database, and starting the backend server for manual testing.
Running Tests
All commands run from the backend/ directory.
npm test
npm run test:watch
npm run test:coverage
npx vitest run tests/contacts.test.ts
npx vitest run -t "creates a contact"
Test Architecture
- Framework: Vitest + Supertest
- Config:
backend/vitest.config.ts
- Setup:
backend/tests/setup.ts sets env vars (JWT_SECRET, AUTH_BYPASS=true) before any imports
- Helpers:
backend/tests/helpers.ts exports createTestApp() which creates a temp SQLite DB, runs migrations, and returns a fully configured Express app (no listen/cron)
- Isolation: Each test file gets its own temp DB via
createTestApp(). Files run sequentially (fileParallelism: false) because the DB module is a singleton.
- Auth: Most tests use AUTH_BYPASS=true. The
auth.test.ts file also tests real setup/passkey auth with a separate app instance.
- Factory functions:
createContact(), createTag(), createAttribute(), createEvent(), createNote() in helpers.ts call real API endpoints.
Test Files
| File | Endpoints | Tests |
|---|
health.test.ts | /health | 2 |
auth.test.ts | /api/auth/* | 18 |
tags.test.ts | /api/tags | 10 |
attributes.test.ts | /api/attributes | 10 |
contacts.test.ts | /api/contacts | 17 |
contacts-notes.test.ts | /api/contacts/:id/notes | 11 |
contacts-relations.test.ts | /api/contacts/:id/tags, attributes | 10 |
contacts-photos.test.ts | /api/contacts/:id/photo | 7 |
events.test.ts | /api/events | 18 |
dashboard.test.ts | /api/dashboard | 6 |
recycle-bin.test.ts | /api/recycle-bin | 12 |
settings.test.ts | /api/settings | 7 |
backups.test.ts | /api/backups | 7 |
integration/workflows.test.ts | Cross-cutting | 21 |
Key Implementation Details
- The DB singleton (
src/models/database.ts) means only one active DB at a time. createTestApp() calls closeDatabase() before each init.
- The auth middleware caches a
_devUserId. The exported _resetDevUser() in src/middleware/auth.ts resets it between test suites.
- Route modules (
Router() instances) are singletons created at import time. They are stateless so reusing them across multiple Express apps is safe.
- Config (
src/config.ts) is mutated directly in createTestApp() to point at the temp DB path.
Adding New Tests
- Create
backend/tests/<feature>.test.ts
- Import
createTestApp and factory helpers from ./helpers
- Call
createTestApp() in beforeAll, cleanup() in afterAll
- Use
request(ctx.app) from supertest for HTTP calls
- Run
npm test to verify
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import { createTestApp, type TestContext } from './helpers';
describe('My Feature', () => {
let ctx: TestContext;
beforeAll(() => {
ctx = createTestApp();
});
afterAll(() => {
ctx.cleanup();
});
it('does something', async () => {
const res = await request(ctx.app).get('/api/my-endpoint');
expect(res.status).toBe(200);
});
});
Resetting the Development Database
The dev database lives at data/robodex.db (gitignored). To reset it:
rm -f data/robodex.db
npm run clean
npm run migrate
After resetting, restart the dev server. On first request with AUTH_BYPASS=true, a dev user and dummy passkey are auto-created.
Running the Dev Server for Manual Testing
npm run dev
npm run dev
The backend serves the API at http://localhost:3000. With AUTH_BYPASS=true (default in dev), all authenticated endpoints work without login.
To test without auth bypass:
AUTH_BYPASS=false npm run dev
Then use the setup flow at /api/auth/setup/init to create a user and passkey.