import { extractStreamingItems } from './foodDetectionService'; // Mock the provider jest.mock('./providers', () => ({ GeminiProvider: jest.fn().mockImplementation(() => ({ query: jest.fn(), queryStream: jest.fn(), })), })); // Mock monitor to avoid Sentry/RN issues jest.mock('@/remote/monitor', () => ({ startSpan: jest.fn((_opts, fn) => fn({ setAttributes: jest.fn() })), })); describe('foodDetectionService', () => { describe('extractStreamingItems', () => { it('should normalize bounding boxes from 0-1000 range to 0-1', () => { const input = JSON.stringify({ items: [ { foodName: 'Test Food 1000', boundingBox: { x: 100, y: 200, width: 500, height: 400 }, confidence: 0.9, hpPredIngredients: [], hrPredIngredients: [], }, ], }); const result = extractStreamingItems(input); const item = result.completedItems[0]; expect(item).toBeDefined(); expect(item.boundingBox).toEqual({ x: 0.1, y: 0.2, width: 0.5, height: 0.4, }); }); it('should keep already normalized bounding boxes (0-1 range)', () => { const input = JSON.stringify({ items: [ { foodName: 'Test Food Normal', boundingBox: { x: 0.1, y: 0.2, width: 0.5, height: 0.4 }, confidence: 0.9, hpPredIngredients: [], hrPredIngredients: [], }, ], }); const result = extractStreamingItems(input); const item = result.completedItems[0]; expect(item).toBeDefined(); expect(item.boundingBox).toEqual({ x: 0.1, y: 0.2, width: 0.5, height: 0.4, }); }); it('should handle mixed ranges gracefully (though unlikely)', () => { const input = JSON.stringify({ items: [ { foodName: 'Large Coords', boundingBox: { x: 100, y: 200, width: 500, height: 400 }, hpPredIngredients: [], hrPredIngredients: [], confidence: 0.9, }, { foodName: 'Small Coords', boundingBox: { x: 0.1, y: 0.2, width: 0.5, height: 0.4 }, hpPredIngredients: [], hrPredIngredients: [], confidence: 0.9, }, ], }); const result = extractStreamingItems(input); expect(result.completedItems[0].boundingBox).toEqual({ x: 0.1, y: 0.2, width: 0.5, height: 0.4, }); expect(result.completedItems[1].boundingBox).toEqual({ x: 0.1, y: 0.2, width: 0.5, height: 0.4, }); }); // Partial item parsing test it('should extract partial items correctly', () => { // The existing logic requires the value string to be closed with a quote to match const input = `{"items": [{"foodName": "Completed", "confidence": 0.9, "hpPredIngredients": [], "hrPredIngredients": []}, {"foodName": "Partial"`; const result = extractStreamingItems(input); expect(result.completedItems).toHaveLength(1); expect(result.completedItems[0].foodName).toBe('Completed'); expect(result.partialItem).toBeDefined(); expect(result.partialItem?.foodName).toBe('Partial'); }); }); });