E2E Tests with Supertest

The Whole App over HTTP

test/products.e2e-spec.ts

import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import request from 'supertest';
import { AppModule } from '../src/app.module';
import { PrismaService } from '../src/prisma/prisma.service';

describe('Products (e2e)', () => {
  let app: INestApplication;
  let prisma: PrismaService;
  let adminToken: string;

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({ imports: [AppModule] }).compile();
    app = moduleRef.createNestApplication();
    app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));   // same as main.ts
    await app.init();

    prisma = app.get(PrismaService);
    await prisma.product.deleteMany();
    const res = await request(app.getHttpServer())
      .post('/auth/login')
      .send({ email: '[email protected]', password: 'Admin@2026' });
    adminToken = res.body.accessToken;
  });

  afterAll(async () => {
    await app.close();
  });

  it('GET /products is public', () => {
    return request(app.getHttpServer()).get('/products').expect(200);
  });

  it('POST /products needs a token', () => {
    return request(app.getHttpServer()).post('/products').send({}).expect(401);
  });

  it('POST /products validates the body', async () => {
    const res = await request(app.getHttpServer())
      .post('/products')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ name: 'TV', price: -1 })
      .expect(400);
    expect(res.body.message).toContain('price must be a positive number');
  });

  it('POST /products creates a product', async () => {
    const res = await request(app.getHttpServer())
      .post('/products')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ name: 'JBL Go 3', price: 2999, stock: 10, categoryId: 1 })
      .expect(201);
    expect(res.body).toMatchObject({ id: expect.any(Number), name: 'JBL Go 3' });
  });
});

Running Against a Test Database

Example

Point DATABASE_URL at a separate test database (for example a Docker container started in CI) and apply migrations first:

export DATABASE_URL=postgresql://shopease:secret@localhost:5433/shopease_test
npx prisma migrate deploy && npx prisma db seed
npm run test:e2e

Example output

 PASS  test/products.e2e-spec.ts (6.112 s)
  Products (e2e)
    ✓ GET /products is public (41 ms)
    ✓ POST /products needs a token (9 ms)
    ✓ POST /products validates the body (14 ms)
    ✓ POST /products creates a product (23 ms)

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total