import assert from 'node:assert/strict'; import test from 'node:test'; import { createInventoryImageService } from '../../src/modules/inventory/services/inventory-image-service.js'; const input = { inventoryItemId: 'inventory-item-id', sellerId: 'seller-id', storageKey: 'inventory/item/front.jpg', originalFilename: 'front.jpg', mimeType: 'image/jpeg', fileSize: 4, width: 1200, height: 900, data: Buffer.from([0xff, 0xd8, 0xff, 0x00]), }; test('stores validated upload bytes before persisting image metadata', async () => { const stored = []; const jobs = []; const service = createInventoryImageService({ imageInspector: { async readMetadata() { return { width: 2, height: 3, mimeType: 'image/jpeg' }; }, async validateDecoding() {} }, imageStorage: { async put(value) { stored.push(value); }, async delete() {}, }, inventoryImageRepository: { async createForSeller(image) { return { id: 'image-1', ...image }; }, }, imageDerivativeJobRepository: { async create(job) { jobs.push(job); }, }, }); const image = await service.upload(input); assert.equal(stored.length, 1); assert.deepEqual(stored[0], { key: input.storageKey, data: input.data }); assert.equal(image.id, 'image-1'); assert.equal(image.width, 2); assert.equal(image.height, 3); assert.equal(image.fileSize, input.data.length); assert.equal(image.processingStatus, 'PENDING'); assert.equal('data' in image, false); assert.deepEqual(jobs, [{ inventoryImageId: 'image-1', sourceKey: input.storageKey, status: 'PENDING', }]); }); test('removes stored bytes when metadata persistence fails', async () => { const deleted = []; const service = createInventoryImageService({ imageInspector: { async readMetadata() { return { width: 2, height: 3, mimeType: 'image/jpeg' }; }, async validateDecoding() {} }, imageStorage: { async put() {}, async delete(key) { deleted.push(key); }, }, inventoryImageRepository: { async createForSeller() { return null; }, }, }); await assert.rejects( () => service.upload(input), (error) => error.code === 'INVENTORY_ITEM_NOT_FOUND', ); assert.deepEqual(deleted, [input.storageKey]); }); test('passes the seller image limit to the atomic repository operation', async () => { let limit; const service = createInventoryImageService({ sellerSettingsRepository: { async findBySellerId() { return { settings: { inventory: { maxImagesPerItem: 2 } } }; } }, inventoryImageRepository: { async createForSellerWithLimit(image, sellerId, maxImages) { assert.equal(sellerId, 'seller-id'); limit = maxImages; return { id: 'image-1', ...image }; }, }, }); const image = await service.create({ ...input, data: undefined }); assert.equal(image.id, 'image-1'); assert.equal(limit, 2); });