fixing routes + routes db mock
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 3m48s
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 3m48s
This commit is contained in:
@@ -1,17 +1,37 @@
|
||||
// src/services/aiApiClient.test.ts
|
||||
import { describe, it, expect, vi, beforeEach, type Mocked } from 'vitest';
|
||||
import * as apiClient from './apiClient';
|
||||
import * as aiApiClient from './aiApiClient';
|
||||
import { MasterGroceryItem, FlyerItem } from '../types';
|
||||
|
||||
// Mock the underlying apiClient to isolate our tests to the aiApiClient logic.
|
||||
vi.mock('./apiClient');
|
||||
const mockedApiClient = apiClient as Mocked<typeof apiClient>;
|
||||
// 1. Hoist the mock function so it is created before modules are evaluated
|
||||
// and can be referenced inside the vi.mock factory.
|
||||
const { mockApiFetchWithAuth } = vi.hoisted(() => ({
|
||||
mockApiFetchWithAuth: vi.fn(),
|
||||
}));
|
||||
|
||||
// 2. Mock the dependency './apiClient' to use our hoisted spy.
|
||||
vi.mock('./apiClient', () => ({
|
||||
apiFetchWithAuth: mockApiFetchWithAuth,
|
||||
}));
|
||||
|
||||
// Mock logger as it is used by aiApiClient
|
||||
vi.mock('./logger', () => ({
|
||||
logger: {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('AI API Client', () => {
|
||||
beforeEach(() => {
|
||||
// Clear all mock history before each test
|
||||
// We will load the module under test dynamically for each test
|
||||
let aiApiClient: typeof import('./aiApiClient');
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules(); // Force a fresh module load
|
||||
|
||||
// 3. Import the module under test AFTER mocks are set up.
|
||||
// This ensures aiApiClient binds to the mocked apiFetchWithAuth.
|
||||
aiApiClient = await import('./aiApiClient');
|
||||
});
|
||||
|
||||
describe('isImageAFlyer', () => {
|
||||
@@ -19,8 +39,8 @@ describe('AI API Client', () => {
|
||||
const file = new File([''], 'flyer.jpg', { type: 'image/jpeg' });
|
||||
await aiApiClient.isImageAFlyer(file, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options, token] = mockedApiClient.apiFetchWithAuth.mock.calls[0];
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options, token] = mockApiFetchWithAuth.mock.calls[0];
|
||||
|
||||
expect(url).toBe('/ai/check-flyer');
|
||||
expect(options.method).toBe('POST');
|
||||
@@ -35,8 +55,8 @@ describe('AI API Client', () => {
|
||||
const file = new File([''], 'flyer.jpg', { type: 'image/jpeg' });
|
||||
await aiApiClient.extractAddressFromImage(file, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options, token] = mockedApiClient.apiFetchWithAuth.mock.calls[0];
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options, token] = mockApiFetchWithAuth.mock.calls[0];
|
||||
|
||||
expect(url).toBe('/ai/extract-address');
|
||||
expect(options.method).toBe('POST');
|
||||
@@ -49,12 +69,12 @@ describe('AI API Client', () => {
|
||||
describe('extractCoreDataFromImage', () => {
|
||||
it('should construct FormData and call apiFetchWithAuth correctly', async () => {
|
||||
const files = [new File([''], 'flyer1.jpg', { type: 'image/jpeg' })];
|
||||
const masterItems: MasterGroceryItem[] = [{ master_grocery_item_id: 1, name: 'Milk', created_at: '' }];
|
||||
const masterItems: any[] = [{ master_grocery_item_id: 1, name: 'Milk', created_at: '' }];
|
||||
|
||||
await aiApiClient.extractCoreDataFromImage(files, masterItems);
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options] = mockedApiClient.apiFetchWithAuth.mock.calls[0];
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options] = mockApiFetchWithAuth.mock.calls[0];
|
||||
|
||||
expect(url).toBe('/ai/process-flyer');
|
||||
expect(options.method).toBe('POST');
|
||||
@@ -72,8 +92,8 @@ describe('AI API Client', () => {
|
||||
const files = [new File([''], 'logo.jpg', { type: 'image/jpeg' })];
|
||||
await aiApiClient.extractLogoFromImage(files, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options, token] = mockedApiClient.apiFetchWithAuth.mock.calls[0];
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
const [url, options, token] = mockApiFetchWithAuth.mock.calls[0];
|
||||
|
||||
expect(url).toBe('/ai/extract-logo');
|
||||
expect(options.method).toBe('POST');
|
||||
@@ -85,11 +105,11 @@ describe('AI API Client', () => {
|
||||
|
||||
describe('getDeepDiveAnalysis', () => {
|
||||
it('should call apiFetchWithAuth with the items in the body', async () => {
|
||||
const items: FlyerItem[] = [];
|
||||
const items: any[] = [];
|
||||
await aiApiClient.getDeepDiveAnalysis(items, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledWith(
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledWith(
|
||||
'/ai/deep-dive',
|
||||
{
|
||||
method: 'POST',
|
||||
@@ -103,11 +123,11 @@ describe('AI API Client', () => {
|
||||
|
||||
describe('searchWeb', () => {
|
||||
it('should call apiFetchWithAuth with the items in the body', async () => {
|
||||
const items: FlyerItem[] = [];
|
||||
const items: any[] = [];
|
||||
await aiApiClient.searchWeb(items, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledWith(
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledWith(
|
||||
'/ai/search-web',
|
||||
{
|
||||
method: 'POST',
|
||||
@@ -124,8 +144,8 @@ describe('AI API Client', () => {
|
||||
const prompt = 'A delicious meal';
|
||||
await aiApiClient.generateImageFromText(prompt, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledWith(
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledWith(
|
||||
'/ai/generate-image',
|
||||
{
|
||||
method: 'POST',
|
||||
@@ -142,8 +162,8 @@ describe('AI API Client', () => {
|
||||
const text = 'Hello world';
|
||||
await aiApiClient.generateSpeechFromText(text, 'test-token');
|
||||
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockedApiClient.apiFetchWithAuth).toHaveBeenCalledWith(
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockApiFetchWithAuth).toHaveBeenCalledWith(
|
||||
'/ai/generate-speech',
|
||||
{
|
||||
method: 'POST',
|
||||
@@ -157,7 +177,8 @@ describe('AI API Client', () => {
|
||||
|
||||
describe('startVoiceSession', () => {
|
||||
it('should throw an error as it is not implemented', () => {
|
||||
expect(() => aiApiClient.startVoiceSession({ onmessage: vi.fn() })).toThrow(
|
||||
// Ensure the real implementation is called, which should throw
|
||||
expect(() => aiApiClient.startVoiceSession({ onmessage: vi.fn() } as any)).toThrow(
|
||||
'Voice session feature is not fully implemented and requires a backend WebSocket proxy.'
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user