import { getDashboardData, hasVisibleBlocks, DashboardNote, DashboardData } from '@/lib/dashboard' // Mock prisma and usage before importing dashboard module jest.mock('@/lib/prisma', () => ({ prisma: { note: { findMany: jest.fn(), }, }, })) jest.mock('@/lib/usage', () => ({ getRecentlyUsedNotes: jest.fn(), })) import { prisma } from '@/lib/prisma' import { getRecentlyUsedNotes } from '@/lib/usage' describe('dashboard.ts', () => { const mockNotes = [ { id: 'note-1', title: 'Docker Commands', content: 'docker build, docker run', type: 'command', isFavorite: true, isPinned: false, createdAt: new Date('2024-01-01'), updatedAt: new Date('2024-01-15'), tags: [{ tag: { id: 'tag-1', name: 'docker' } }], }, { id: 'note-2', title: 'React Snippet', content: 'useState usage', type: 'snippet', isFavorite: false, isPinned: true, createdAt: new Date('2024-01-02'), updatedAt: new Date('2024-01-14'), tags: [{ tag: { id: 'tag-2', name: 'react' } }], }, { id: 'note-3', title: 'Git Commands', content: 'git commit, git push', type: 'command', isFavorite: false, isPinned: false, createdAt: new Date('2024-01-03'), updatedAt: new Date('2024-01-13'), tags: [{ tag: { id: 'tag-3', name: 'git' } }], }, { id: 'note-4', title: 'SQL Queries', content: 'SELECT * FROM', type: 'snippet', isFavorite: true, isPinned: true, createdAt: new Date('2024-01-04'), updatedAt: new Date('2024-01-12'), tags: [{ tag: { id: 'tag-4', name: 'sql' } }], }, ] beforeEach(() => { jest.clearAllMocks() }) describe('getDashboardData', () => { it('should return dashboard data with all sections', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([ { noteId: 'note-1', count: 5, lastUsed: new Date() }, { noteId: 'note-2', count: 3, lastUsed: new Date() }, ]) const result = await getDashboardData(3) expect(result).toHaveProperty('recentNotes') expect(result).toHaveProperty('mostUsedNotes') expect(result).toHaveProperty('recentCommands') expect(result).toHaveProperty('recentSnippets') expect(result).toHaveProperty('activityBasedNotes') expect(result).toHaveProperty('hasActivity') }) it('should return recent notes ordered by updatedAt', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([]) const result = await getDashboardData(2) expect(result.recentNotes).toHaveLength(2) expect(result.recentNotes[0].id).toBe('note-1') // most recent expect(result.recentNotes[1].id).toBe('note-2') }) it('should return most used notes by usage count', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([ { noteId: 'note-2', count: 10, lastUsed: new Date() }, { noteId: 'note-1', count: 5, lastUsed: new Date() }, ]) const result = await getDashboardData(3) expect(result.mostUsedNotes).toHaveLength(2) expect(result.mostUsedNotes[0].id).toBe('note-2') // highest usage expect(result.mostUsedNotes[0].usageCount).toBe(10) }) it('should return only command type notes for recentCommands', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([]) const result = await getDashboardData(5) expect(result.recentCommands).toHaveLength(2) expect(result.recentCommands.every((n: DashboardNote) => n.type === 'command')).toBe(true) expect(result.recentCommands[0].id).toBe('note-1') }) it('should return only snippet type notes for recentSnippets', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([]) const result = await getDashboardData(5) expect(result.recentSnippets).toHaveLength(2) expect(result.recentSnippets.every((n: DashboardNote) => n.type === 'snippet')).toBe(true) }) it('should return activity based notes excluding recent notes', async () => { // mockNotes are sorted by updatedAt desc: note-1, note-2, note-3, note-4 ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) // note-4 is in recently used but will be filtered out since recentNotes has first 3 ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([ { noteId: 'note-4', count: 5, lastUsed: new Date() }, ]) const result = await getDashboardData(3) // note-4 is used but not in recentNotes (which contains note-1, note-2, note-3) expect(result.activityBasedNotes).toHaveLength(1) expect(result.activityBasedNotes[0].id).toBe('note-4') }) it('should set hasActivity based on recently used notes', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([ { noteId: 'note-1', count: 5, lastUsed: new Date() }, ]) const resultWithActivity = await getDashboardData(3) expect(resultWithActivity.hasActivity).toBe(true) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([]) const resultWithoutActivity = await getDashboardData(3) expect(resultWithoutActivity.hasActivity).toBe(false) }) it('should respect the limit parameter', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([ { noteId: 'note-1', count: 10, lastUsed: new Date() }, { noteId: 'note-2', count: 8, lastUsed: new Date() }, { noteId: 'note-3', count: 6, lastUsed: new Date() }, { noteId: 'note-4', count: 4, lastUsed: new Date() }, ]) const result = await getDashboardData(2) expect(result.recentNotes).toHaveLength(2) expect(result.mostUsedNotes).toHaveLength(2) }) it('should add usageCount to notes from usage map', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([ { noteId: 'note-1', count: 10, lastUsed: new Date() }, { noteId: 'note-2', count: 5, lastUsed: new Date() }, ]) const result = await getDashboardData(3) const note1 = result.mostUsedNotes.find((n: DashboardNote) => n.id === 'note-1') const note2 = result.mostUsedNotes.find((n: DashboardNote) => n.id === 'note-2') expect(note1?.usageCount).toBe(10) expect(note2?.usageCount).toBe(5) }) it('should return empty arrays when no notes exist', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue([]) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([]) const result = await getDashboardData() expect(result.recentNotes).toEqual([]) expect(result.mostUsedNotes).toEqual([]) expect(result.recentCommands).toEqual([]) expect(result.recentSnippets).toEqual([]) expect(result.activityBasedNotes).toEqual([]) expect(result.hasActivity).toBe(false) }) it('should convert dates to ISO strings', async () => { ;(prisma.note.findMany as jest.Mock).mockResolvedValue(mockNotes) ;(getRecentlyUsedNotes as jest.Mock).mockResolvedValue([]) const result = await getDashboardData(1) expect(result.recentNotes[0].createdAt).toBe('2024-01-01T00:00:00.000Z') expect(result.recentNotes[0].updatedAt).toBe('2024-01-15T00:00:00.000Z') }) }) describe('hasVisibleBlocks', () => { it('should return true when recentNotes has items', () => { const data: DashboardData = { recentNotes: [{ id: '1', title: 'Test', content: '', type: 'note' as const, isFavorite: false, isPinned: false, createdAt: '', updatedAt: '', tags: [] }], mostUsedNotes: [], recentCommands: [], recentSnippets: [], activityBasedNotes: [], hasActivity: false, } expect(hasVisibleBlocks(data)).toBe(true) }) it('should return true when mostUsedNotes has items', () => { const data: DashboardData = { recentNotes: [], mostUsedNotes: [{ id: '1', title: 'Test', content: '', type: 'note' as const, isFavorite: false, isPinned: false, createdAt: '', updatedAt: '', tags: [], usageCount: 5 }], recentCommands: [], recentSnippets: [], activityBasedNotes: [], hasActivity: false, } expect(hasVisibleBlocks(data)).toBe(true) }) it('should return true when recentCommands has items', () => { const data: DashboardData = { recentNotes: [], mostUsedNotes: [], recentCommands: [{ id: '1', title: 'Test', content: '', type: 'command' as const, isFavorite: false, isPinned: false, createdAt: '', updatedAt: '', tags: [] }], recentSnippets: [], activityBasedNotes: [], hasActivity: false, } expect(hasVisibleBlocks(data)).toBe(true) }) it('should return true when recentSnippets has items', () => { const data: DashboardData = { recentNotes: [], mostUsedNotes: [], recentCommands: [], recentSnippets: [{ id: '1', title: 'Test', content: '', type: 'snippet' as const, isFavorite: false, isPinned: false, createdAt: '', updatedAt: '', tags: [] }], activityBasedNotes: [], hasActivity: false, } expect(hasVisibleBlocks(data)).toBe(true) }) it('should return true when activityBasedNotes has items', () => { const data: DashboardData = { recentNotes: [], mostUsedNotes: [], recentCommands: [], recentSnippets: [], activityBasedNotes: [{ id: '1', title: 'Test', content: '', type: 'note' as const, isFavorite: false, isPinned: false, createdAt: '', updatedAt: '', tags: [] }], hasActivity: true, } expect(hasVisibleBlocks(data)).toBe(true) }) it('should return false when all arrays are empty', () => { const data: DashboardData = { recentNotes: [], mostUsedNotes: [], recentCommands: [], recentSnippets: [], activityBasedNotes: [], hasActivity: false, } expect(hasVisibleBlocks(data)).toBe(false) }) }) })