Skip to content

Commit 8367f1f

Browse files
loop: todo-header-mobile completed after 3 iterations
1 parent 286f9fb commit 8367f1f

4 files changed

Lines changed: 437 additions & 3 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { describe, it, expect, beforeEach } from 'vitest'
2+
import { render, screen } from '@testing-library/react'
3+
import userEvent from '@testing-library/user-event'
4+
import { SessionTodoDisplay } from './SessionTodoDisplay'
5+
import { useSessionTodos } from '@/stores/sessionTodosStore'
6+
import type { Todo } from './SessionTodoDisplay'
7+
8+
const activeTodos: Todo[] = [
9+
{ id: '1', content: 'Implement mobile header fix', status: 'in_progress', priority: 'high' },
10+
{ id: '2', content: 'Add regression tests', status: 'pending', priority: 'medium' },
11+
{ id: '3', content: 'Verify completed item grouping', status: 'completed', priority: 'low' },
12+
]
13+
14+
const allCompletedTodos: Todo[] = [
15+
{ id: '1', content: 'Task one', status: 'completed', priority: 'high' },
16+
{ id: '2', content: 'Task two', status: 'completed', priority: 'medium' },
17+
]
18+
19+
describe('SessionTodoDisplay', () => {
20+
beforeEach(() => {
21+
useSessionTodos.setState({ todos: new Map() })
22+
})
23+
24+
it('renders collapsed by default', () => {
25+
useSessionTodos.getState().setTodos('session-1', activeTodos)
26+
27+
render(<SessionTodoDisplay sessionID="session-1" />)
28+
29+
expect(screen.getByText('Tasks: 1/3 complete')).toBeInTheDocument()
30+
31+
expect(screen.queryByText('Implement mobile header fix')).not.toBeInTheDocument()
32+
expect(screen.queryByText('Add regression tests')).not.toBeInTheDocument()
33+
})
34+
35+
it('expands to show a small scrollable task preview when clicked', async () => {
36+
const user = userEvent.setup()
37+
useSessionTodos.getState().setTodos('session-1', activeTodos)
38+
39+
render(<SessionTodoDisplay sessionID="session-1" />)
40+
41+
const collapsedRow = screen.getByText('Tasks: 1/3 complete')
42+
await user.click(collapsedRow)
43+
44+
expect(screen.getByText('Implement mobile header fix')).toBeInTheDocument()
45+
expect(screen.getByText('Add regression tests')).toBeInTheDocument()
46+
expect(screen.getByText('Verify completed item grouping')).toBeInTheDocument()
47+
48+
const expandedContainer = screen.getByTestId('todo-expanded-list')
49+
expect(expandedContainer).toHaveClass('max-h-[80px]')
50+
expect(expandedContainer).toHaveClass('sm:max-h-[160px]')
51+
expect(expandedContainer).toHaveClass('overflow-y-auto')
52+
})
53+
54+
it('collapses again when expanded header is clicked', async () => {
55+
const user = userEvent.setup()
56+
useSessionTodos.getState().setTodos('session-1', activeTodos)
57+
58+
render(<SessionTodoDisplay sessionID="session-1" />)
59+
60+
const collapsedRow = screen.getByText('Tasks: 1/3 complete')
61+
await user.click(collapsedRow)
62+
63+
expect(screen.getByTestId('todo-expanded-list')).toBeInTheDocument()
64+
65+
const expandedHeader = screen.getByText('Tasks: 1/3 complete')
66+
await user.click(expandedHeader)
67+
68+
expect(screen.queryByTestId('todo-expanded-list')).not.toBeInTheDocument()
69+
})
70+
71+
it('does not render when all tasks are completed', () => {
72+
useSessionTodos.getState().setTodos('session-1', allCompletedTodos)
73+
74+
const { container } = render(<SessionTodoDisplay sessionID="session-1" />)
75+
76+
expect(container.firstChild).toBeNull()
77+
})
78+
79+
it('dismisses current todo signature and reappears when todo status changes', async () => {
80+
const user = userEvent.setup()
81+
useSessionTodos.getState().setTodos('session-1', activeTodos)
82+
83+
const { rerender } = render(<SessionTodoDisplay sessionID="session-1" />)
84+
85+
expect(screen.getByText('Tasks: 1/3 complete')).toBeInTheDocument()
86+
87+
const dismissButton = screen.getByLabelText('Dismiss tasks')
88+
await user.click(dismissButton)
89+
90+
expect(screen.queryByText('Tasks: 1/3 complete')).not.toBeInTheDocument()
91+
92+
const updatedTodos: Todo[] = [
93+
{ id: '1', content: 'Implement mobile header fix', status: 'completed', priority: 'high' },
94+
{ id: '2', content: 'Add regression tests', status: 'pending', priority: 'medium' },
95+
{ id: '3', content: 'Verify completed item grouping', status: 'completed', priority: 'low' },
96+
]
97+
useSessionTodos.getState().setTodos('session-1', updatedTodos)
98+
99+
rerender(<SessionTodoDisplay sessionID="session-1" />)
100+
101+
expect(screen.getByText('Tasks: 2/3 complete')).toBeInTheDocument()
102+
})
103+
})

frontend/src/components/message/SessionTodoDisplay.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const todoSignature = (todos: Todo[]) =>
1515

1616
export function SessionTodoDisplay({ sessionID }: SessionTodoDisplayProps) {
1717
const todos = useSessionTodosForSession(sessionID)
18-
const [isCollapsed, setIsCollapsed] = useState(false)
18+
const [isCollapsed, setIsCollapsed] = useState(true)
1919
const [isDismissed, setIsDismissed] = useState(false)
2020
const dismissedSignatureRef = useRef<string>('')
2121

@@ -129,7 +129,7 @@ export function SessionTodoDisplay({ sessionID }: SessionTodoDisplayProps) {
129129
<X className="w-3.5 h-3.5" />
130130
</button>
131131
</div>
132-
<div className="max-h-[80px] sm:max-h-[160px] overflow-y-auto p-1.5 sm:p-2 bg-muted/30">
132+
<div data-testid="todo-expanded-list" className="max-h-[80px] sm:max-h-[160px] overflow-y-auto p-1.5 sm:p-2 bg-muted/30">
133133
{renderGroup('In Progress', inProgress)}
134134
{renderGroup('Pending', pending)}
135135
{renderGroup('Completed', completedTodos)}

frontend/src/pages/SessionDetail.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,10 @@ export function SessionDetail() {
457457
className="h-dvh max-h-dvh overflow-hidden bg-gradient-to-br from-background via-background to-background flex flex-col"
458458
>
459459
<div
460+
data-testid="session-header-region"
460461
className={`flex-shrink-0 overflow-hidden bg-background transition-all duration-200 ease-out ${
461462
isHeaderVisible
462-
? 'max-h-40 opacity-100 translate-y-0'
463+
? 'max-h-72 sm:max-h-80 opacity-100 translate-y-0'
463464
: 'max-h-0 opacity-0 -translate-y-2'
464465
}`}
465466
>

0 commit comments

Comments
 (0)