campverse-backend / __tests__ /unit /firebaseStorageService.test.js
CampVerse CI
Deploy backend from GitHub Actions
c904036
Raw History Blame Contribute Delete
9.67 kB
/* eslint-disable no-unused-vars, no-undef */
/**
* Firebase Storage Service Unit Tests
* Comprehensive testing for all storage operations
*/
// Mock Firebase file
const mockFile = {
save: jest.fn(),
delete: jest.fn(),
getMetadata: jest.fn(),
getSignedUrl: jest.fn(),
name: 'test-file.jpg'
};
// Mock Firebase admin
jest.mock('../../firebase', () => ({
name: 'test-bucket.appspot.com',
file: jest.fn(() => mockFile),
getFiles: jest.fn(),
getMetadata: jest.fn()
}));
// Mock logger
jest.mock('../../Middleware/errorHandler', () => ({
logger: {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn()
}
}));
// eslint-disable-next-line no-unused-vars
const {
FirebaseStorageService,
} = require('../../Services/firebaseStorageService');
const mockBucket = require('../../firebase');
describe('Firebase Storage Service Unit Tests', () => {
let service;
let mockFileBuffer;
beforeEach(() => {
jest.clearAllMocks();
service = new FirebaseStorageService();
mockFileBuffer = Buffer.from('test file content');
// Setup default mock implementations
mockBucket.file.mockReturnValue(mockFile);
mockFile.save.mockResolvedValue(undefined);
mockFile.delete.mockResolvedValue(undefined);
mockFile.getMetadata.mockResolvedValue([{
name: 'test-file.jpg',
size: '1024',
contentType: 'image/jpeg',
timeCreated: '2024-01-01T00:00:00Z',
updated: '2024-01-01T00:00:00Z',
metadata: {}
}]);
mockFile.getSignedUrl.mockResolvedValue(['https://signed-url.com']);
mockBucket.getFiles.mockResolvedValue([[]]);
mockBucket.getMetadata.mockResolvedValue([{ name: 'test-bucket' }]);
});
describe('FirebaseStorageService Class', () => {
it('should initialize correctly', () => {
expect(service.bucket).toBe(mockBucket);
expect(service.baseFolder).toBe('CampVerse');
expect(service.initialized).toBe(true);
});
it('should generate correct file paths', () => {
const filePath = service.generateFilePath('events', 'logos', 'test.jpg');
expect(filePath).toMatch(/^CampVerse\/events\/logos\/\d+_[a-f0-9-]+_test\.jpg$/);
});
it('should generate correct file paths with userId', () => {
const filePath = service.generateFilePath('users', 'profiles', 'avatar.jpg', 'user123');
expect(filePath).toMatch(/^CampVerse\/users\/user123\/profiles\/\d+_[a-f0-9-]+_avatar\.jpg$/);
});
});
describe('uploadEventImage', () => {
it('should upload event logo successfully', async () => {
const result = await service.uploadEventImage(
mockFileBuffer,
'logo.jpg',
'logo',
'image/jpeg'
);
expect(mockBucket.file).toHaveBeenCalled();
expect(mockFile.save).toHaveBeenCalledWith(
mockFileBuffer,
expect.objectContaining({
contentType: 'image/jpeg',
metadata: expect.objectContaining({
originalName: 'logo.jpg',
category: 'event',
type: 'logo',
fileType: 'image'
})
})
);
expect(result).toMatch(/^https:\/\/firebasestorage\.googleapis\.com/);
});
it('should reject invalid file types', async () => {
await expect(
service.uploadEventImage(mockFileBuffer, 'document.pdf', 'logo', 'application/pdf')
).rejects.toThrow('Invalid file type: application/pdf');
});
it('should handle upload errors', async () => {
mockFile.save.mockRejectedValue(new Error('Upload failed'));
await expect(
service.uploadEventImage(mockFileBuffer, 'logo.jpg', 'logo', 'image/jpeg')
).rejects.toThrow('Upload failed');
});
});
describe('uploadProfilePhoto', () => {
it('should upload profile photo successfully', async () => {
const result = await service.uploadProfilePhoto(
mockFileBuffer,
'avatar.jpg',
'user123',
'image/jpeg'
);
expect(mockFile.save).toHaveBeenCalledWith(
mockFileBuffer,
expect.objectContaining({
contentType: 'image/jpeg',
metadata: expect.objectContaining({
category: 'profile',
userId: 'user123',
fileType: 'image'
})
})
);
expect(result).toMatch(/^https:\/\/firebasestorage\.googleapis\.com/);
});
it('should reject invalid file types for profile photos', async () => {
await expect(
service.uploadProfilePhoto(mockFileBuffer, 'document.txt', 'user123', 'text/plain')
).rejects.toThrow('Invalid file type: text/plain');
});
});
describe('uploadUserDocument', () => {
it('should upload ID card successfully', async () => {
const result = await service.uploadUserDocument(
mockFileBuffer,
'id-card.jpg',
'id-cards',
'user123',
'image/jpeg'
);
expect(mockFile.save).toHaveBeenCalledWith(
mockFileBuffer,
expect.objectContaining({
metadata: expect.objectContaining({
category: 'user_document',
documentType: 'id-cards',
userId: 'user123',
fileType: 'image'
})
})
);
expect(result).toMatch(/^https:\/\/firebasestorage\.googleapis\.com/);
});
it('should upload PDF document successfully', async () => {
const result = await service.uploadUserDocument(
mockFileBuffer,
'permission.pdf',
'permissions',
'user123',
'application/pdf'
);
expect(mockFile.save).toHaveBeenCalledWith(
mockFileBuffer,
expect.objectContaining({
metadata: expect.objectContaining({
documentType: 'permissions',
fileType: 'document'
})
})
);
expect(result).toMatch(/^https:\/\/firebasestorage\.googleapis\.com/);
});
it('should reject invalid document types', async () => {
await expect(
service.uploadUserDocument(mockFileBuffer, 'video.mp4', 'videos', 'user123', 'video/mp4')
).rejects.toThrow('Invalid file type: video/mp4');
});
});
describe('deleteFile', () => {
it('should delete file with Firebase Storage URL', async () => {
const fileUrl = 'https://firebasestorage.googleapis.com/v0/b/bucket/o/CampVerse%2Fevents%2Flogos%2Ftest.jpg?alt=media&token=123';
const result = await service.deleteFile(fileUrl);
expect(mockFile.delete).toHaveBeenCalled();
expect(result).toBe(true);
});
it('should handle file not found', async () => {
mockFile.delete.mockRejectedValue({ code: 404 });
const result = await service.deleteFile('https://firebasestorage.googleapis.com/v0/b/bucket/o/nonexistent.jpg');
expect(result).toBe(false);
});
it('should handle invalid URLs', async () => {
const result = await service.deleteFile('invalid-url');
expect(mockFile.delete).not.toHaveBeenCalled();
expect(result).toBe(false);
});
});
describe('listFiles', () => {
it('should list files in folder successfully', async () => {
const mockFiles = [
{
name: 'file1.jpg',
getMetadata: jest.fn().mockResolvedValue([{
size: '1024',
contentType: 'image/jpeg',
timeCreated: '2024-01-01T00:00:00Z',
updated: '2024-01-01T00:00:00Z'
}]),
getSignedUrl: jest.fn().mockResolvedValue(['https://signed-url-1.com'])
}
];
mockBucket.getFiles.mockResolvedValue([mockFiles]);
const result = await service.listFiles('events/logos');
expect(mockBucket.getFiles).toHaveBeenCalledWith({
prefix: 'CampVerse/events/logos'
});
expect(result).toHaveLength(1);
expect(result[0]).toEqual({
name: 'file1.jpg',
path: 'file1.jpg',
url: 'https://signed-url-1.com',
size: '1024',
contentType: 'image/jpeg',
timeCreated: '2024-01-01T00:00:00Z',
updated: '2024-01-01T00:00:00Z'
});
});
});
describe('healthCheck', () => {
it('should return healthy status', async () => {
const result = await service.healthCheck();
expect(result).toEqual({
status: 'healthy',
message: 'Firebase Storage service is operational',
bucket: 'test-bucket.appspot.com',
initialized: true
});
});
it('should return error status when bucket is inaccessible', async () => {
mockBucket.getMetadata.mockRejectedValue(new Error('Access denied'));
const result = await service.healthCheck();
expect(result).toEqual({
status: 'error',
message: 'Access denied',
bucket: 'test-bucket.appspot.com',
initialized: true
});
});
});
describe('Backward Compatibility Functions', () => {
it('should call uploadEventImage through compatibility function', async () => {
const result = await uploadEventImage(mockFileBuffer, 'logo.jpg', 'logo', 'image/jpeg');
expect(result).toMatch(/^https:\/\/firebasestorage\.googleapis\.com/);
});
it('should call uploadProfilePhoto through compatibility function', async () => {
const result = await uploadProfilePhoto(mockFileBuffer, 'avatar.jpg', 'user123', 'image/jpeg');
expect(result).toMatch(/^https:\/\/firebasestorage\.googleapis\.com/);
});
it('should call deleteFile through deleteEventImage compatibility function', async () => {
const result = await deleteEventImage('https://firebasestorage.googleapis.com/test.jpg');
expect(result).toBe(true);
});
});
});