diff --git a/src/routes/ai.test.ts b/src/routes/ai.test.ts index 996110da..f9901018 100644 --- a/src/routes/ai.test.ts +++ b/src/routes/ai.test.ts @@ -156,6 +156,66 @@ describe('AI Routes (/api/ai)', () => { expect(response.status).toBe(400); expect(response.body.message).toBe('Flyer image file is required.'); }); + + it('should return 400 if extractedData is missing from payload', async () => { + const badPayload = { checksum: 'c2', originalFileName: 'noflyer.jpg' }; // no extractedData + + const response = await supertest(app) + .post('/api/ai/flyers/process') + .field('data', JSON.stringify(badPayload)) + .attach('flyerImage', imagePath); + + expect(response.status).toBe(400); + expect(response.body.message).toBe('Invalid request: extractedData is required.'); + expect(mockedDb.createFlyerAndItems).not.toHaveBeenCalled(); + }); + + it('should accept payload when extractedData.items is missing and save with empty items', async () => { + // Arrange: extractedData present but items missing + const partialPayload = { + checksum: 'test-checksum-2', + originalFileName: 'flyer2.jpg', + extractedData: { store_name: 'Partial Store' } // no items key + }; + + mockedDb.findFlyerByChecksum.mockResolvedValue(undefined); + mockedDb.createFlyerAndItems.mockResolvedValue({ flyer_id: 2, created_at: new Date().toISOString(), file_name: partialPayload.originalFileName, image_url: '/flyer-images/flyer2.jpg' } as any); + + const response = await supertest(app) + .post('/api/ai/flyers/process') + .field('data', JSON.stringify(partialPayload)) + .attach('flyerImage', imagePath); + + expect(response.status).toBe(201); + expect(mockedDb.createFlyerAndItems).toHaveBeenCalledTimes(1); + // verify the items array passed to DB was an empty array + const callArgs = mockedDb.createFlyerAndItems.mock.calls[0]?.[1]; + expect(callArgs).toBeDefined(); + expect(Array.isArray(callArgs)).toBe(true); + expect(callArgs.length).toBe(0); + }); + + it('should fallback to a safe store name when store_name is missing', async () => { + const payloadNoStore = { + checksum: 'test-checksum-3', + originalFileName: 'flyer3.jpg', + extractedData: { items: [] } // store_name missing + }; + + mockedDb.findFlyerByChecksum.mockResolvedValue(undefined); + mockedDb.createFlyerAndItems.mockResolvedValue({ flyer_id: 3, created_at: new Date().toISOString(), file_name: payloadNoStore.originalFileName, image_url: '/flyer-images/flyer3.jpg' } as any); + + const response = await supertest(app) + .post('/api/ai/flyers/process') + .field('data', JSON.stringify(payloadNoStore)) + .attach('flyerImage', imagePath); + + expect(response.status).toBe(201); + expect(mockedDb.createFlyerAndItems).toHaveBeenCalledTimes(1); + // verify the flyerData.store_name passed to DB was the fallback string + const flyerDataArg = mockedDb.createFlyerAndItems.mock.calls[0][0]; + expect(flyerDataArg.store_name).toContain('Unknown Store'); + }); }); describe('when user is authenticated', () => {