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('GroupsController (e2e)', () => { let app: INestApplication; let accessToken: string; let testUser: any; let testUserId: string; let testGroupId: string; let testProjectId: string; let testPersonId: 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 person const personResponse = await request(app.getHttpServer()) .post('/api/persons') .set('Authorization', `Bearer ${accessToken}`) .send({ name: `Test Person ${uuidv4().substring(0, 8)}`, projectId: testProjectId, skills: ['JavaScript', 'TypeScript'], metadata: { email: 'testperson@example.com' } }); testPersonId = personResponse.body.id; }); afterAll(async () => { // Clean up test data if (testGroupId) { await request(app.getHttpServer()) .delete(`/api/groups/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`); } if (testPersonId) { await request(app.getHttpServer()) .delete(`/api/persons/${testPersonId}`) .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/groups', () => { it('should create a new group', async () => { const createGroupDto = { name: `Test Group ${uuidv4().substring(0, 8)}`, projectId: testProjectId, description: 'Test group for e2e tests' }; const response = await request(app.getHttpServer()) .post('/api/groups') .set('Authorization', `Bearer ${accessToken}`) .send(createGroupDto) .expect(201); expect(response.body).toHaveProperty('id'); expect(response.body.name).toBe(createGroupDto.name); expect(response.body.projectId).toBe(createGroupDto.projectId); testGroupId = response.body.id; }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .post('/api/groups') .send({ name: 'Unauthorized Group', projectId: testProjectId }) .expect(401); }); }); describe('GET /api/groups', () => { it('should return all groups', () => { return request(app.getHttpServer()) .get('/api/groups') .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(group => group.id === testGroupId)).toBe(true); }); }); it('should filter groups by project ID', () => { return request(app.getHttpServer()) .get(`/api/groups?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(group => group.projectId === testProjectId)).toBe(true); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .get('/api/groups') .expect(401); }); }); describe('GET /api/groups/:id', () => { it('should return a group by ID', () => { return request(app.getHttpServer()) .get(`/api/groups/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(200) .expect((res) => { expect(res.body).toHaveProperty('id', testGroupId); expect(res.body).toHaveProperty('projectId', testProjectId); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .get(`/api/groups/${testGroupId}`) .expect(401); }); it('should return 404 for non-existent group', () => { const nonExistentId = uuidv4(); return request(app.getHttpServer()) .get(`/api/groups/${nonExistentId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(404); }); }); describe('PUT /api/groups/:id', () => { it('should update a group', () => { const updateData = { name: `Updated Group ${uuidv4().substring(0, 8)}`, description: 'Updated description' }; return request(app.getHttpServer()) .put(`/api/groups/${testGroupId}`) .set('Authorization', `Bearer ${accessToken}`) .send(updateData) .expect(200) .expect((res) => { expect(res.body).toHaveProperty('id', testGroupId); expect(res.body.name).toBe(updateData.name); expect(res.body.description).toBe(updateData.description); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .put(`/api/groups/${testGroupId}`) .send({ name: 'Unauthorized Update' }) .expect(401); }); }); describe('POST /api/groups/:id/persons/:personId', () => { it('should add a person to a group', () => { return request(app.getHttpServer()) .post(`/api/groups/${testGroupId}/persons/${testPersonId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(201) .expect((res) => { expect(res.body).toHaveProperty('id', testGroupId); expect(res.body.persons).toContainEqual(expect.objectContaining({ id: testPersonId })); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .post(`/api/groups/${testGroupId}/persons/${testPersonId}`) .expect(401); }); }); describe('GET /api/groups/:id/persons', () => { it('should get all persons in a group', () => { return request(app.getHttpServer()) .get(`/api/groups/${testGroupId}/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 return 401 when not authenticated', () => { return request(app.getHttpServer()) .get(`/api/groups/${testGroupId}/persons`) .expect(401); }); }); describe('DELETE /api/groups/:id/persons/:personId', () => { it('should remove a person from a group', () => { return request(app.getHttpServer()) .delete(`/api/groups/${testGroupId}/persons/${testPersonId}`) .set('Authorization', `Bearer ${accessToken}`) .expect(200) .expect((res) => { expect(res.body).toHaveProperty('id', testGroupId); expect(res.body.persons.every(person => person.id !== testPersonId)).toBe(true); }); }); it('should return 401 when not authenticated', () => { return request(app.getHttpServer()) .delete(`/api/groups/${testGroupId}/persons/${testPersonId}`) .expect(401); }); }); // Note: We're not testing the DELETE /api/groups/:id endpoint here to avoid complications with test cleanup });