Files
flyer-crawler.projectium.com/src/services/flyerFileHandler.server.test.ts
Torben Sorensen fd52a79a72
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 42s
fixin
2025-12-28 22:38:26 -08:00

129 lines
4.1 KiB
TypeScript

// src/services/flyerFileHandler.server.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Job } from 'bullmq';
import type { Dirent } from 'node:fs';
import sharp from 'sharp';
import { FlyerFileHandler, ICommandExecutor, IFileSystem } from './flyerFileHandler.server';
import { PdfConversionError, UnsupportedFileTypeError } from './processingErrors';
import { logger } from './logger.server';
import type { FlyerJobData } from '../types/job-data';
// Mock dependencies
vi.mock('sharp', () => {
const mockSharpInstance = {
png: vi.fn().mockReturnThis(),
toFile: vi.fn().mockResolvedValue({}),
};
return {
__esModule: true,
default: vi.fn(() => mockSharpInstance),
};
});
vi.mock('./logger.server', () => ({
logger: {
info: vi.fn(),
error: vi.fn(),
warn: vi.fn(),
debug: vi.fn(),
child: vi.fn().mockReturnThis(),
},
}));
const createMockJob = (data: Partial<FlyerJobData>): Job<FlyerJobData> => {
return {
id: 'job-1',
data: {
filePath: '/tmp/flyer.jpg',
originalFileName: 'flyer.jpg',
checksum: 'checksum-123',
...data,
},
updateProgress: vi.fn(),
} as unknown as Job<FlyerJobData>;
};
describe('FlyerFileHandler', () => {
let service: FlyerFileHandler;
let mockFs: IFileSystem;
let mockExec: ICommandExecutor;
beforeEach(() => {
vi.clearAllMocks();
mockFs = {
readdir: vi.fn().mockResolvedValue([]),
unlink: vi.fn(),
};
mockExec = vi.fn().mockResolvedValue({ stdout: 'success', stderr: '' });
service = new FlyerFileHandler(mockFs, mockExec);
});
it('should convert a PDF and return image paths', async () => {
const job = createMockJob({ filePath: '/tmp/flyer.pdf' });
vi.mocked(mockFs.readdir).mockResolvedValue([
{ name: 'flyer-1.jpg' },
{ name: 'flyer-2.jpg' },
] as Dirent[]);
const { imagePaths, createdImagePaths } = await service.prepareImageInputs(
'/tmp/flyer.pdf',
job,
logger,
);
expect(mockExec).toHaveBeenCalledWith('pdftocairo -jpeg -r 150 "/tmp/flyer.pdf" "/tmp/flyer"');
expect(imagePaths).toHaveLength(2);
expect(imagePaths[0].path).toContain('flyer-1.jpg');
expect(createdImagePaths).toHaveLength(2);
});
it('should throw PdfConversionError if PDF conversion yields no images', async () => {
const job = createMockJob({ filePath: '/tmp/flyer.pdf' });
vi.mocked(mockFs.readdir).mockResolvedValue([]); // No images found
await expect(service.prepareImageInputs('/tmp/flyer.pdf', job, logger)).rejects.toThrow(
PdfConversionError,
);
});
it('should handle supported image types directly', async () => {
const job = createMockJob({ filePath: '/tmp/flyer.jpg' });
const { imagePaths, createdImagePaths } = await service.prepareImageInputs(
'/tmp/flyer.jpg',
job,
logger,
);
expect(imagePaths).toEqual([{ path: '/tmp/flyer.jpg', mimetype: 'image/jpeg' }]);
expect(createdImagePaths).toEqual([]);
expect(mockExec).not.toHaveBeenCalled();
expect(sharp).not.toHaveBeenCalled();
});
it('should convert convertible image types to PNG', async () => {
const job = createMockJob({ filePath: '/tmp/flyer.gif' });
const mockSharpInstance = sharp('/tmp/flyer.gif');
vi.mocked(mockSharpInstance.toFile).mockResolvedValue({} as any);
const { imagePaths, createdImagePaths } = await service.prepareImageInputs(
'/tmp/flyer.gif',
job,
logger,
);
expect(sharp).toHaveBeenCalledWith('/tmp/flyer.gif');
expect(mockSharpInstance.png).toHaveBeenCalled();
expect(mockSharpInstance.toFile).toHaveBeenCalledWith('/tmp/flyer-converted.png');
expect(imagePaths).toEqual([{ path: '/tmp/flyer-converted.png', mimetype: 'image/png' }]);
expect(createdImagePaths).toEqual(['/tmp/flyer-converted.png']);
});
it('should throw UnsupportedFileTypeError for unsupported types', async () => {
const job = createMockJob({ filePath: '/tmp/document.txt' });
await expect(service.prepareImageInputs('/tmp/document.txt', job, logger)).rejects.toThrow(
UnsupportedFileTypeError,
);
});
});