updated upload unit tests for s3 image handling

This commit is contained in:
jackiettran
2025-12-19 18:58:30 -05:00
parent 4b4584bc0f
commit 4e0a4ef019
2 changed files with 435 additions and 53 deletions

View File

@@ -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);
});
});
});