Overview
The backend has zero automated tests. Any refactor or new feature can silently break existing behavior. This issue establishes the NestJS testing foundation and writes unit + integration tests for the most critical modules: Auth, Shipments, and Guards. The companion backend test issue for remaining modules is [BE-32].
Technical Details
1. Testing Framework Setup
NestJS ships with Jest built in. Confirm the following are in backend/package.json:
"jest": {
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": { "^.+\\.(t|j)s$": "ts-jest" },
"collectCoverageFrom": ["**/*.(t|j)s"],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
Add a test:cov script that runs Jest with --coverage.
2. Auth Service Unit Tests (backend/src/auth/auth.service.spec.ts)
Mock UsersService, JwtService, ConfigService, and MailService. Write tests for:
describe('AuthService') {
it('register() creates a user, hashes password, sends verification email')
it('register() throws ConflictException if email already exists')
it('validateUser() returns user for correct credentials')
it('validateUser() returns null for wrong password')
it('validateUser() returns null for non-existent email')
it('login() returns access_token and refresh_token')
it('refreshToken() returns new tokens for a valid refresh token')
it('refreshToken() throws UnauthorizedException for invalid token')
it('forgotPassword() queues a reset email without revealing user existence')
it('resetPassword() updates password and invalidates the reset token')
it('resetPassword() throws BadRequestException for expired token')
}
3. Shipments Service Unit Tests (backend/src/shipments/shipments.service.spec.ts)
Mock the Shipment repository. Write tests for:
describe('ShipmentsService') {
it('create() sets trackingNumber, status=pending, and assigns the shipperId')
it('findAll() returns only the requesting user\'s shipments')
it('findOne() throws NotFoundException for a shipment that does not exist')
it('findOne() throws ForbiddenException when accessed by a non-party user')
it('updateStatus() transitions pending → accepted correctly')
it('updateStatus() throws BadRequestException for invalid transition (e.g. pending → completed)')
it('updateStatus() throws ForbiddenException when a carrier tries to accept their own bid')
}
4. JWT Auth Guard Integration Test (backend/src/auth/guards/jwt-auth.guard.spec.ts)
Use the NestJS Test.createTestingModule() to spin up a real guard instance:
it('passes for a valid JWT in the Authorization header')
it('passes for a valid JWT in an httpOnly cookie')
it('throws UnauthorizedException for an expired JWT')
it('throws UnauthorizedException for a missing JWT')
it('skips auth for routes decorated with @Public()')
it('throws ForbiddenException for a suspended user')
5. E2E Test Setup (backend/test/app.e2e-spec.ts)
Set up a NestJS e2e test that starts the full app against a test PostgreSQL database (use an in-memory SQLite or a Docker Compose test service defined in docker-compose.test.yml):
POST /api/v1/auth/register → POST /api/v1/auth/login → GET /api/v1/auth/me full flow
POST /api/v1/shipments → GET /api/v1/shipments/:id → check status = pending
Acceptance Criteria
Overview
The backend has zero automated tests. Any refactor or new feature can silently break existing behavior. This issue establishes the NestJS testing foundation and writes unit + integration tests for the most critical modules: Auth, Shipments, and Guards. The companion backend test issue for remaining modules is [BE-32].
Technical Details
1. Testing Framework Setup
NestJS ships with Jest built in. Confirm the following are in
backend/package.json:Add a
test:covscript that runs Jest with--coverage.2. Auth Service Unit Tests (
backend/src/auth/auth.service.spec.ts)Mock
UsersService,JwtService,ConfigService, andMailService. Write tests for:3. Shipments Service Unit Tests (
backend/src/shipments/shipments.service.spec.ts)Mock the
Shipmentrepository. Write tests for:4. JWT Auth Guard Integration Test (
backend/src/auth/guards/jwt-auth.guard.spec.ts)Use the NestJS
Test.createTestingModule()to spin up a real guard instance:5. E2E Test Setup (
backend/test/app.e2e-spec.ts)Set up a NestJS e2e test that starts the full app against a test PostgreSQL database (use an in-memory SQLite or a Docker Compose
testservice defined indocker-compose.test.yml):POST /api/v1/auth/register→POST /api/v1/auth/login→GET /api/v1/auth/mefull flowPOST /api/v1/shipments→GET /api/v1/shipments/:id→ check status = pendingAcceptance Criteria
npm run testruns without errors and all tests passnpm run test:covreports ≥ 70% line coverage forauth.service.tsnpm run test:covreports ≥ 60% line coverage forshipments.service.ts@Public()bypass and suspended user check)package.jsonorjest.config.ts