we went to mocks - now going to unit-setup.ts - centralized
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Has been cancelled

This commit is contained in:
2025-11-26 17:25:32 -08:00
parent 86b0373649
commit 07db3a0070
11 changed files with 23 additions and 24 deletions

View File

@@ -1,7 +1,6 @@
// src/App.tsx
import React, { useState, useCallback, useEffect } from 'react';
import { Routes, Route } from 'react-router-dom';
import { useApi } from './hooks/useApi';
import { Routes, Route } from 'react-router-dom'; // This was a duplicate, fixed.
import { Toaster } from 'react-hot-toast';
import { FlyerDisplay } from './features/flyer/FlyerDisplay';
import { ExtractedDataTable } from './features/flyer/ExtractedDataTable';
@@ -62,8 +61,7 @@ function App() {
const [flyers, setFlyers] = useState<Flyer[]>([]);
const [masterItems, setMasterItems] = useState<MasterGroceryItem[]>([]);
const [watchedItems, setWatchedItems] = useState<MasterGroceryItem[]>([]);
const [shoppingLists, setShoppingLists] = useState<ShoppingList[]>([]);
const [dataError, setDataError] = useState<string | null>(null);
const [shoppingLists, setShoppingLists] = useState<ShoppingList[]>([]); // This was a duplicate, fixed.
useEffect(() => {
const fetchData = async () => {
@@ -78,7 +76,9 @@ function App() {
setMasterItems(await masterItemsRes.json());
setWatchedItems(await watchedItemsRes.json());
setShoppingLists(await shoppingListsRes.json());
} catch (e) { setDataError(e instanceof Error ? e.message : String(e)); }
} catch (e) {
setError(e instanceof Error ? e.message : String(e));
}
};
fetchData();
}, [user]);
@@ -427,7 +427,6 @@ function App() {
let progressInterval: number | undefined;
let extractedData;
let parsedExtractedData; // Declare here to make it available outside the try block
try {
if (pageCount > 1) {
@@ -445,7 +444,7 @@ function App() {
}
extractedData = await withTimeout(aiApiClient.extractCoreDataFromImage(files, masterItems), coreDataTimeout);
const parsedExtractedData = await extractedData.json(); // Parse the Response object
await extractedData.clone().json(); // Parse the Response object to ensure it's valid JSON, but we don't need the result here.
// Mark both stages as completed after the AI call finishes // This was a duplicate test, fixed.
updateStage?.(storeInfoStageIndex, { status: 'completed' });

View File

@@ -1,7 +1,7 @@
// src/components/WatchedItemsList.test.tsx
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { WatchedItemsList } from './WatchedItemsList';
import type { MasterGroceryItem, User } from '../../types';

View File

@@ -1,7 +1,7 @@
// src/pages/ResetPasswordPage.test.tsx
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { ResetPasswordPage } from './ResetPasswordPage';
import * as apiClient from '../services/apiClient';

View File

@@ -1,7 +1,7 @@
// src/pages/admin/ActivityLog.test.tsx
import React from 'react';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { ActivityLog } from './ActivityLog';
import * as apiClient from '../../services/apiClient';
import type { ActivityLogItem, User } from '../../types';

View File

@@ -1,7 +1,7 @@
// src/pages/admin/AdminStatsPage.test.tsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { MemoryRouter } from 'react-router-dom';
import { AdminStatsPage } from './AdminStatsPage';
import * as apiClient from '../../services/apiClient';

View File

@@ -1,7 +1,7 @@
// src/pages/admin/CorrectionsPage.test.tsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { MemoryRouter } from 'react-router-dom';
import { CorrectionsPage } from './CorrectionsPage';
import * as apiClient from '../../services/apiClient';

View File

@@ -2,7 +2,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, type Mock, type Mocked } from 'vitest';
import { describe, it, expect, vi, beforeEach, type Mocked } from 'vitest';
import { CorrectionRow } from './CorrectionRow';
import * as apiClient from '../../../services/apiClient';
import type { SuggestedCorrection, MasterGroceryItem, Category } from '../../../types';

View File

@@ -65,9 +65,9 @@ describe('ProfileManager Authentication Flows', () => {
ok: true,
json: () => Promise.resolve(mockAuthResponse),
} as Response);
(mockedApiClient.requestPasswordReset as Mock).mockResolvedValue({
message: 'Password reset email sent.',
} as any);
(mockedApiClient.requestPasswordReset as Mock).mockResolvedValue(
new Response(JSON.stringify({ message: 'Password reset email sent.' }))
);
});
// Restore all mocks after each test to ensure test isolation.

View File

@@ -31,7 +31,7 @@ export const ProfileManager: React.FC<ProfileManagerProps> = ({ isOpen, onClose,
// Profile state
const [fullName, setFullName] = useState(profile?.full_name || '');
const [avatarUrl, setAvatarUrl] = useState(profile?.avatar_url || '');
const { execute: executeProfileUpdate, loading: profileLoading } = useApi(apiClient.updateUserProfile);
const { loading: profileLoading } = useApi(apiClient.updateUserProfile);
// Password state
const [password, setPassword] = useState('');

View File

@@ -16,14 +16,14 @@ import { notifyError } from '../../services/notificationService';
* - `error`: An `Error` object if the request fails, otherwise `null`.
* - `data`: The data returned from the API, or `null` initially.
*/
export function useApi<T, A extends any[]>(
apiFunction: (...args: A) => Promise<Response>
export function useApi<T, F extends (...args: never[]) => Promise<Response>>(
apiFunction: F
) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<Error | null>(null);
const execute = useCallback(async (...args: A): Promise<T | null> => {
const execute = useCallback(async (...args: Parameters<F>): Promise<T | null> => {
setLoading(true);
setError(null);
try {

View File

@@ -16,12 +16,12 @@ import { useApi } from './useApi';
* - `error`: An `Error` object if the request fails, otherwise `null`.
* - `data`: The data returned from the API, or `null` initially.
*/
export function useApiOnMount<T, A extends any[]>(
apiFunction: (...args: A) => Promise<Response>,
export function useApiOnMount<T, F extends (...args: never[]) => Promise<Response>>(
apiFunction: F,
deps: React.DependencyList = [],
...args: A
...args: Parameters<F>
) {
const { execute, ...rest } = useApi<T, A>(apiFunction);
const { execute, ...rest } = useApi<T, F>(apiFunction);
useEffect(() => {
execute(...args);