import sharp from 'sharp'; import { describe, expect, it } from 'vitest'; import { ImageReplacementInputError, replaceGreenScreen } from '../src/services/image-replacement.js'; describe('replaceGreenScreen', () => { it('warps a replacement into the detected green region and preserves the surrounding source', async () => { const source = await sharp({ create: { width: 200, height: 160, channels: 3, background: '#20252a' }, }).composite([{ input: Buffer.from( '', ) }]).png().toBuffer(); const target = await sharp({ create: { width: 80, height: 120, channels: 3, background: '#ee2233' }, }).png().toBuffer(); const result = await replaceGreenScreen(source, target); const decoded = await sharp(result.bytes).raw().toBuffer({ resolveWithObject: true }); const pixel = (x: number, y: number) => { const offset = (y * decoded.info.width + x) * decoded.info.channels; return [...decoded.data.subarray(offset, offset + 3)]; }; expect(result).toMatchObject({ mimeType: 'image/jpeg', width: 200, height: 160 }); expect(pixel(100, 80)[0]).toBeGreaterThan(150); expect(pixel(100, 80)[1]).toBeLessThan(100); expect(pixel(10, 10)[0]).toBeLessThan(70); }); it('rejects a source without a usable green-screen area', async () => { const source = await sharp({ create: { width: 100, height: 100, channels: 3, background: '#223344' } }).png().toBuffer(); const target = await sharp({ create: { width: 20, height: 20, channels: 3, background: '#ffffff' } }).png().toBuffer(); await expect(replaceGreenScreen(source, target)).rejects.toThrow(ImageReplacementInputError); }); });