updated upload unit tests for s3 image handling
This commit is contained in:
@@ -446,15 +446,137 @@ describe('Upload Routes', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// Note: The GET /upload/signed-url/*key route uses Express 5 wildcard syntax
|
||||
// which is not fully compatible with the test environment when mocking.
|
||||
// The S3OwnershipService functionality is tested separately in s3OwnershipService.test.js
|
||||
// The route integration is verified in integration tests.
|
||||
describe('GET /upload/signed-url/*key (wildcard route)', () => {
|
||||
it('should be defined as a route', () => {
|
||||
// The route exists and is properly configured
|
||||
// Full integration testing of wildcard routes is done in integration tests
|
||||
expect(true).toBe(true);
|
||||
describe('GET /upload/signed-url/:key(*)', () => {
|
||||
const mockSignedUrl = 'https://bucket.s3.amazonaws.com/messages/uuid.jpg?signature=abc';
|
||||
|
||||
beforeEach(() => {
|
||||
mockGetPresignedDownloadUrl.mockResolvedValue(mockSignedUrl);
|
||||
mockCanAccessFile.mockResolvedValue({ authorized: true });
|
||||
});
|
||||
|
||||
it('should return signed URL for authorized private content (messages)', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages/550e8400-e29b-41d4-a716-446655440000.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.url).toBe(mockSignedUrl);
|
||||
expect(response.body.expiresIn).toBe(3600);
|
||||
|
||||
expect(mockCanAccessFile).toHaveBeenCalledWith(
|
||||
'messages/550e8400-e29b-41d4-a716-446655440000.jpg',
|
||||
'user-123'
|
||||
);
|
||||
expect(mockGetPresignedDownloadUrl).toHaveBeenCalledWith(
|
||||
'messages/550e8400-e29b-41d4-a716-446655440000.jpg'
|
||||
);
|
||||
});
|
||||
|
||||
it('should return signed URL for authorized condition-check content', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/condition-checks/550e8400-e29b-41d4-a716-446655440000.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.url).toBe(mockSignedUrl);
|
||||
|
||||
expect(mockCanAccessFile).toHaveBeenCalledWith(
|
||||
'condition-checks/550e8400-e29b-41d4-a716-446655440000.jpg',
|
||||
'user-123'
|
||||
);
|
||||
});
|
||||
|
||||
it('should require authentication', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages/uuid.jpg');
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
expect(mockGetPresignedDownloadUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return 503 when S3 is disabled', async () => {
|
||||
mockIsEnabled.mockReturnValue(false);
|
||||
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(503);
|
||||
});
|
||||
|
||||
it('should return 400 for public folder paths (items)', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/items/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Signed URLs only for private content');
|
||||
expect(mockGetPresignedDownloadUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return 400 for public folder paths (profiles)', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/profiles/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Signed URLs only for private content');
|
||||
});
|
||||
|
||||
it('should return 400 for public folder paths (forum)', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/forum/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.error).toBe('Signed URLs only for private content');
|
||||
});
|
||||
|
||||
it('should return 403 when user is not authorized to access file', async () => {
|
||||
mockCanAccessFile.mockResolvedValue({
|
||||
authorized: false,
|
||||
reason: 'Not a participant in this message'
|
||||
});
|
||||
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(403);
|
||||
expect(response.body.error).toBe('Access denied');
|
||||
expect(mockGetPresignedDownloadUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle URL-encoded keys', async () => {
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages%2Fuuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
// The key should be decoded
|
||||
expect(mockCanAccessFile).toHaveBeenCalledWith(
|
||||
expect.stringContaining('messages'),
|
||||
'user-123'
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle S3 service errors gracefully', async () => {
|
||||
mockGetPresignedDownloadUrl.mockRejectedValue(new Error('S3 error'));
|
||||
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(500);
|
||||
});
|
||||
|
||||
it('should handle ownership service errors gracefully', async () => {
|
||||
mockCanAccessFile.mockRejectedValue(new Error('Database error'));
|
||||
|
||||
const response = await request(app)
|
||||
.get('/upload/signed-url/messages/uuid.jpg')
|
||||
.set('Authorization', 'Bearer valid-token');
|
||||
|
||||
expect(response.status).toBe(500);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user