moar unit test !
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 6m29s

This commit is contained in:
2025-12-07 15:17:09 -08:00
parent b48445b713
commit 393c779ec4
2 changed files with 18 additions and 13 deletions

View File

@@ -84,6 +84,11 @@ describe('FlyerUploader', () => {
expect(screen.getByText('Processing...')).toBeInTheDocument();
expect(screen.getByText('File accepted. Waiting for processing to start...')).toBeInTheDocument();
});
// Advance timers to allow the first poll to execute
await act(async () => {
await vi.runAllTimersAsync();
});
});
it('should poll for status, complete successfully, and redirect', async () => {

View File

@@ -6,7 +6,7 @@
*/
import type { FlyerItem, Store } from "../types";
import { logger } from "./logger";
import { apiFetchWithAuth } from './apiClient';
import { apiFetch } from './apiClient';
/**
* Uploads a flyer file to the backend to be processed asynchronously.
@@ -23,7 +23,7 @@ export const uploadAndProcessFlyer = async (file: File, checksum: string, tokenO
logger.info(`[aiApiClient] Starting background processing for file: ${file.name}`);
return apiFetchWithAuth('/ai/upload-and-process', {
return apiFetch('/ai/upload-and-process', {
method: 'POST',
body: formData,
}, tokenOverride);
@@ -37,7 +37,7 @@ export const uploadAndProcessFlyer = async (file: File, checksum: string, tokenO
* @returns A promise that resolves to the API response with the job's status.
*/
export const getJobStatus = async (jobId: string, tokenOverride?: string): Promise<Response> => {
return apiFetchWithAuth(`/ai/jobs/${jobId}/status`, {}, tokenOverride);
return apiFetch(`/ai/jobs/${jobId}/status`, {}, tokenOverride);
};
export const isImageAFlyer = async (imageFile: File, tokenOverride?: string): Promise<Response> => {
@@ -46,7 +46,7 @@ export const isImageAFlyer = async (imageFile: File, tokenOverride?: string): Pr
// Use apiFetchWithAuth for FormData to let the browser set the correct Content-Type.
// The URL must be relative, as the helper constructs the full path.
return apiFetchWithAuth('/ai/check-flyer', {
return apiFetch('/ai/check-flyer', {
method: 'POST',
body: formData,
}, tokenOverride);
@@ -56,7 +56,7 @@ export const extractAddressFromImage = async (imageFile: File, tokenOverride?: s
const formData = new FormData();
formData.append('image', imageFile);
return apiFetchWithAuth('/ai/extract-address', {
return apiFetch('/ai/extract-address', {
method: 'POST',
body: formData,
}, tokenOverride);
@@ -68,14 +68,14 @@ export const extractLogoFromImage = async (imageFiles: File[], tokenOverride?: s
formData.append('images', file);
});
return apiFetchWithAuth('/ai/extract-logo', {
return apiFetch('/ai/extract-logo', {
method: 'POST',
body: formData,
}, tokenOverride);
};
export const getQuickInsights = async (items: Partial<FlyerItem>[], tokenOverride?: string): Promise<Response> => {
return apiFetchWithAuth('/ai/quick-insights', {
return apiFetch('/ai/quick-insights', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items }),
@@ -83,7 +83,7 @@ export const getQuickInsights = async (items: Partial<FlyerItem>[], tokenOverrid
};
export const getDeepDiveAnalysis = async (items: Partial<FlyerItem>[], tokenOverride?: string): Promise<Response> => {
return apiFetchWithAuth('/ai/deep-dive', {
return apiFetch('/ai/deep-dive', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items }),
@@ -91,7 +91,7 @@ export const getDeepDiveAnalysis = async (items: Partial<FlyerItem>[], tokenOver
};
export const searchWeb = async (items: Partial<FlyerItem>[], tokenOverride?: string): Promise<Response> => {
return apiFetchWithAuth('/ai/search-web', {
return apiFetch('/ai/search-web', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items }),
@@ -111,7 +111,7 @@ export const searchWeb = async (items: Partial<FlyerItem>[], tokenOverride?: str
*/
export const planTripWithMaps = async (items: FlyerItem[], store: Store | undefined, userLocation: GeolocationCoordinates, tokenOverride?: string): Promise<Response> => {
logger.debug("Stub: planTripWithMaps called with location:", { userLocation });
return apiFetchWithAuth('/ai/plan-trip', {
return apiFetch('/ai/plan-trip', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items, store, userLocation }),
@@ -125,7 +125,7 @@ export const planTripWithMaps = async (items: FlyerItem[], store: Store | undefi
*/
export const generateImageFromText = async (prompt: string, tokenOverride?: string): Promise<Response> => {
logger.debug("Stub: generateImageFromText called with prompt:", { prompt });
return apiFetchWithAuth('/ai/generate-image', {
return apiFetch('/ai/generate-image', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt }),
@@ -139,7 +139,7 @@ export const generateImageFromText = async (prompt: string, tokenOverride?: stri
*/
export const generateSpeechFromText = async (text: string, tokenOverride?: string): Promise<Response> => {
logger.debug("Stub: generateSpeechFromText called with text:", { text });
return apiFetchWithAuth('/ai/generate-speech', {
return apiFetch('/ai/generate-speech', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text }),
@@ -194,5 +194,5 @@ export const rescanImageArea = async (
formData.append('cropArea', JSON.stringify(cropArea));
formData.append('extractionType', extractionType);
return apiFetchWithAuth('/ai/rescan-area', { method: 'POST', body: formData }, tokenOverride);
return apiFetch('/ai/rescan-area', { method: 'POST', body: formData }, tokenOverride);
};