unit tests fixin
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 36s

This commit is contained in:
2025-11-22 00:45:44 -08:00
parent fd08efbd08
commit 680c2636c3
3 changed files with 37 additions and 40 deletions

View File

@@ -4,11 +4,10 @@
* The `.server.ts` naming convention helps enforce this separation.
*/
import { GoogleGenAI, Type } from '@google/genai';
import { GoogleGenAI } from '@google/genai';
import fs from 'fs/promises';
import { logger } from './logger';
import { parsePriceToCents } from '../utils/priceParser';
import type { FlyerItem, MasterGroceryItem, RawFlyerItem } from '../types';
import type { FlyerItem, MasterGroceryItem } from '../types';
// Use the secure, server-side API key.
const apiKey = process.env.GEMINI_API_KEY;
@@ -87,8 +86,8 @@ export const extractItemsFromReceiptImage = async (
* @returns A promise that resolves to the extracted core data.
*/
export const extractCoreDataFromFlyerImage = async (
imagePaths: { path: string; mimetype: string }[],
masterItems: MasterGroceryItem[]
_imagePaths: { path: string; mimetype: string }[],
_masterItems: MasterGroceryItem[]
): Promise<{
store_name: string;
valid_from: string | null;

View File

@@ -1,40 +1,40 @@
// This file is intended for client-side Gemini helper functions.
// Currently, most AI logic is handled on the server via `aiService.server.ts`
// and exposed through the API, so this file is largely a placeholder for future features.
import type { FlyerItem, MasterGroceryItem, Store } from "../types";
import { logger } from "./logger";
import { apiFetch } from './apiClient';
// import { logger } from "./logger";
/**
* Parses a JSON string from a Gemini response, robustly handling markdown fences.
* @param responseText The raw text from the AI response.
* @returns The parsed JSON object.
*/
function parseGeminiJson<T>(responseText: string): T {
let cleanedText = responseText.trim();
// /**
// * Parses a JSON string from a Gemini response, robustly handling markdown fences.
// * @param responseText The raw text from the AI response.
// * @returns The parsed JSON object.
// */
// function parseGeminiJson<T>(responseText: string): T {
// let cleanedText = responseText.trim();
// Remove markdown fences ` ```json ... ``` `
const jsonRegex = /```json\s*([\s\S]*?)\s*```/;
const match = cleanedText.match(jsonRegex);
if (match && match[1]) {
cleanedText = match[1];
}
// // Remove markdown fences ` ```json ... ``` `
// const jsonRegex = /```json\s*([\s\S]*?)\s*```/;
// const match = cleanedText.match(jsonRegex);
// if (match && match[1]) {
// cleanedText = match[1];
// }
try {
return JSON.parse(cleanedText) as T;
} catch (e) {
// Ensure we handle different types of thrown errors gracefully.
const errorMessage = e instanceof Error ? e.message : String(e);
logger.error("Failed to parse JSON response from AI.", {
originalResponse: responseText,
cleanedJSON: cleanedText,
error: errorMessage,
});
// try {
// return JSON.parse(cleanedText) as T;
// } catch (e) {
// // Ensure we handle different types of thrown errors gracefully.
// const errorMessage = e instanceof Error ? e.message : String(e);
// logger.error("Failed to parse JSON response from AI.", {
// originalResponse: responseText,
// cleanedJSON: cleanedText,
// error: errorMessage,
// });
// Re-throw with more context.
throw new Error(`Failed to parse JSON response from AI. Error: ${errorMessage}. The AI may have returned malformed data.`);
}
}
// // Re-throw with more context.
// throw new Error(`Failed to parse JSON response from AI. Error: ${errorMessage}. The AI may have returned malformed data.`);
// }
// }
// ============================================================================
// STUBS FOR FUTURE AI FEATURES

View File

@@ -1,9 +1,7 @@
import { exec } from 'child_process';
import { promisify } from 'util';
import { setup as globalSetup } from './global-setup';
import { pingBackend } from '../../services/apiClient'; // Import the ping function
const execAsync = promisify(exec);
import { logger } from '../../services/logger';
/**
* This setup function is specifically for integration tests that need a running backend.
@@ -29,7 +27,7 @@ export async function setup() {
return; // Server is ready, exit setup.
}
} catch (e) {
// Ignore connection errors while waiting
logger.debug('Ping failed while waiting for server, this is expected.', { error: e });
}
console.log(`Waiting for backend server... (attempt ${i + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, retryDelay));