import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { describe, test, expect, vi, beforeEach } from 'vitest'
import React from 'react'
// Mock the dependencies
vi.mock('../../contexts/ToastContext', () => ({
useToast: () => ({
showToast: vi.fn()
})
}))
vi.mock('../../services/projectService', () => ({
projectService: {
getProjectDocuments: vi.fn().mockResolvedValue([])
}
}))
vi.mock('../../services/knowledgeBaseService', () => ({
knowledgeBaseService: {
getItems: vi.fn().mockResolvedValue([])
}
}))
// Create a minimal DocsTab component for testing
const DocsTabTest = () => {
const [documents, setDocuments] = React.useState([
{
id: 'doc-1',
title: 'Document 1',
content: { type: 'prp' },
document_type: 'prp',
updated_at: '2025-07-30T12:00:00Z'
},
{
id: 'doc-2',
title: 'Document 2',
content: { type: 'technical' },
document_type: 'technical',
updated_at: '2025-07-30T13:00:00Z'
},
{
id: 'doc-3',
title: 'Document 3',
content: { type: 'business' },
document_type: 'business',
updated_at: '2025-07-30T14:00:00Z'
}
])
const [selectedDocument, setSelectedDocument] = React.useState(documents[0])
const { showToast } = { showToast: vi.fn() }
return (
{documents.map(doc => (
setSelectedDocument(doc)}
>
{doc.document_type}
{doc.title}
{selectedDocument?.id !== doc.id && (
)}
))}
console.log('New document')}
>
New Document
{selectedDocument && (
Selected: {selectedDocument.title}
)}
)
}
describe('DocsTab Document Cards Integration', () => {
beforeEach(() => {
vi.clearAllMocks()
})
test('renders all document cards', () => {
render()
expect(screen.getByTestId('document-card-doc-1')).toBeInTheDocument()
expect(screen.getByTestId('document-card-doc-2')).toBeInTheDocument()
expect(screen.getByTestId('document-card-doc-3')).toBeInTheDocument()
expect(screen.getByTestId('new-document-card')).toBeInTheDocument()
})
test('shows active state on selected document', () => {
render()
const doc1 = screen.getByTestId('document-card-doc-1')
expect(doc1.className).toContain('border-blue-500')
const doc2 = screen.getByTestId('document-card-doc-2')
expect(doc2.className).not.toContain('border-blue-500')
})
test('switches between documents', () => {
render()
// Initially doc-1 is selected
expect(screen.getByTestId('selected-document')).toHaveTextContent('Selected: Document 1')
// Click on doc-2
fireEvent.click(screen.getByTestId('document-card-doc-2'))
// Now doc-2 should be selected
expect(screen.getByTestId('selected-document')).toHaveTextContent('Selected: Document 2')
// Check active states
expect(screen.getByTestId('document-card-doc-1').className).not.toContain('border-blue-500')
expect(screen.getByTestId('document-card-doc-2').className).toContain('border-blue-500')
})
test('deletes document with confirmation', () => {
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true)
render()
// Click delete on doc-2
const deleteButton = screen.getByTestId('delete-doc-2')
fireEvent.click(deleteButton)
expect(confirmSpy).toHaveBeenCalledWith('Delete "Document 2"?')
// Document should be removed
expect(screen.queryByTestId('document-card-doc-2')).not.toBeInTheDocument()
confirmSpy.mockRestore()
})
test('cancels delete when user declines', () => {
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(false)
render()
// Click delete on doc-2
const deleteButton = screen.getByTestId('delete-doc-2')
fireEvent.click(deleteButton)
// Document should still be there
expect(screen.getByTestId('document-card-doc-2')).toBeInTheDocument()
confirmSpy.mockRestore()
})
test('selects next document when deleting active document', () => {
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true)
render()
// doc-1 is initially selected
expect(screen.getByTestId('selected-document')).toHaveTextContent('Selected: Document 1')
// Switch to doc-2
fireEvent.click(screen.getByTestId('document-card-doc-2'))
expect(screen.getByTestId('selected-document')).toHaveTextContent('Selected: Document 2')
// Delete doc-2 (currently selected)
const deleteButton = screen.getByTestId('delete-doc-2')
fireEvent.click(deleteButton)
// Should automatically select another document
expect(screen.getByTestId('selected-document')).toHaveTextContent('Selected: Document')
expect(screen.queryByTestId('document-card-doc-2')).not.toBeInTheDocument()
confirmSpy.mockRestore()
})
test('does not show delete button on active card', () => {
render()
// doc-1 is active, should not have delete button
expect(screen.queryByTestId('delete-doc-1')).not.toBeInTheDocument()
// doc-2 is not active, should have delete button
expect(screen.getByTestId('delete-doc-2')).toBeInTheDocument()
})
test('horizontal scroll container has correct classes', () => {
const { container } = render()
const scrollContainer = container.querySelector('.overflow-x-auto')
expect(scrollContainer).toBeInTheDocument()
expect(scrollContainer?.className).toContain('scrollbar-thin')
expect(scrollContainer?.className).toContain('scrollbar-thumb-gray-300')
})
test('document cards maintain fixed width', () => {
render()
const cards = screen.getAllByTestId(/document-card-doc-/)
cards.forEach(card => {
expect(card.className).toContain('flex-shrink-0')
expect(card.className).toContain('w-48')
})
})
})