mirror of
https://github.com/coleam00/Archon.git
synced 2026-01-01 12:18:41 -05:00
227 lines
6.3 KiB
TypeScript
227 lines
6.3 KiB
TypeScript
import { render, screen, fireEvent } from '@testing-library/react'
|
|
import { describe, test, expect, vi } from 'vitest'
|
|
import React from 'react'
|
|
import { DocumentCard, NewDocumentCard } from '../../../src/components/project-tasks/DocumentCard'
|
|
import type { ProjectDoc } from '../../../src/components/project-tasks/DocumentCard'
|
|
|
|
describe('DocumentCard', () => {
|
|
const mockDocument: ProjectDoc = {
|
|
id: 'doc-1',
|
|
title: 'Test Document',
|
|
content: { test: 'content' },
|
|
document_type: 'prp',
|
|
updated_at: '2025-07-30T12:00:00Z',
|
|
}
|
|
|
|
const mockHandlers = {
|
|
onSelect: vi.fn(),
|
|
onDelete: vi.fn(),
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
test('renders document card with correct content', () => {
|
|
render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
expect(screen.getByText('Test Document')).toBeInTheDocument()
|
|
expect(screen.getByText('prp')).toBeInTheDocument()
|
|
expect(screen.getByText('7/30/2025')).toBeInTheDocument()
|
|
})
|
|
|
|
test('shows correct icon and color for different document types', () => {
|
|
const documentTypes = [
|
|
{ type: 'prp', expectedClass: 'text-blue-600' },
|
|
{ type: 'technical', expectedClass: 'text-green-600' },
|
|
{ type: 'business', expectedClass: 'text-purple-600' },
|
|
{ type: 'meeting_notes', expectedClass: 'text-orange-600' },
|
|
]
|
|
|
|
documentTypes.forEach(({ type, expectedClass }) => {
|
|
const { container, rerender } = render(
|
|
<DocumentCard
|
|
document={{ ...mockDocument, document_type: type }}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const badge = container.querySelector(`.${expectedClass}`)
|
|
expect(badge).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
test('applies active styles when selected', () => {
|
|
const { container } = render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={true}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const card = container.firstChild as HTMLElement
|
|
expect(card.className).toContain('border-blue-500')
|
|
expect(card.className).toContain('scale-105')
|
|
})
|
|
|
|
test('calls onSelect when clicked', () => {
|
|
render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const card = screen.getByText('Test Document').closest('div')
|
|
fireEvent.click(card!)
|
|
|
|
expect(mockHandlers.onSelect).toHaveBeenCalledWith(mockDocument)
|
|
})
|
|
|
|
test('shows delete button on hover', () => {
|
|
const { container } = render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const card = container.firstChild as HTMLElement
|
|
|
|
// Delete button should not be visible initially
|
|
expect(screen.queryByLabelText('Delete Test Document')).not.toBeInTheDocument()
|
|
|
|
// Hover over the card
|
|
fireEvent.mouseEnter(card)
|
|
|
|
// Delete button should now be visible
|
|
expect(screen.getByLabelText('Delete Test Document')).toBeInTheDocument()
|
|
|
|
// Mouse leave
|
|
fireEvent.mouseLeave(card)
|
|
|
|
// Delete button should be hidden again
|
|
expect(screen.queryByLabelText('Delete Test Document')).not.toBeInTheDocument()
|
|
})
|
|
|
|
test('does not show delete button on active card', () => {
|
|
const { container } = render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={true}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const card = container.firstChild as HTMLElement
|
|
fireEvent.mouseEnter(card)
|
|
|
|
expect(screen.queryByLabelText('Delete Test Document')).not.toBeInTheDocument()
|
|
})
|
|
|
|
test('confirms before deleting', () => {
|
|
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true)
|
|
|
|
const { container } = render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const card = container.firstChild as HTMLElement
|
|
fireEvent.mouseEnter(card)
|
|
|
|
const deleteButton = screen.getByLabelText('Delete Test Document')
|
|
fireEvent.click(deleteButton)
|
|
|
|
expect(confirmSpy).toHaveBeenCalledWith('Delete "Test Document"?')
|
|
expect(mockHandlers.onDelete).toHaveBeenCalledWith('doc-1')
|
|
|
|
confirmSpy.mockRestore()
|
|
})
|
|
|
|
test('cancels delete when user declines', () => {
|
|
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(false)
|
|
|
|
const { container } = render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={false}
|
|
/>
|
|
)
|
|
|
|
const card = container.firstChild as HTMLElement
|
|
fireEvent.mouseEnter(card)
|
|
|
|
const deleteButton = screen.getByLabelText('Delete Test Document')
|
|
fireEvent.click(deleteButton)
|
|
|
|
expect(confirmSpy).toHaveBeenCalled()
|
|
expect(mockHandlers.onDelete).not.toHaveBeenCalled()
|
|
|
|
confirmSpy.mockRestore()
|
|
})
|
|
|
|
test('applies dark mode styles correctly', () => {
|
|
const { container } = render(
|
|
<DocumentCard
|
|
document={mockDocument}
|
|
isActive={false}
|
|
onSelect={mockHandlers.onSelect}
|
|
onDelete={mockHandlers.onDelete}
|
|
isDarkMode={true}
|
|
/>
|
|
)
|
|
|
|
const card = container.firstChild as HTMLElement
|
|
expect(card.className).toContain('dark:')
|
|
})
|
|
})
|
|
|
|
describe('NewDocumentCard', () => {
|
|
test('renders new document card', () => {
|
|
const onClick = vi.fn()
|
|
render(<NewDocumentCard onClick={onClick} />)
|
|
|
|
expect(screen.getByText('New Document')).toBeInTheDocument()
|
|
})
|
|
|
|
test('calls onClick when clicked', () => {
|
|
const onClick = vi.fn()
|
|
render(<NewDocumentCard onClick={onClick} />)
|
|
|
|
const card = screen.getByText('New Document').closest('div')
|
|
fireEvent.click(card!)
|
|
|
|
expect(onClick).toHaveBeenCalledTimes(1)
|
|
})
|
|
}) |