Skip to content

Story Desk Backend

Backend API server for Story Desk application.

Getting Started

Prerequisites

  • Node.js (v18+)
  • MongoDB (or use MongoDB Memory Server for testing)

Installation

npm install
npm run setup  # Install git hooks via lefthook

Environment Variables

Copy .env.example to .env and configure the required variables.

Running the Server

# Development
npm run dev

# Production
npm run build
npm start

Testing

The project uses Jest with separate configurations for unit and integration tests.

Test Structure

tests/
  unit/           # Unit tests with mocked dependencies
  integration/    # Integration tests with MongoDB Memory Server

Running Tests

# Run all tests
npm test

# Run unit tests only
npm run test:unit

# Run integration tests only
npm run test:integration

# Run tests with coverage
npm run test:coverage        # Unit tests only
npm run test:coverage:all    # All tests

# Watch mode
npm run test:watch

Coverage Thresholds

The project enforces strict coverage thresholds: - Lines/Statements/Functions: 95% - Branches: 75%

Coverage is enforced via lefthook pre-push hooks.

Test Architecture

Unit Tests (tests/unit/)

  • Test individual functions and classes in isolation
  • All external dependencies are mocked
  • Uses deterministic UUID mocking for predictable test data

Integration Tests (tests/integration/)

  • Test full API request/response cycles
  • Uses MongoDB Memory Server for isolated database testing
  • External services (OpenAI, Email) are mocked
  • Environment variables are corrupted to prevent accidental use of real services

Writing Tests

Unit Test Example

import { someFunction } from '../../src/services/example.service';

jest.mock('../../src/external-dependency');

describe('someFunction', () => {
  it('should return expected result', () => {
    const result = someFunction(input);
    expect(result).toBe(expected);
  });
});

Integration Test Example

import request from 'supertest';
import app from '../../src/index';
import { setupTestDB, teardownTestDB } from '../integration/helpers/setup';

describe('API Endpoint', () => {
  beforeAll(async () => {
    await setupTestDB();
  });

  afterAll(async () => {
    await teardownTestDB();
  });

  it('should return 200', async () => {
    const response = await request(app).get('/api/endpoint');
    expect(response.status).toBe(200);
  });
});

Test Helpers

Located in tests/integration/helpers/:

  • setup.ts - MongoDB Memory Server setup/teardown
  • envCorrupter.ts - Corrupts env vars to prevent real service usage
  • testUser.ts - Test user credentials and signup codes
  • mockOpenAI.ts - OpenAI response mocking utilities

Test Flows

Reusable test flows in tests/integration/flows/:

  • signupFlow.ts - User registration flow
  • loginFlow.ts - User authentication flow
  • storyFlow.ts - Story CRUD operations
  • llmChatFlow.ts - LLM chat interactions

Linting

npm run lint

Building

npm run build

Git Hooks

Git hooks are managed via Lefthook:

  • pre-commit: ESLint and TypeScript build checks
  • pre-push: Test coverage threshold enforcement