Files
tolaria/src/components/Inspector.test.tsx
lucaronin a357edf1b2 Add relationships panel to inspector (M4 Task 2)
Show belongsTo and relatedTo from frontmatter as clickable links
that navigate to the referenced note. Empty state when no
relationships exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 20:47:19 +01:00

120 lines
4.4 KiB
TypeScript

import { render, screen, fireEvent } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { Inspector } from './Inspector'
import type { VaultEntry } from '../types'
const mockEntry: VaultEntry = {
path: '/vault/project/test.md',
filename: 'test.md',
title: 'Test Project',
isA: 'Project',
aliases: [],
belongsTo: ['[[responsibility/grow-newsletter]]'],
relatedTo: ['[[topic/software-development]]'],
status: 'Active',
owner: 'Luca Rossi',
cadence: null,
modifiedAt: 1707900000,
fileSize: 1024,
}
const mockContent = `---
title: Test Project
is_a: Project
status: Active
---
# Test Project
This is a test note with some words to count.
`
const defaultProps = {
collapsed: false,
onToggle: () => {},
entry: null as VaultEntry | null,
content: null as string | null,
entries: [] as VaultEntry[],
onNavigate: () => {},
}
describe('Inspector', () => {
it('renders expanded state with "no note selected"', () => {
render(<Inspector {...defaultProps} />)
expect(screen.getByText('Inspector')).toBeInTheDocument()
expect(screen.getByText('Properties')).toBeInTheDocument()
expect(screen.getByText('No note selected')).toBeInTheDocument()
})
it('renders collapsed state without sections', () => {
render(<Inspector {...defaultProps} collapsed={true} />)
expect(screen.queryByText('Inspector')).not.toBeInTheDocument()
expect(screen.queryByText('Properties')).not.toBeInTheDocument()
})
it('calls onToggle when toggle button clicked', () => {
const onToggle = vi.fn()
render(<Inspector {...defaultProps} onToggle={onToggle} />)
fireEvent.click(screen.getByRole('button'))
expect(onToggle).toHaveBeenCalledOnce()
})
it('shows properties when a note is selected', () => {
render(<Inspector {...defaultProps} entry={mockEntry} content={mockContent} />)
expect(screen.getByText('Project')).toBeInTheDocument()
expect(screen.getByText('Active')).toBeInTheDocument()
expect(screen.getByText('Luca Rossi')).toBeInTheDocument()
expect(screen.getByText('Type')).toBeInTheDocument()
expect(screen.getByText('Status')).toBeInTheDocument()
expect(screen.getByText('Owner')).toBeInTheDocument()
expect(screen.getByText('Words')).toBeInTheDocument()
})
it('renders status as a colored pill', () => {
render(<Inspector {...defaultProps} entry={mockEntry} content={mockContent} />)
const pill = screen.getByText('Active')
expect(pill).toHaveClass('inspector__status-pill')
expect(pill).toHaveStyle({ backgroundColor: '#4caf50' })
})
it('computes word count from content minus frontmatter', () => {
render(<Inspector {...defaultProps} entry={mockEntry} content={mockContent} />)
// "# Test Project" + "This is a test note with some words to count." = 13 words
expect(screen.getByText('13')).toBeInTheDocument()
})
it('shows "Add property" button as disabled placeholder', () => {
render(<Inspector {...defaultProps} entry={mockEntry} content={mockContent} />)
const btn = screen.getByText('+ Add property')
expect(btn).toBeDisabled()
})
it('shows cadence when present', () => {
const entryWithCadence = { ...mockEntry, cadence: 'Weekly' }
render(<Inspector {...defaultProps} entry={entryWithCadence} content={mockContent} />)
expect(screen.getByText('Cadence')).toBeInTheDocument()
expect(screen.getByText('Weekly')).toBeInTheDocument()
})
it('shows relationships with clickable links', () => {
render(<Inspector {...defaultProps} entry={mockEntry} content={mockContent} />)
expect(screen.getByText('Belongs to')).toBeInTheDocument()
expect(screen.getByText('Grow Newsletter')).toBeInTheDocument()
expect(screen.getByText('Related to')).toBeInTheDocument()
expect(screen.getByText('Software Development')).toBeInTheDocument()
})
it('navigates when a relationship link is clicked', () => {
const onNavigate = vi.fn()
render(<Inspector {...defaultProps} entry={mockEntry} content={mockContent} onNavigate={onNavigate} />)
fireEvent.click(screen.getByText('Grow Newsletter'))
expect(onNavigate).toHaveBeenCalledWith('grow newsletter')
})
it('shows "No relationships" when entry has no belongsTo/relatedTo', () => {
const noRels = { ...mockEntry, belongsTo: [], relatedTo: [] }
render(<Inspector {...defaultProps} entry={noRels} content={mockContent} />)
expect(screen.getByText('No relationships')).toBeInTheDocument()
})
})