From eee33433d9965dc0cec45e5f3f5fbac0a7ae9931 Mon Sep 17 00:00:00 2001 From: Frederick Legaspi Date: Sun, 2 Nov 2025 10:32:56 -0500 Subject: [PATCH 1/3] fix: resolve TypeScript error in theme-provider test - Fix 'children' prop missing error by passing undefined instead of empty - All 11 tests still passing - Resolves TypeScript compilation error --- .../components/theme-provider.test.tsx | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/__tests__/components/theme-provider.test.tsx diff --git a/src/__tests__/components/theme-provider.test.tsx b/src/__tests__/components/theme-provider.test.tsx new file mode 100644 index 0000000..fb63c7a --- /dev/null +++ b/src/__tests__/components/theme-provider.test.tsx @@ -0,0 +1,136 @@ +import { render, screen } from '@testing-library/react'; +import { ThemeProvider } from '@/components/theme-provider'; +import { useTheme } from 'next-themes'; + +// Mock next-themes +jest.mock('next-themes', () => ({ + ThemeProvider: ({ children }: { children: React.ReactNode }) =>
{children}
, + useTheme: jest.fn(), +})); + +describe('ThemeProvider', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('Rendering', () => { + it('should render children', () => { + render( + +
Test Child
+
+ ); + + expect(screen.getByTestId('child')).toBeInTheDocument(); + expect(screen.getByText('Test Child')).toBeInTheDocument(); + }); + + it('should wrap children with NextThemesProvider', () => { + render( + +
Content
+
+ ); + + expect(screen.getByTestId('theme-provider')).toBeInTheDocument(); + }); + + it('should render multiple children', () => { + render( + +
Child 1
+
Child 2
+
Child 3
+
+ ); + + expect(screen.getByTestId('child-1')).toBeInTheDocument(); + expect(screen.getByTestId('child-2')).toBeInTheDocument(); + expect(screen.getByTestId('child-3')).toBeInTheDocument(); + }); + }); + + describe('Props Forwarding', () => { + it('should forward attribute prop to NextThemesProvider', () => { + const { container } = render( + +
Content
+
+ ); + + expect(container).toBeInTheDocument(); + }); + + it('should forward defaultTheme prop to NextThemesProvider', () => { + const { container } = render( + +
Content
+
+ ); + + expect(container).toBeInTheDocument(); + }); + + it('should forward enableSystem prop to NextThemesProvider', () => { + const { container } = render( + +
Content
+
+ ); + + expect(container).toBeInTheDocument(); + }); + + it('should forward disableTransitionOnChange prop to NextThemesProvider', () => { + const { container } = render( + +
Content
+
+ ); + + expect(container).toBeInTheDocument(); + }); + + it('should forward multiple props simultaneously', () => { + const { container } = render( + +
Content
+
+ ); + + expect(container).toBeInTheDocument(); + }); + }); + + describe('Integration', () => { + it('should work with nested components', () => { + const NestedComponent = () =>
Nested
; + + render( + +
+ +
+
+ ); + + expect(screen.getByTestId('nested')).toBeInTheDocument(); + }); + + it('should not throw when children is null', () => { + expect(() => { + render({null}); + }).not.toThrow(); + }); + + it('should handle empty children', () => { + const { container } = render({undefined}); + expect(container).toBeInTheDocument(); + }); + }); +}); From a1dd36c778fbfa477342da5e07e68fd67207dd3b Mon Sep 17 00:00:00 2001 From: Frederick Legaspi Date: Tue, 4 Nov 2025 11:09:46 -0500 Subject: [PATCH 2/3] fix: display actual title prop in ConversationTitle component (TDD) TDD Red Phase: - Added 3 failing tests for custom title display bug - Tests verified title was overridden to 'New Conversation' Root Cause: - Line 58 in conversation-title.tsx had conditional override: const displayTitle = isNewConversation ? 'New Conversation' : title - When messages.length === 0, isNewConversation is true - Component overrode custom title with 'New Conversation' TDD Green Phase: - Removed conditional override: const displayTitle = title - Component now always displays actual title prop - Updated test expecting old buggy behavior Result: - Title updates immediately in UI when changed - All 33 component tests passing - All 511 tests passing (no regressions) - Fixes issue documented in docs/04-development/issues/ Previous 7 fix attempts modified page.tsx state management, but bug was in component override logic all along. --- .../components/conversation-title.test.tsx | 35 +++++++++++++++++-- src/components/conversation-title.tsx | 4 ++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/__tests__/components/conversation-title.test.tsx b/src/__tests__/components/conversation-title.test.tsx index 65f230c..80832bb 100644 --- a/src/__tests__/components/conversation-title.test.tsx +++ b/src/__tests__/components/conversation-title.test.tsx @@ -19,9 +19,10 @@ describe('ConversationTitle', () => { expect(screen.getByText('Test Conversation')).toBeInTheDocument(); }); - it('displays "New Conversation" for new conversations', () => { + it('displays actual title prop even for new conversations', () => { + // Fixed: Now displays the actual title prop, not hardcoded "New Conversation" render(); - expect(screen.getByText('New Conversation')).toBeInTheDocument(); + expect(screen.getByText('Test Conversation')).toBeInTheDocument(); }); it('shows edit button on hover (non-new conversations)', () => { @@ -422,4 +423,34 @@ describe('ConversationTitle', () => { expect(input.value).toBe('External Update'); }); }); + + describe('Custom Title Display (Bug Fix)', () => { + it('displays custom title even when isNewConversation is true and has no messages', () => { + // BUG: When a new conversation gets a custom title but has no messages yet, + // it should show the custom title, not "New Conversation" + render(); + + // Should show custom title, not "New Conversation" + expect(screen.getByText('My Custom Title')).toBeInTheDocument(); + expect(screen.queryByText('New Conversation')).not.toBeInTheDocument(); + }); + + it('displays "New Conversation" only when title is actually "New Conversation"', () => { + render(); + expect(screen.getByText('New Conversation')).toBeInTheDocument(); + }); + + it('updates from "New Conversation" to custom title in real-time', () => { + const { rerender } = render( + + ); + expect(screen.getByText('New Conversation')).toBeInTheDocument(); + + // User sets custom title - should update immediately + rerender(); + expect(screen.getByText('Research Notes')).toBeInTheDocument(); + expect(screen.queryByText('New Conversation')).not.toBeInTheDocument(); + }); + }); }); + diff --git a/src/components/conversation-title.tsx b/src/components/conversation-title.tsx index 872c238..d8762cf 100644 --- a/src/components/conversation-title.tsx +++ b/src/components/conversation-title.tsx @@ -57,7 +57,9 @@ export function ConversationTitle({ title, onTitleChange, isNewConversation }: C } }; - const displayTitle = isNewConversation ? 'New Conversation' : title; + // Always display the actual title prop - don't override with "New Conversation" + // The parent component determines what title to show + const displayTitle = title; if (isEditing) { return ( From 20ac3e0e9611d04943f4d2fc4043b7dde4a685f3 Mon Sep 17 00:00:00 2001 From: Frederick Legaspi Date: Tue, 4 Nov 2025 11:10:57 -0500 Subject: [PATCH 3/3] docs: update issue resolution and README with title fix details --- README.md | 26 ++++++ .../conversation-title-not-updating-in-ui.md | 84 +++++++++++++++++-- 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 805c084..9b71abc 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,32 @@ An intelligent AI-powered chat application built with Next.js 15 and Google Gemi - Word documents (.docx) - Extracted text content - **🌐 Website Scraping:** Provide any website URL, and the application will scrape its content to use as a source - **📊 Source Management:** Clean sidebar interface to easily add, view, and remove your files and URL sources + +## 🚀 Recent Updates + +### November 4, 2025 - Conversation Title UI Fix 🐛 +- ✅ **Fixed Critical Bug** - Conversation titles now update immediately in the header + - **Root Cause:** `ConversationTitle` component was overriding the title prop with hardcoded "New Conversation" when `messages.length === 0` + - **Solution:** Removed conditional override logic - component now displays actual title prop + - **Impact:** Instant UI updates when changing conversation titles (no more page refresh needed) + - **Testing:** TDD methodology with 3 new tests, all 511 tests passing ✅ + - **Branch:** `fix/conversation-title-ui-update` + - **Lesson:** Previous 7 fix attempts modified state management, but bug was in component display logic + +### November 2, 2025 - Enhanced Conversation Management +- ✅ **Save Empty Conversations** - You can now save and name conversations even without messages or files + - Create conversations with custom titles before chatting + - Edit conversation titles anytime (not just after first message) + - Better organization for planning and research workflows + +### October 30, 2025 - Extended File Type Support 📄 +- ✅ **Added support for 3 new file types:** CSV, Markdown, and Word documents + - `.csv` - Parsed with column headers and formatted tables + - `.md` - Markdown files with preserved formatting + - `.docx` - Microsoft Word documents with extracted text +- ✅ **Updated welcome message** to reflect all 5 supported file types +- ✅ **Comprehensive testing** with Jest and Playwright for all file formats + - **🎨 AI-Powered Theme Generation:** Dynamically create and apply color themes with AI-generated background images powered by Gemini 2.5 Flash Image - **🌙 Dark/Light Mode:** Quick theme toggle with keyboard shortcut (`Ctrl+Shift+T`) - **📱 Responsive Design:** Modern, responsive UI that works across different screen sizes diff --git a/docs/04-development/issues/conversation-title-not-updating-in-ui.md b/docs/04-development/issues/conversation-title-not-updating-in-ui.md index 03a5f65..c7bd0e8 100644 --- a/docs/04-development/issues/conversation-title-not-updating-in-ui.md +++ b/docs/04-development/issues/conversation-title-not-updating-in-ui.md @@ -1,9 +1,12 @@ # Issue: Conversation Title Not Updating in UI -**Status:** Open +**Status:** ✅ RESOLVED **Priority:** High **Date Reported:** November 2, 2025 -**Branch:** feat/save-empty-conversations +**Date Resolved:** November 4, 2025 +**Original Branch:** feat/save-empty-conversations +**Fix Branch:** fix/conversation-title-ui-update +**Commit:** a1dd36c ## Problem Description @@ -147,14 +150,77 @@ useEffect(() => { All unit tests pass, but the visual UI update is not happening. This suggests the issue is related to React's rendering cycle rather than the underlying logic. -## Next Steps +--- -1. Add detailed console logging to track state changes -2. Inspect ChatHeader and ConversationTitle components for rendering issues -3. Check React DevTools to see if props are updating -4. Consider if this is a React 19 or Next.js 15 specific issue -5. Try creating a minimal reproduction case +## ✅ RESOLUTION (November 4, 2025) -## Workaround for Users +### Root Cause Found +The bug was **NOT** in `page.tsx` state management (as all 7 attempts assumed), but in the `ConversationTitle` component itself. + +**File:** `src/components/conversation-title.tsx` +**Line:** 58 +**Buggy Code:** +```typescript +const displayTitle = isNewConversation ? 'New Conversation' : title; +``` + +**Problem:** +- When `isNewConversation = !currentConversationId || messages.length === 0` +- User sets custom title on empty conversation → `currentConversationId` exists +- But `messages.length === 0` is still `true` +- Therefore `isNewConversation` is `true` +- Component **overrides** the `title` prop with hardcoded `"New Conversation"` +- Title prop was correct, but component ignored it! + +### Fix Applied (TDD Methodology) + +**Red Phase:** Added 3 failing tests +1. "displays custom title even when isNewConversation is true and has no messages" +2. "displays 'New Conversation' only when title is actually 'New Conversation'" +3. "updates from 'New Conversation' to custom title in real-time" + +**Green Phase:** Fixed bug with single line change +```typescript +// BEFORE (BUGGY): +const displayTitle = isNewConversation ? 'New Conversation' : title; + +// AFTER (FIXED): +// Always display the actual title prop - don't override with "New Conversation" +// The parent component determines what title to show +const displayTitle = title; +``` + +Also updated existing test that expected buggy behavior. + +**Result:** +- ✅ Title updates immediately in UI +- ✅ All 33 component tests passing +- ✅ All 511 tests passing (no regressions) +- ✅ Minimal change (1 line fix) + +### Why Previous 7 Attempts Failed +All previous fixes modified `page.tsx` state management: +- Removed dependencies from auto-save +- Added refs to prevent stale closures +- Fixed state update order +- Auto-synced refs with useEffect +- Saved full conversation on title change +- Updated refs before setting conversation ID + +**The real problem:** State management was working correctly all along! The component was **fighting against** the parent's state updates by overriding the title prop internally. + +### Lessons Learned +1. **Component hierarchy matters** - Check child components for prop overrides +2. **State vs Display** - Component was ignoring parent's state +3. **Minimal testing** - Previous attempts only tested state, not DOM rendering +4. **TDD helps** - Writing failing tests exposed the component-level bug + +### Related Commits +- Fix commit: `a1dd36c` on `fix/conversation-title-ui-update` branch +- Previous attempts: 7 commits on `feat/save-empty-conversations` branch (superseded) + +--- + +## Workaround for Users (NO LONGER NEEDED) **Current Workaround:** Refresh the page (F5 or Ctrl+R) after changing title or loading conversation.