Refactor tests to use mockClient for database interactions, improve error handling, and enhance modal functionality
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Has been cancelled

- Updated personalization.db.test.ts to use mockClient for query calls in addWatchedItem tests.
- Simplified error handling in shopping.db.test.ts, ensuring clearer error messages.
- Added comprehensive tests for VoiceAssistant component, including rendering and interaction tests.
- Introduced useModal hook with tests to manage modal state effectively.
- Created deals.db.test.ts to test deals repository functionality with mocked database interactions.
- Implemented error handling tests for custom error classes in errors.db.test.ts.
- Developed googleGeocodingService.server.test.ts to validate geocoding service behavior with mocked fetch.
This commit is contained in:
2025-12-14 01:12:33 -08:00
parent 7615d7746e
commit f891da687b
25 changed files with 786 additions and 290 deletions

View File

@@ -20,6 +20,7 @@ import { QuestionMarkCircleIcon } from './components/icons/QuestionMarkCircleIco
import { useAuth } from './hooks/useAuth';
import { useFlyers } from './hooks/useFlyers'; // Assuming useFlyers fetches all flyers
import { useFlyerItems } from './hooks/useFlyerItems'; // Import the new hook for flyer items
import { useModal } from './hooks/useModal';
import { MainLayout } from './layouts/MainLayout';
import config from './config';
import { HomePage } from './pages/HomePage';
@@ -34,18 +35,13 @@ function App() {
const { user, profile, authStatus, login, logout, updateProfile } = useAuth();
const { flyers } = useFlyers();
const [selectedFlyer, setSelectedFlyer] = useState<Flyer | null>(null);
const { openModal, closeModal, isModalOpen } = useModal();
const location = useLocation();
const params = useParams<{ flyerId?: string }>();
const [isDarkMode, setIsDarkMode] = useState(false);
// Fetch items for the currently selected flyer
const { flyerItems } = useFlyerItems(selectedFlyer);
const [unitSystem, setUnitSystem] = useState<'metric' | 'imperial'>('imperial');
const [isProfileManagerOpen, setIsProfileManagerOpen] = useState(false); // This will now control the login modal as well
const [isWhatsNewOpen, setIsWhatsNewOpen] = useState(false);
const [isVoiceAssistantOpen, setIsVoiceAssistantOpen] = useState(false);
const [isCorrectionToolOpen, setIsCorrectionToolOpen] = useState(false);
const handleDataExtractedFromCorrection = (type: 'store_name' | 'dates', value: string) => {
if (!selectedFlyer) return;
@@ -180,7 +176,7 @@ function App() {
const lastSeenVersion = localStorage.getItem('lastSeenVersion');
// If the current version is new, show the "What's New" modal.
if (appVersion !== lastSeenVersion) {
setIsWhatsNewOpen(true);
openModal('whatsNew');
localStorage.setItem('lastSeenVersion', appVersion);
}
}
@@ -207,36 +203,34 @@ function App() {
profile={profile}
authStatus={authStatus}
user={user}
onOpenProfile={() => setIsProfileManagerOpen(true)}
onOpenVoiceAssistant={() => setIsVoiceAssistantOpen(true)}
onOpenProfile={() => openModal('profile')}
onOpenVoiceAssistant={() => openModal('voiceAssistant')}
onSignOut={logout}
/>
{/* The ProfileManager is now always available to be opened, handling both login and profile management. */}
{isProfileManagerOpen && (
<ProfileManager
isOpen={isProfileManagerOpen}
onClose={() => setIsProfileManagerOpen(false)}
user={user}
authStatus={authStatus}
profile={profile}
onProfileUpdate={handleProfileUpdate}
onLoginSuccess={handleLoginSuccess}
onSignOut={logout} // Pass the signOut handler
/>
)}
<ProfileManager
isOpen={isModalOpen('profile')}
onClose={() => closeModal('profile')}
user={user}
authStatus={authStatus}
profile={profile}
onProfileUpdate={handleProfileUpdate}
onLoginSuccess={handleLoginSuccess}
onSignOut={logout} // Pass the signOut handler
/>
{user && (
<VoiceAssistant
isOpen={isVoiceAssistantOpen}
onClose={() => setIsVoiceAssistantOpen(false)}
isOpen={isModalOpen('voiceAssistant')}
onClose={() => closeModal('voiceAssistant')}
/>
)}
{/* "What's New" modal, shown automatically on new versions */}
{appVersion && commitMessage && (
<WhatsNewModal
isOpen={isWhatsNewOpen}
onClose={() => setIsWhatsNewOpen(false)}
isOpen={isModalOpen('whatsNew')}
onClose={() => closeModal('whatsNew')}
version={appVersion}
commitMessage={commitMessage}
/>
@@ -244,8 +238,8 @@ function App() {
{selectedFlyer && (
<FlyerCorrectionTool
isOpen={isCorrectionToolOpen}
onClose={() => setIsCorrectionToolOpen(false)}
isOpen={isModalOpen('correctionTool')}
onClose={() => closeModal('correctionTool')}
imageUrl={selectedFlyer.image_url}
onDataExtracted={handleDataExtractedFromCorrection}
/>
@@ -257,14 +251,14 @@ function App() {
<MainLayout
onFlyerSelect={handleFlyerSelect}
selectedFlyerId={selectedFlyer?.flyer_id || null}
onOpenProfile={() => setIsProfileManagerOpen(true)} // Pass the profile opener function
onOpenProfile={() => openModal('profile')} // Pass the profile opener function
/>
}>
<Route index element={
<HomePage selectedFlyer={selectedFlyer} flyerItems={flyerItems} onOpenCorrectionTool={() => setIsCorrectionToolOpen(true)} />
<HomePage selectedFlyer={selectedFlyer} flyerItems={flyerItems} onOpenCorrectionTool={() => openModal('correctionTool')} />
} />
<Route path="/flyers/:flyerId" element={
<HomePage selectedFlyer={selectedFlyer} flyerItems={flyerItems} onOpenCorrectionTool={() => setIsCorrectionToolOpen(true)} />
<HomePage selectedFlyer={selectedFlyer} flyerItems={flyerItems} onOpenCorrectionTool={() => openModal('correctionTool')} />
} />
</Route>
@@ -292,7 +286,7 @@ function App() {
>
Version: {appVersion}
</a>
<button onClick={() => setIsWhatsNewOpen(true)} title="Show what's new in this version">
<button onClick={() => openModal('whatsNew')} title="Show what's new in this version">
<QuestionMarkCircleIcon className="w-5 h-5 text-gray-400 dark:text-gray-600 hover:text-brand-primary dark:hover:text-brand-primary transition-colors" />
</button>
</div>