import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; import { createTestApp, createTestUser, generateTokensForUser, cleanupTestData } from './test-utils'; import { v4 as uuidv4 } from 'uuid'; describe('PersonsController (e2e)', () => { let app: INestApplication; let accessToken: string; let testUser: any; let testUserId: string; let testProjectId: string; let testPersonId: string; let testGroupId: string; beforeAll(async () => { app = await createTestApp(); // Create a test user and generate tokens testUser = await createTestUser(app); testUserId = testUser.id; const tokens = await generateTokensForUser(app, testUserId); accessToken = tokens.accessToken; // Create a test project const projectResponse = await request(app.getHttpServer()) .post('/api/projects') .set('Authorization', `Bearer ${accessToken}`) .send({ name: `Test Project ${uuidv4().substring(0, 8)}`, description: 'Test project for e2e tests', ownerId: testUserId }); testProjectId = projectResponse.body.id; // Create a test group const groupResponse = await request(app.getHttpServer()) .post('/api/groups') .set('Authorization', `Bearer ${accessToken}`) .send({ name: `Test Group ${uuidv4().substring(0, 8)}`, projectId: testProjectId, description: 'Test group for e2e tests' }); testGroupId = groupResponse.body.id; }); afterAll(async () => { // Clean up test data if (testPersonId) { await request(app.getHttpServer()) .delete(`/api/persons/${testPersonId}`) .set('Authorization', `Bearer ${accessToken}`); } if (testGroupId) { await request(app.getHttpServer()) .delete(`/api/groups/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`); } if (testProjectId) { await request(app.getHttpServer()) .delete(`/api/projects/${testProjectId}`) .set('Authorization', `Bearer ${accessToken}`); } await cleanupTestData(app, testUserId); await app.close(); }); describe('POST /api/persons', () => { it('should create a new person', async () => { const createPersonDto = { name: `Test Person ${uuidv4().substring(0, 8)}`, projectId: testProjectId, skills: ['JavaScript', 'TypeScript'], metadata: { email: 'testperson@example.com' } }; const response = await request(app.getHttpServer()) .post('/api/persons') .set('Authorization', `Bearer ${accessToken}`) .send(createPersonDto) .expect(201); expect(response.body).toHaveProperty('id'); expect(response.body.name).toBe(createPersonDto.name); expect(response.body.projectId).toBe(createPersonDto.projectId); expect(response.body.skills).toEqual(createPersonDto.skills); testPersonId = response.body.id; }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .post('/api/persons') .send({ name: 'Unauthorized Person', projectId: testProjectId }) .expect(401); }); }); describe('GET /api/persons', () => { it('should return all persons', () => { return request(app.getHttpServer()) .get('/api/persons') .set('Authorization', `Bearer ${accessToken}`) .expect(200) .expect((res) => { expect(Array.isArray(res.body)).toBe(true); expect(res.body.length).toBeGreaterThan(0); expect(res.body.some(person => person.id === testPersonId)).toBe(true); }); }); it('should filter persons by project ID', () => { return request(app.getHttpServer()) .get(`/api/persons?projectId=${testProjectId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(200) .expect((res) => { expect(Array.isArray(res.body)).toBe(true); expect(res.body.length).toBeGreaterThan(0); expect(res.body.every(person => person.projectId === testProjectId)).toBe(true); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .get('/api/persons') .expect(401); }); }); describe('GET /api/persons/:id', () => { it('should return a person by ID', () => { return request(app.getHttpServer()) .get(`/api/persons/${testPersonId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(200) .expect((res) => { expect(res.body).toHaveProperty('id', testPersonId); expect(res.body).toHaveProperty('projectId', testProjectId); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .get(`/api/persons/${testPersonId}`) .expect(401); }); it('should return 404 for non-existent person', () => { const nonExistentId = uuidv4(); return request(app.getHttpServer()) .get(`/api/persons/${nonExistentId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(404); }); }); describe('PATCH /api/persons/:id', () => { it('should update a person', () => { const updateData = { name: `Updated Person ${uuidv4().substring(0, 8)}`, skills: ['JavaScript', 'TypeScript', 'NestJS'] }; return request(app.getHttpServer()) .patch(`/api/persons/${testPersonId}`) .set('Authorization', `Bearer ${accessToken}`) .send(updateData) .expect(200) .expect((res) => { expect(res.body).toHaveProperty('id', testPersonId); expect(res.body.name).toBe(updateData.name); expect(res.body.skills).toEqual(updateData.skills); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .patch(`/api/persons/${testPersonId}`) .send({ name: 'Unauthorized Update' }) .expect(401); }); }); describe('POST /api/persons/:id/groups/:groupId', () => { it('should add a person to a group', () => { return request(app.getHttpServer()) .post(`/api/persons/${testPersonId}/groups/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(201); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .post(`/api/persons/${testPersonId}/groups/${testGroupId}`) .expect(401); }); }); describe('GET /api/persons/project/:projectId/group/:groupId', () => { it('should get persons by project ID and group ID', () => { return request(app.getHttpServer()) .get(`/api/persons/project/${testProjectId}/group/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(200) .expect((res) => { expect(Array.isArray(res.body)).toBe(true); expect(res.body.length).toBeGreaterThan(0); expect(res.body.some(person => person.id === testPersonId)).toBe(true); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .get(`/api/persons/project/${testProjectId}/group/${testGroupId}`) .expect(401); }); }); describe('DELETE /api/persons/:id/groups/:groupId', () => { it('should remove a person from a group', () => { return request(app.getHttpServer()) .delete(`/api/persons/${testPersonId}/groups/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(204); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .delete(`/api/persons/${testPersonId}/groups/${testGroupId}`) .expect(401); }); }); // Note: We're not testing the DELETE /api/persons/:id endpoint here to avoid complications with test cleanup });