From e97733f4afdc25c9662fc7ad42d71bd650178260 Mon Sep 17 00:00:00 2001 From: Mehmet Dogan Date: Sun, 8 Jun 2025 12:56:46 +0200 Subject: [PATCH] Add FircleController integration tests with in-memory Prisma --- .gitignore | 2 + apps/api/jest.config.js | 2 +- apps/api/prisma/test-schema.prisma | 41 +++++++++++++ apps/api/test/fircle.spec.ts | 98 ++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 apps/api/prisma/test-schema.prisma create mode 100644 apps/api/test/fircle.spec.ts diff --git a/.gitignore b/.gitignore index 123ae94..e646e05 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules +apps/api/generated +apps/api/prisma/test.db diff --git a/apps/api/jest.config.js b/apps/api/jest.config.js index 29d0967..ba20075 100644 --- a/apps/api/jest.config.js +++ b/apps/api/jest.config.js @@ -6,7 +6,7 @@ module.exports = { diagnostics: false, }, }, - roots: ['/src'], + roots: ['/src', '/test'], coverageDirectory: '/coverage', collectCoverageFrom: ['src/**/*.ts', '!src/main.ts'], }; diff --git a/apps/api/prisma/test-schema.prisma b/apps/api/prisma/test-schema.prisma new file mode 100644 index 0000000..facf1b7 --- /dev/null +++ b/apps/api/prisma/test-schema.prisma @@ -0,0 +1,41 @@ +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" + output = "../generated/test-client" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String + fircles Fircle[] @relation("Members") + items Item[] + requests LendingRequest[] @relation("Requestor") +} + +model Fircle { + id Int @id @default(autoincrement()) + name String + members User[] @relation("Members") +} + +model Item { + id Int @id @default(autoincrement()) + name String + ownerId Int + owner User @relation(fields: [ownerId], references: [id]) + requests LendingRequest[] +} + +model LendingRequest { + id Int @id @default(autoincrement()) + itemId Int + item Item @relation(fields: [itemId], references: [id]) + requestedById Int + requestedBy User @relation("Requestor", fields: [requestedById], references: [id]) + offerType String +} diff --git a/apps/api/test/fircle.spec.ts b/apps/api/test/fircle.spec.ts new file mode 100644 index 0000000..86d9d98 --- /dev/null +++ b/apps/api/test/fircle.spec.ts @@ -0,0 +1,98 @@ +import { INestApplication } from '@nestjs/common'; +import { Test } from '@nestjs/testing'; +import * as path from 'path'; +process.env.DATABASE_URL = 'file:' + path.join(__dirname, '../prisma/test.db'); +import * as request from 'supertest'; +import { FircleController } from '../src/fircles/fircles.controller'; +import { ItemController } from '../src/items/items.controller'; +import { FirclesService } from '../src/fircles/fircles.service'; +import { ItemsService } from '../src/items/items.service'; +import { PrismaService } from '../src/prisma.service'; +import { PrismaClient } from '../generated/test-client'; + +class TestPrismaService extends PrismaClient {} + +describe('FircleController (e2e)', () => { + let app: INestApplication; + let prisma: TestPrismaService; + + beforeAll(async () => { + const path = require('path'); + process.env.DATABASE_URL = 'file:' + path.join(__dirname, '../prisma/test.db'); + prisma = new TestPrismaService(); + await prisma.$connect(); + const module = await Test.createTestingModule({ + controllers: [FircleController, ItemController], + providers: [ + FirclesService, + ItemsService, + { provide: PrismaService, useValue: prisma }, + ], + }).compile(); + + app = module.createNestApplication(); + await app.init(); + }); + + afterAll(async () => { + await app.close(); + await prisma.$disconnect(); + }); + + beforeEach(async () => { + await prisma.lendingRequest.deleteMany(); + await prisma.item.deleteMany(); + await prisma.fircle.deleteMany(); + await prisma.user.deleteMany(); + }); + + it('POST /fircles', async () => { + const res = await request(app.getHttpServer()) + .post('/fircles') + .send({ name: 'New Fircle' }) + .expect(201); + expect(res.body).toMatchObject({ id: expect.any(Number), name: 'New Fircle' }); + }); + + it('POST /fircles/:id/invite', async () => { + const user = await prisma.user.create({ data: { email: 'a@b.com', name: 'A' } }); + const fircle = await prisma.fircle.create({ data: { name: 'Group1' } }); + + await request(app.getHttpServer()) + .post(`/fircles/${fircle.id}/invite`) + .send({ email: user.email }) + .expect(201); + + const updated = await prisma.fircle.findUnique({ where: { id: fircle.id }, include: { members: true } }); + expect(updated?.members.map(m => m.id)).toContain(user.id); + }); + + it('GET /fircles/:id/members', async () => { + const user = await prisma.user.create({ data: { email: 'b@b.com', name: 'B' } }); + const fircle = await prisma.fircle.create({ data: { name: 'Group2', members: { connect: { id: user.id } } } }); + + const res = await request(app.getHttpServer()) + .get(`/fircles/${fircle.id}/members`) + .expect(200); + expect(res.body).toEqual({ members: [{ id: user.id, email: user.email, name: user.name }] }); + }); + + it('POST /items/:id/request-lend', async () => { + const user = await prisma.user.create({ data: { email: 'c@b.com', name: 'C' } }); + const item = await prisma.item.create({ data: { name: 'Item1', ownerId: user.id } }); + + const res = await request(app.getHttpServer()) + .post(`/items/${item.id}/request-lend`) + .send({ requestedBy: user.id, offerType: 'LEND' }) + .expect(201); + expect(res.body).toMatchObject({ itemId: item.id, requestedById: user.id, offerType: 'LEND' }); + }); + + it('POST /fircles/:id/items returns 404', async () => { + const fircle = await prisma.fircle.create({ data: { name: 'Group3' } }); + await request(app.getHttpServer()) + .post(`/fircles/${fircle.id}/items`) + .send({ name: 'ItemX' }) + .expect(404); + }); +});