0789893e19
UI Improvements: - Modern gradient buttons with hover effects and shine animation - Better typography and spacing throughout the app - Improved session cards with message count and timestamps - Better styled input fields with focus states - Smooth transitions and animations - Added emoji icons for better visual cues - Improved empty states with icons and better messaging New Features: - Added streaming toggle button in API configuration - Real-time streaming response support with live token display - Stop button to cancel streaming requests - Message count display in header - STREAMING indicator badge when enabled - AbortController support for request cancellation - Export now includes streaming status Technical Changes: - Added sendMessageStream function to llmApi - Added streaming field to Config interface - Updated all components to support streaming mode - All 52 tests passing
82 lines
3.0 KiB
TypeScript
82 lines
3.0 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest'
|
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
import { SessionDrawer } from './SessionDrawer'
|
|
import type { Session, Config } from '../services/sessionService'
|
|
|
|
describe('SessionDrawer', () => {
|
|
const defaultProps = {
|
|
isOpen: true,
|
|
onClose: vi.fn(),
|
|
sessions: [] as Session[],
|
|
currentSessionId: null,
|
|
onSelectSession: vi.fn(),
|
|
onCreateSession: vi.fn(),
|
|
onDeleteSession: vi.fn(),
|
|
config: { endpoint: '', systemPrompt: '', model: 'local-swarm', streaming: false } as Config,
|
|
onUpdateConfig: vi.fn()
|
|
}
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('should render when open', () => {
|
|
render(<SessionDrawer {...defaultProps} />)
|
|
expect(screen.getByText(/Your Sessions/)).toBeInTheDocument()
|
|
expect(screen.getByRole('button', { name: /New Session/i })).toBeInTheDocument()
|
|
})
|
|
|
|
it('should call onClose when overlay clicked', () => {
|
|
render(<SessionDrawer {...defaultProps} />)
|
|
|
|
const overlay = document.querySelector('[style*="position: fixed"]')
|
|
if (overlay) {
|
|
fireEvent.click(overlay)
|
|
expect(defaultProps.onClose).toHaveBeenCalled()
|
|
}
|
|
})
|
|
|
|
it('should display sessions list', () => {
|
|
const sessions: Session[] = [
|
|
{ id: '1', name: 'Session 1', messages: [], endpoint: '', systemPrompt: '', createdAt: Date.now(), updatedAt: Date.now() },
|
|
{ id: '2', name: 'Session 2', messages: [], endpoint: '', systemPrompt: '', createdAt: Date.now(), updatedAt: Date.now() }
|
|
]
|
|
render(<SessionDrawer {...defaultProps} sessions={sessions} currentSessionId="1" />)
|
|
|
|
expect(screen.getByText('Session 1')).toBeInTheDocument()
|
|
expect(screen.getByText('Session 2')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should call onSelectSession when session clicked', () => {
|
|
const sessions: Session[] = [
|
|
{ id: '1', name: 'Session 1', messages: [], endpoint: '', systemPrompt: '', createdAt: Date.now(), updatedAt: Date.now() }
|
|
]
|
|
render(<SessionDrawer {...defaultProps} sessions={sessions} />)
|
|
|
|
fireEvent.click(screen.getByText('Session 1'))
|
|
|
|
expect(defaultProps.onSelectSession).toHaveBeenCalledWith('1')
|
|
expect(defaultProps.onClose).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should call onCreateSession when new session button clicked', () => {
|
|
render(<SessionDrawer {...defaultProps} />)
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: /New Session/i }))
|
|
|
|
expect(defaultProps.onCreateSession).toHaveBeenCalled()
|
|
expect(defaultProps.onClose).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should call onUpdateConfig when save config clicked', () => {
|
|
render(<SessionDrawer {...defaultProps} />)
|
|
|
|
const endpointInput = screen.getByPlaceholderText(/192.168/i)
|
|
fireEvent.change(endpointInput, { target: { value: 'https://new.com' } })
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: /Save Config/i }))
|
|
|
|
expect(defaultProps.onUpdateConfig).toHaveBeenCalledWith({ endpoint: 'https://new.com', systemPrompt: '', model: 'local-swarm', streaming: false })
|
|
})
|
|
})
|