diff --git a/src/components/NoteList.test.tsx b/src/components/NoteList.test.tsx index fa817e3a..72e452f6 100644 --- a/src/components/NoteList.test.tsx +++ b/src/components/NoteList.test.tsx @@ -1107,6 +1107,72 @@ describe('NoteList — multi-select', () => { }) }) +// --- Type note filtering tests --- + +const typeEntry: VaultEntry = { + path: '/Users/luca/Laputa/types/project.md', + filename: 'project.md', + title: 'Project', + isA: 'Type', + aliases: [], + belongsTo: [], + relatedTo: [], + status: null, + owner: null, + cadence: null, + archived: false, + trashed: false, + trashedAt: null, + modifiedAt: 1700000000, + createdAt: null, + fileSize: 200, + snippet: 'Defines the Project type.', + wordCount: 50, + relationships: {}, + icon: null, + color: null, + order: null, + outgoingLinks: [], +} + +const entriesWithType = [...mockEntries, typeEntry] + +describe('NoteList — type note filtering', () => { + beforeEach(() => { + noopSelect.mockClear() + noopReplace.mockClear() + }) + + it('does not show type note PinnedCard when browsing a sectionGroup', () => { + render( + + ) + // The type note snippet should NOT be visible (PinnedCard was removed) + expect(screen.queryByText('Defines the Project type.')).not.toBeInTheDocument() + // But the Project instance should still be in the list + expect(screen.getByText('Build Laputa App')).toBeInTheDocument() + }) + + it('shows clickable header title that navigates to type note', () => { + render( + + ) + const headerLink = screen.getByTestId('type-header-link') + expect(headerLink).toBeInTheDocument() + expect(headerLink.textContent).toBe('Project') + expect(headerLink.style.cursor).toBe('pointer') + fireEvent.click(headerLink) + expect(noopReplace).toHaveBeenCalledWith(typeEntry) + }) + + it('header is not clickable when not viewing a type section', () => { + render( + + ) + expect(screen.queryByTestId('type-header-link')).not.toBeInTheDocument() + }) +}) + describe('NoteList — traffic light padding when sidebar collapsed', () => { it('adds left padding to header when sidebarCollapsed is true', () => { const { container } = render( diff --git a/src/components/NoteList.tsx b/src/components/NoteList.tsx index fc8568bf..f90fce8f 100644 --- a/src/components/NoteList.tsx +++ b/src/components/NoteList.tsx @@ -136,31 +136,24 @@ function EntityView({ entity, groups, query, collapsedGroups, sortPrefs, onToggl ) } -function ListViewHeader({ typeDocument, isTrashView, expiredTrashCount, typeEntryMap, onClickNote }: { - typeDocument: VaultEntry | null; isTrashView: boolean; expiredTrashCount: number - typeEntryMap: Record; onClickNote: (entry: VaultEntry, e: React.MouseEvent) => void +function ListViewHeader({ isTrashView, expiredTrashCount }: { + isTrashView: boolean; expiredTrashCount: number }) { - return ( - <> - {typeDocument && } - - - ) + return } -function ListView({ typeDocument, isTrashView, isChangesView, expiredTrashCount, searched, query, renderItem, typeEntryMap, onClickNote }: { - typeDocument: VaultEntry | null; isTrashView: boolean; isChangesView?: boolean; expiredTrashCount: number +function ListView({ isTrashView, isChangesView, expiredTrashCount, searched, query, renderItem }: { + isTrashView: boolean; isChangesView?: boolean; expiredTrashCount: number searched: VaultEntry[]; query: string renderItem: (entry: VaultEntry) => React.ReactNode - typeEntryMap: Record; onClickNote: (entry: VaultEntry, e: React.MouseEvent) => void }) { const emptyText = isChangesView ? 'No pending changes' : isTrashView ? 'Trash is empty' : (query ? 'No matching notes' : 'No notes found') - const hasHeader = typeDocument || (isTrashView && expiredTrashCount > 0) + const hasHeader = isTrashView && expiredTrashCount > 0 if (searched.length === 0) { return (
- {hasHeader && } + {hasHeader && }
) @@ -172,7 +165,7 @@ function ListView({ typeDocument, isTrashView, isChangesView, expiredTrashCount, data={searched} overscan={200} components={{ - Header: hasHeader ? () => : undefined, + Header: hasHeader ? () => : undefined, }} itemContent={(_index, entry) => renderItem(entry)} /> @@ -369,7 +362,14 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF return (
-

{resolveHeaderTitle(selection, typeDocument)}

+

onReplaceActiveTab(typeDocument) : undefined} + data-testid={typeDocument ? 'type-header-link' : undefined} + > + {resolveHeaderTitle(selection, typeDocument)} +

{!isEntityView && }