254 lines
8.6 KiB
TypeScript
254 lines
8.6 KiB
TypeScript
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('ProjectsController (e2e)', () => {
|
|
let app: INestApplication;
|
|
let accessToken: string;
|
|
let testUser: any;
|
|
let testUserId: string;
|
|
let testProjectId: string;
|
|
let collaboratorUser: any;
|
|
let collaboratorUserId: string;
|
|
let collaboratorAccessToken: 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 collaborator user
|
|
collaboratorUser = await createTestUser(app);
|
|
collaboratorUserId = collaboratorUser.id;
|
|
const collaboratorTokens = await generateTokensForUser(app, collaboratorUserId);
|
|
collaboratorAccessToken = collaboratorTokens.accessToken;
|
|
});
|
|
|
|
afterAll(async () => {
|
|
// Clean up test data
|
|
if (testProjectId) {
|
|
await request(app.getHttpServer())
|
|
.delete(`/api/projects/${testProjectId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`);
|
|
}
|
|
|
|
await cleanupTestData(app, collaboratorUserId);
|
|
await cleanupTestData(app, testUserId);
|
|
await app.close();
|
|
});
|
|
|
|
describe('POST /api/projects', () => {
|
|
it('should create a new project', async () => {
|
|
const createProjectDto = {
|
|
name: `Test Project ${uuidv4().substring(0, 8)}`,
|
|
description: 'Test project for e2e tests',
|
|
ownerId: testUserId
|
|
};
|
|
|
|
const response = await request(app.getHttpServer())
|
|
.post('/api/projects')
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.send(createProjectDto)
|
|
.expect(201);
|
|
|
|
expect(response.body).toHaveProperty('id');
|
|
expect(response.body.name).toBe(createProjectDto.name);
|
|
expect(response.body.description).toBe(createProjectDto.description);
|
|
expect(response.body.ownerId).toBe(createProjectDto.ownerId);
|
|
|
|
testProjectId = response.body.id;
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.post('/api/projects')
|
|
.send({
|
|
name: 'Unauthorized Project',
|
|
ownerId: testUserId
|
|
})
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
describe('GET /api/projects', () => {
|
|
it('should return all projects', () => {
|
|
return request(app.getHttpServer())
|
|
.get('/api/projects')
|
|
.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(project => project.id === testProjectId)).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should filter projects by owner ID', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects?ownerId=${testUserId}`)
|
|
.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(project => project.ownerId === testUserId)).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.get('/api/projects')
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
describe('GET /api/projects/:id', () => {
|
|
it('should return a project by ID', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).toHaveProperty('id', testProjectId);
|
|
expect(res.body).toHaveProperty('ownerId', testUserId);
|
|
});
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}`)
|
|
.expect(401);
|
|
});
|
|
|
|
it('should return 404 for non-existent project', () => {
|
|
const nonExistentId = uuidv4();
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${nonExistentId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(404);
|
|
});
|
|
});
|
|
|
|
describe('PATCH /api/projects/:id', () => {
|
|
it('should update a project', () => {
|
|
const updateData = {
|
|
name: `Updated Project ${uuidv4().substring(0, 8)}`,
|
|
description: 'Updated description'
|
|
};
|
|
|
|
return request(app.getHttpServer())
|
|
.patch(`/api/projects/${testProjectId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.send(updateData)
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).toHaveProperty('id', testProjectId);
|
|
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())
|
|
.patch(`/api/projects/${testProjectId}`)
|
|
.send({ name: 'Unauthorized Update' })
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
describe('POST /api/projects/:id/collaborators/:userId', () => {
|
|
it('should add a collaborator to a project', () => {
|
|
return request(app.getHttpServer())
|
|
.post(`/api/projects/${testProjectId}/collaborators/${collaboratorUserId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(201);
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.post(`/api/projects/${testProjectId}/collaborators/${collaboratorUserId}`)
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
describe('GET /api/projects/:id/collaborators', () => {
|
|
it('should get all collaborators for a project', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}/collaborators`)
|
|
.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(user => user.id === collaboratorUserId)).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}/collaborators`)
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
describe('GET /api/projects/:id/check-access/:userId', () => {
|
|
it('should check if owner has access to a project', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}/check-access/${testUserId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should check if collaborator has access to a project', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}/check-access/${collaboratorUserId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should check if non-collaborator has no access to a project', () => {
|
|
const nonCollaboratorId = uuidv4();
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}/check-access/${nonCollaboratorId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).toBe(false);
|
|
});
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.get(`/api/projects/${testProjectId}/check-access/${testUserId}`)
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
describe('DELETE /api/projects/:id/collaborators/:userId', () => {
|
|
it('should remove a collaborator from a project', () => {
|
|
return request(app.getHttpServer())
|
|
.delete(`/api/projects/${testProjectId}/collaborators/${collaboratorUserId}`)
|
|
.set('Authorization', `Bearer ${accessToken}`)
|
|
.expect(204);
|
|
});
|
|
|
|
it('should return 401 when not authenticated', () => {
|
|
return request(app.getHttpServer())
|
|
.delete(`/api/projects/${testProjectId}/collaborators/${collaboratorUserId}`)
|
|
.expect(401);
|
|
});
|
|
});
|
|
|
|
// Note: We're not testing the DELETE /api/projects/:id endpoint here to avoid complications with test cleanup
|
|
}); |