diff --git a/src/routes/admin.test.ts b/src/routes/admin.test.ts
index a520b265..c748508d 100644
--- a/src/routes/admin.test.ts
+++ b/src/routes/admin.test.ts
@@ -230,7 +230,7 @@ describe('Admin Routes (/api/admin)', () => {
it('should approve a correction and return a success message', async () => {
// Arrange
const correctionId = 123;
- mockedDb.approveCorrection.mockResolvedValue(); // Mock the DB call to succeed
+ mockedDb.approveCorrection.mockResolvedValue(undefined); // Mock the DB call to succeed
// Act
const response = await supertest(app).post(`/api/admin/corrections/${correctionId}/approve`);
@@ -269,7 +269,7 @@ describe('Admin Routes (/api/admin)', () => {
it('should reject a correction and return a success message', async () => {
// Arrange
const correctionId = 789;
- mockedDb.rejectCorrection.mockResolvedValue(); // Mock the DB call to succeed
+ mockedDb.rejectCorrection.mockResolvedValue(undefined); // Mock the DB call to succeed
// Act
const response = await supertest(app).post(`/api/admin/corrections/${correctionId}/reject`);
@@ -352,7 +352,7 @@ describe('Admin Routes (/api/admin)', () => {
it('should upload a logo and update the brand', async () => {
// Arrange
const brandId = 55;
- mockedDb.updateBrandLogo.mockResolvedValue(); // Mock the DB call
+ mockedDb.updateBrandLogo.mockResolvedValue(undefined); // Mock the DB call
// Create a dummy file for supertest to attach.
// supertest needs a real file path to stream from.
diff --git a/src/routes/auth.test.ts b/src/routes/auth.test.ts
index 39cd9b09..55e57e3a 100644
--- a/src/routes/auth.test.ts
+++ b/src/routes/auth.test.ts
@@ -214,7 +214,7 @@ describe('Auth Routes (/api/auth)', () => {
it('should send a reset link if the user exists', async () => {
// Arrange
const mockUser = { user_id: 'user-123', email: 'test@test.com' };
- mockedDb.findUserByEmail.mockResolvedValue(mockUser as any);
+ mockedDb.findUserByEmail.mockResolvedValue(mockUser as Awaited
>);
mockedDb.createPasswordResetToken.mockResolvedValue();
// Act
@@ -251,8 +251,8 @@ describe('Auth Routes (/api/auth)', () => {
it('should reset the password with a valid token and strong password', async () => {
// Arrange
const tokenRecord = { user_id: 'user-123', token_hash: 'hashed-token' };
- mockedDb.getValidResetTokens.mockResolvedValue([tokenRecord] as any);
- (bcrypt.compare as Mocked).mockResolvedValue(true); // Mock that the token matches the hash
+ mockedDb.getValidResetTokens.mockResolvedValue([tokenRecord] as Awaited>);
+ vi.mocked(bcrypt.compare).mockResolvedValue(true as never); // Mock that the token matches the hash
mockedDb.updateUserPassword.mockResolvedValue();
mockedDb.deleteResetToken.mockResolvedValue();
@@ -270,8 +270,8 @@ describe('Auth Routes (/api/auth)', () => {
it('should reject with an invalid or expired token', async () => {
// Arrange: Mock that the token does not match any valid hashes.
- mockedDb.getValidResetTokens.mockResolvedValue([{ user_id: 'user-123', token_hash: 'hashed-token' }] as any);
- (bcrypt.compare as Mocked).mockResolvedValue(false);
+ mockedDb.getValidResetTokens.mockResolvedValue([{ user_id: 'user-123', token_hash: 'hashed-token' } as Awaited>[0]]);
+ vi.mocked(bcrypt.compare).mockResolvedValue(false as never);
// Act
const response = await supertest(app)
@@ -288,7 +288,7 @@ describe('Auth Routes (/api/auth)', () => {
it('should issue a new access token with a valid refresh token cookie', async () => {
// Arrange
const mockUser = { user_id: 'user-123', email: 'test@test.com' };
- mockedDb.findUserByRefreshToken.mockResolvedValue(mockUser as any);
+ mockedDb.findUserByRefreshToken.mockResolvedValue(mockUser);
// Act
const response = await supertest(app)
diff --git a/src/routes/public.routes.test.ts b/src/routes/public.routes.test.ts
index 3a8f8037..e4c1e4c0 100644
--- a/src/routes/public.routes.test.ts
+++ b/src/routes/public.routes.test.ts
@@ -64,14 +64,14 @@ describe('Public Routes (/api)', () => {
describe('GET /health/storage', () => {
it('should return 200 OK if storage is writable', async () => {
- (mockedFs.access as Mock).mockResolvedValue(undefined);
+ vi.mocked(mockedFs.access).mockResolvedValue(undefined);
const response = await supertest(app).get('/api/health/storage');
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
});
it('should return 500 if storage is not accessible', async () => {
- (mockedFs.access as Mock).mockRejectedValue(new Error('Permission denied'));
+ vi.mocked(mockedFs.access).mockRejectedValue(new Error('Permission denied'));
const response = await supertest(app).get('/api/health/storage');
expect(response.status).toBe(500);
expect(response.body.success).toBe(false);
diff --git a/src/routes/system.test.ts b/src/routes/system.test.ts
index 4cb83587..2a2daf6d 100644
--- a/src/routes/system.test.ts
+++ b/src/routes/system.test.ts
@@ -42,7 +42,7 @@ describe('System Routes (/api/system)', () => {
└───────────┴───────────┘
`;
// The `exec` callback receives (error, stdout, stderr). For success, error is null.
- (mockedExec as Mock).mockImplementation((
+ vi.mocked(mockedExec).mockImplementation((
command: string,
callback: (error: ExecException | null, stdout: string, stderr: string) => void
) => {
@@ -63,7 +63,7 @@ describe('System Routes (/api/system)', () => {
const pm2StoppedOutput = `
│ status │ stopped │
`;
- (mockedExec as Mock).mockImplementation((
+ vi.mocked(mockedExec).mockImplementation((
command: string,
callback: (error: ExecException | null, stdout: string, stderr: string) => void
) => {
@@ -82,7 +82,7 @@ describe('System Routes (/api/system)', () => {
it('should return success: false when pm2 process does not exist', async () => {
// Arrange: Simulate the error and stdout when a process is not found.
const processNotFoundOutput = "[PM2][ERROR] Process or Namespace flyer-crawler-api doesn't exist";
- (mockedExec as Mock).mockImplementation((
+ vi.mocked(mockedExec).mockImplementation((
command: string,
callback: (error: ExecException | null, stdout: string, stderr: string) => void
) => {
@@ -100,7 +100,7 @@ describe('System Routes (/api/system)', () => {
it('should return 500 on a generic exec error', async () => {
// Arrange: Simulate a generic failure of the `exec` command.
- (mockedExec as Mock).mockImplementation((
+ vi.mocked(mockedExec).mockImplementation((
command: string,
callback: (error: ExecException | null, stdout: string, stderr: string) => void
) => {
@@ -120,7 +120,7 @@ describe('System Routes (/api/system)', () => {
// Arrange: Simulate a scenario where the command writes to stderr but doesn't
// produce a formal error object for the callback's first argument.
const stderrMessage = 'A non-fatal warning or configuration issue.';
- (mockedExec as Mock).mockImplementation((
+ vi.mocked(mockedExec).mockImplementation((
command: string,
callback: (error: ExecException | null, stdout: string, stderr: string) => void
) => {
diff --git a/src/routes/user.test.ts b/src/routes/user.test.ts
index 8103cf5c..a95f8150 100644
--- a/src/routes/user.test.ts
+++ b/src/routes/user.test.ts
@@ -417,7 +417,7 @@ describe('User Routes (/api/users)', () => {
});
it('PUT should successfully set the appliances', async () => {
- (mockedDb.setUserAppliances as Mocked).mockResolvedValue([]);
+ vi.mocked(mockedDb.setUserAppliances).mockResolvedValue([]);
const applianceIds = [2, 4, 6];
const response = await supertest(app).put('/api/users/me/appliances').send({ applianceIds });
expect(response.status).toBe(204);
diff --git a/src/services/aiService.server.test.ts b/src/services/aiService.server.test.ts
index 5f860253..b9fec21a 100644
--- a/src/services/aiService.server.test.ts
+++ b/src/services/aiService.server.test.ts
@@ -1,14 +1,15 @@
// src/services/aiService.server.test.ts
-import { describe, it, expect, vi, beforeEach, type Mocked } from 'vitest';
+import { describe, it, expect, vi, beforeEach } from 'vitest';
import type { MasterGroceryItem } from '../types';
+import type { readFile as ReadFileFn } from 'fs/promises';
// Mock fs/promises
const mockReadFile = vi.fn();
vi.mock('fs/promises', () => ({
default: {
- readFile: (...args: any[]) => mockReadFile(...args),
+ readFile: (...args: Parameters) => mockReadFile(...args),
},
- readFile: (...args: any[]) => mockReadFile(...args),
+ readFile: (...args: Parameters) => mockReadFile(...args),
}));
// Mock the Google GenAI library
diff --git a/src/services/db/recipe.test.ts b/src/services/db/recipe.test.ts
index 1e0b846d..73fb1b02 100644
--- a/src/services/db/recipe.test.ts
+++ b/src/services/db/recipe.test.ts
@@ -83,7 +83,7 @@ describe('Recipe DB Service', () => {
describe('removeFavoriteRecipe', () => {
it('should execute a DELETE query', async () => {
- mockQuery.mockResolvedValue({ rows: [] });
+ mockQuery.mockResolvedValue({ rowCount: 1 });
await removeFavoriteRecipe('user-123', 1);
expect(getPool().query).toHaveBeenCalledWith('DELETE FROM public.favorite_recipes WHERE user_id = $1 AND recipe_id = $2', ['user-123', 1]);
});
@@ -111,7 +111,7 @@ describe('Recipe DB Service', () => {
describe('forkRecipe', () => {
it('should call the fork_recipe database function', async () => {
- const mockRecipe: Recipe = { recipe_id: 2, name: 'Forked Recipe', avg_rating: 0, rating_count: 0, status: 'private', created_at: new Date().toISOString() };
+ const mockRecipe: Recipe = { recipe_id: 2, name: 'Forked Recipe', avg_rating: 0, rating_count: 0, fork_count: 0, status: 'private', created_at: new Date().toISOString() };
mockQuery.mockResolvedValue({ rows: [mockRecipe] });
const result = await forkRecipe('user-123', 1);
diff --git a/src/services/db/shopping.test.ts b/src/services/db/shopping.test.ts
index 0d5cd88c..f89225a8 100644
--- a/src/services/db/shopping.test.ts
+++ b/src/services/db/shopping.test.ts
@@ -69,7 +69,7 @@ describe('Shopping DB Service', () => {
describe('deleteShoppingList', () => {
it('should execute a DELETE query with user ownership check', async () => {
- mockQuery.mockResolvedValue({ rows: [] });
+ mockQuery.mockResolvedValue({ rowCount: 1 });
await deleteShoppingList(1, 'user-123');
expect(getPool().query).toHaveBeenCalledWith('DELETE FROM public.shopping_lists WHERE shopping_list_id = $1 AND user_id = $2', [1, 'user-123']);
});
@@ -89,7 +89,7 @@ describe('Shopping DB Service', () => {
describe('removeShoppingListItem', () => {
it('should execute a DELETE query', async () => {
- mockQuery.mockResolvedValue({ rows: [] });
+ mockQuery.mockResolvedValue({ rowCount: 1 });
await removeShoppingListItem(101);
expect(getPool().query).toHaveBeenCalledWith('DELETE FROM public.shopping_list_items WHERE shopping_list_item_id = $1', [101]);
});
diff --git a/src/services/db/user.test.ts b/src/services/db/user.test.ts
index de059729..a237590b 100644
--- a/src/services/db/user.test.ts
+++ b/src/services/db/user.test.ts
@@ -23,7 +23,7 @@ import {
logSearchQuery,
} from './user';
import { mockQuery, mockConnect } from '../../tests/setup/mock-db';
-import type { Profile, User } from '../../types';
+import type { Profile } from '../../types';
// Mock other db services that are used by functions in user.ts
vi.mock('./shopping', () => ({
@@ -92,7 +92,7 @@ describe('User DB Service', () => {
describe('updateUserProfile', () => {
it('should execute an UPDATE query for the user profile', async () => {
- const mockProfile: Profile = { user_id: '123', full_name: 'Updated Name', role: 'user' };
+ const mockProfile: Profile = { user_id: '123', full_name: 'Updated Name', role: 'user', points: 0 };
mockQuery.mockResolvedValue({ rows: [mockProfile] });
await updateUserProfile('123', { full_name: 'Updated Name' });
diff --git a/src/services/notificationService.ts b/src/services/notificationService.ts
index 9a6997e3..ffd0caef 100644
--- a/src/services/notificationService.ts
+++ b/src/services/notificationService.ts
@@ -2,10 +2,8 @@
import toast, { ToastOptions } from 'react-hot-toast';
console.log('[NotificationService] Module loaded.');
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
console.log('[NotificationService] Imported toast object type:', typeof toast);
console.log('[NotificationService] Imported toast keys:', Object.keys(toast || {}));
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (toast && (toast as any).default) {
console.log('[NotificationService] Has .default property:', Object.keys((toast as any).default));
}
@@ -38,10 +36,8 @@ export const notifySuccess = (message: string) => {
if (typeof toast.success !== 'function') {
console.error('[NotificationService] CRITICAL: toast.success is not a function. It is:', typeof toast.success);
// Fallback check for default property (common in CJS/ESM interop issues)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((toast as any).default && typeof (toast as any).default.success === 'function') {
console.warn('[NotificationService] Found success on .default, using that instead.');
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
(toast as any).default.success(message, { ...commonToastOptions, iconTheme: { primary: '#10B981', secondary: '#fff' } });
return;
}