fix(gemini): sync waitingResponseRef on stop and add useGeminiMessage tests#1370
fix(gemini): sync waitingResponseRef on stop and add useGeminiMessage tests#1370
Conversation
… tests
- Add `waitingResponseRef.current = false` inside `resetState` to keep the
ref in sync with the state update. Previously only `setWaitingResponse(false)`
was called (async React update), leaving the ref stale until the next render.
Every other write-site for waitingResponse already performs the double-write.
- Export `useGeminiMessage` so it can be unit-tested in isolation.
- Add three regression tests in `tests/unit/useGeminiMessage.dom.test.ts`:
1. resetState() resets `running` to false
2. resetState() clears activeMsgIdRef so thought events from new messages
are no longer filtered
3. Full lifecycle: old request → resetState → new request → correct filtering
- Include GeminiSendBox.tsx in vitest coverage tracking.
Follow-up to #1354
There was a problem hiding this comment.
Code Review
HIGH Issues
1. New console.log statements in renderer code (debug hygiene / production noise)
File: src/renderer/pages/conversation/gemini/GeminiSendBox.tsx:140-170
console.log(
`%c[RequestTrace]%c ✅ FINISH | ${requestTraceRef.current.provider} → ${requestTraceRef.current.modelId} | ${duration}ms | ${new Date().toISOString()}`,
'color: #52c41a; font-weight: bold',
'color: inherit'
);console.log(
`%c[RequestTrace]%c ➡️ START | ${requestTraceRef.current.provider} → ${trace.modelId} | ${new Date().toISOString()}`,
'color: #1890ff; font-weight: bold',
'color: inherit',
trace
);console.log(
`%c[RequestTrace]%c ❌ ERROR | ${requestTraceRef.current.provider} → ${requestTraceRef.current.modelId} | ${duration}ms | ${new Date().toISOString()}`,
'color: #ff4d4f; font-weight: bold',
'color: inherit',
message.data
);Problem: The PR introduces/keeps console.log in production renderer code. This violates the project’s debug hygiene expectations (no-console: warn) and will add noisy logs for all users during normal usage (every request start/finish/error). Since the PR is already touching this area, it’s a good time to ensure these logs are gated or removed.
Fix: Gate these logs behind a debug flag (e.g., import.meta.env.DEV, process.env.NODE_ENV !== 'production', or a project-specific logger), or replace with the project’s logging facility if one exists.
Example:
const isDev = import.meta.env?.DEV ?? process.env.NODE_ENV !== 'production';
if (isDev) {
console.log(/* ... */);
}Or:
logger.debug('[RequestTrace] ...', { trace });MEDIUM Issues
2. Hook export from a UI module increases coupling; consider extracting to a dedicated hook module
File: src/renderer/pages/conversation/gemini/GeminiSendBox.tsx
The PR changes:
export const useGeminiMessage = (conversation_id: string, onError?: (message: IResponseMessage) => void) => {Recommendation: Exporting the hook is fine for testing, but exporting it from GeminiSendBox.tsx forces tests (and any future consumers) to import a large UI module with many renderer/UI dependencies. You already had to mock a lot to load the module in the new test file, which is a sign of tight coupling.
Fix: Move useGeminiMessage into a dedicated file (e.g. src/renderer/pages/conversation/gemini/hooks/useGeminiMessage.ts) and keep GeminiSendBox.tsx focused on UI composition. This will:
- reduce test mocking surface,
- speed up tests,
- make the hook reusable and easier to reason about.
Summary
| Level | Count |
|---|---|
| CRITICAL | 0 |
| HIGH | 1 |
| MEDIUM | 1 |
🤖 This review was generated by AI and may contain inaccuracies. Please focus on issues you agree with and feel free to disregard any that seem incorrect. Thank you for your contribution!
Summary
resetStateref sync: addswaitingResponseRef.current = falsealongside the existingsetWaitingResponse(false)call. Previously the ref could remain stale (true) between the async React state update and the next render cycle. All other write-sites forwaitingResponsealready perform the double-write;resetStatewas the only exception.useGeminiMessage: makes the hook importable for isolated unit testing.tests/unit/useGeminiMessage.dom.test.ts): three cases coveringresetState()state reset,activeMsgIdRefclearing, and correct event filtering after a new request begins.GeminiSendBox.tsxinvitest.config.ts.Test plan
bun run test -- useGeminiMessage— all 3 new tests passbunx tsc --noEmit— no type errorsbun run lint:fix— no errors (pre-existing warnings only)Closes #1354