test fixes
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 30m38s
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 30m38s
This commit is contained in:
@@ -91,11 +91,55 @@ export class AIService {
|
||||
private fs: IFileSystem;
|
||||
private rateLimiter: <T>(fn: () => Promise<T>) => Promise<T>;
|
||||
private logger: Logger;
|
||||
// The fallback list is ordered by preference (speed/cost vs. power).
|
||||
// We try the fastest models first, then the more powerful 'pro' model as a high-quality fallback,
|
||||
// and finally the 'lite' model as a last resort.
|
||||
private readonly models = [ 'gemini-3-flash-preview','gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.5-flash-lite','gemini-2.0-flash-001','gemini-2.0-flash','gemini-2.0-flash-exp','gemini-2.0-flash-lite-001','gemini-2.0-flash-lite', 'gemma-3-27b-it', 'gemma-3-12b-it'];
|
||||
private readonly models_lite = ["gemma-3-4b-it", "gemma-3-2b-it", "gemma-3-1b-it"];
|
||||
|
||||
// OPTIMIZED: Flyer Image Processing (Vision + Long Output)
|
||||
// PRIORITIES:
|
||||
// 1. Output Limit: Must be 65k+ (Gemini 2.5/3.0) to avoid cutting off data.
|
||||
// 2. Intelligence: 'Pro' models handle messy layouts better.
|
||||
// 3. Quota Management: 'Preview' and 'Exp' models are added as fallbacks to tap into separate rate limits.
|
||||
private readonly models = [
|
||||
// --- TIER A: The Happy Path (Fast & Stable) ---
|
||||
'gemini-2.5-flash', // Primary workhorse. 65k output.
|
||||
'gemini-2.5-flash-lite', // Cost-saver. 65k output.
|
||||
|
||||
// --- TIER B: The Heavy Lifters (Complex Layouts) ---
|
||||
'gemini-2.5-pro', // High IQ for messy flyers. 65k output.
|
||||
|
||||
// --- TIER C: Separate Quota Buckets (Previews) ---
|
||||
'gemini-3-flash-preview', // Newer/Faster. Separate 'Preview' quota. 65k output.
|
||||
'gemini-3-pro-preview', // High IQ. Separate 'Preview' quota. 65k output.
|
||||
|
||||
// --- TIER D: Experimental Buckets (High Capacity) ---
|
||||
'gemini-exp-1206', // Excellent reasoning. Separate 'Experimental' quota. 65k output.
|
||||
|
||||
// --- TIER E: Last Resorts (Lower Capacity/Local) ---
|
||||
'gemma-3-27b-it', // Open model fallback.
|
||||
'gemini-2.0-flash-exp' // Exp fallback. WARNING: 8k output limit. Good for small flyers only.
|
||||
];
|
||||
|
||||
// OPTIMIZED: Simple Text Tasks (Recipes, Shopping Lists, Summaries)
|
||||
// PRIORITIES:
|
||||
// 1. Cost/Speed: These tasks are simple.
|
||||
// 2. Output Limit: The 8k limit of Gemini 2.0 is perfectly fine here.
|
||||
private readonly models_lite = [
|
||||
// --- Best Value (Smart + Cheap) ---
|
||||
"gemini-2.5-flash-lite", // Current generation efficiency king.
|
||||
|
||||
// --- The "Recycled" Gemini 2.0 Models (Perfect for Text) ---
|
||||
"gemini-2.0-flash-lite-001", // Extremely cheap, very capable for text.
|
||||
"gemini-2.0-flash-001", // Smarter than Lite, good for complex recipes.
|
||||
|
||||
// --- Open Models (Good for simple categorization) ---
|
||||
"gemma-3-12b-it", // Solid reasoning for an open model.
|
||||
"gemma-3-4b-it", // Very fast.
|
||||
|
||||
// --- Quota Fallbacks (Experimental/Preview) ---
|
||||
"gemini-2.0-flash-exp", // Use this separate quota bucket if others are exhausted.
|
||||
|
||||
// --- Edge/Nano Models (Simple string manipulation only) ---
|
||||
"gemma-3n-e4b-it", // Corrected name from JSON
|
||||
"gemma-3n-e2b-it" // Corrected name from JSON
|
||||
];
|
||||
|
||||
constructor(logger: Logger, aiClient?: IAiClient, fs?: IFileSystem) {
|
||||
this.logger = logger;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// src/tests/e2e/auth.e2e.test.ts
|
||||
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
|
||||
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
|
||||
import * as apiClient from '../../services/apiClient';
|
||||
import { cleanupDb } from '../utils/cleanup';
|
||||
import { createAndLoginUser, TEST_PASSWORD } from '../utils/testHelpers';
|
||||
@@ -13,15 +13,19 @@ describe('Authentication E2E Flow', () => {
|
||||
let testUser: UserProfile;
|
||||
const createdUserIds: string[] = [];
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll(async () => {
|
||||
// Create a user that can be used for login-related tests in this suite.
|
||||
const { user } = await createAndLoginUser({
|
||||
email: `e2e-login-user-${Date.now()}@example.com`,
|
||||
fullName: 'E2E Login User',
|
||||
// E2E tests use apiClient which doesn't need the `request` object.
|
||||
});
|
||||
testUser = user;
|
||||
createdUserIds.push(user.user.user_id);
|
||||
try {
|
||||
const { user } = await createAndLoginUser({
|
||||
email: `e2e-login-user-${Date.now()}@example.com`,
|
||||
fullName: 'E2E Login User',
|
||||
});
|
||||
testUser = user;
|
||||
createdUserIds.push(user.user.user_id);
|
||||
} catch (error) {
|
||||
console.error('[FATAL] Setup failed. DB might be down.', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -70,7 +74,7 @@ describe('Authentication E2E Flow', () => {
|
||||
const firstResponse = await apiClient.registerUser(email, TEST_PASSWORD, 'Duplicate User');
|
||||
const firstData = await firstResponse.json();
|
||||
expect(firstResponse.status).toBe(201);
|
||||
createdUserIds.push(firstData.userprofile.user.user_id); // Add for cleanup
|
||||
createdUserIds.push(firstData.userprofile.user.user_id);
|
||||
|
||||
// Act 2: Attempt to register the same user again
|
||||
const secondResponse = await apiClient.registerUser(email, TEST_PASSWORD, 'Duplicate User');
|
||||
@@ -186,17 +190,23 @@ describe('Authentication E2E Flow', () => {
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
expect(loginSuccess, 'User should be able to log in after registration before password reset is attempted.').toBe(true);
|
||||
expect(loginSuccess, 'User should be able to log in after registration. DB might be lagging.').toBe(true);
|
||||
|
||||
// Act 1: Request a password reset.
|
||||
// The test environment returns the token directly in the response for E2E testing.
|
||||
// Act 1: Request a password reset
|
||||
const forgotResponse = await apiClient.requestPasswordReset(email);
|
||||
const forgotData = await forgotResponse.json();
|
||||
const resetToken = forgotData.token;
|
||||
|
||||
// --- DEBUG SECTION FOR FAILURE ---
|
||||
if (!resetToken) {
|
||||
console.error(' [DEBUG FAILURE] Token missing in response:', JSON.stringify(forgotData, null, 2));
|
||||
console.error(' [DEBUG FAILURE] This usually means the backend hit a DB error or is not in NODE_ENV=test mode.');
|
||||
}
|
||||
// ---------------------------------
|
||||
|
||||
// Assert 1: Check that we received a token.
|
||||
expect(forgotResponse.status).toBe(200);
|
||||
expect(resetToken).toBeDefined();
|
||||
expect(resetToken, 'Backend returned 200 but no token. Check backend logs for "Connection terminated" errors.').toBeDefined();
|
||||
expect(resetToken).toBeTypeOf('string');
|
||||
|
||||
// Act 2: Use the token to set a new password.
|
||||
@@ -208,7 +218,7 @@ describe('Authentication E2E Flow', () => {
|
||||
expect(resetResponse.status).toBe(200);
|
||||
expect(resetData.message).toBe('Password has been reset successfully.');
|
||||
|
||||
// Act 3 & Assert 3 (Verification): Log in with the NEW password to confirm the change.
|
||||
// Act 3: Log in with the NEW password
|
||||
const loginResponse = await apiClient.loginUser(email, newPassword, false);
|
||||
const loginData = await loginResponse.json();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user