import { createVersion, getVersions, getVersion, restoreVersion } from '@/lib/versions' jest.mock('@/lib/prisma', () => ({ prisma: { note: { findUnique: jest.fn(), update: jest.fn() }, noteVersion: { create: jest.fn(), findMany: jest.fn(), findUnique: jest.fn() }, }, })) import { prisma } from '@/lib/prisma' import { NotFoundError } from '@/lib/errors' describe('versions.ts', () => { beforeEach(() => { jest.clearAllMocks() }) describe('createVersion', () => { it('creates a version with correct noteId, title, content', async () => { const mockNote = { id: 'note-1', title: 'Test Title', content: 'Test Content' } const mockVersion = { id: 'version-1', noteId: 'note-1', title: 'Test Title', content: 'Test Content', createdAt: new Date() } ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(mockNote) ;(prisma.noteVersion.create as jest.Mock).mockResolvedValue(mockVersion) const result = await createVersion('note-1') expect(result).toEqual(mockVersion) expect(prisma.note.findUnique).toHaveBeenCalledWith({ where: { id: 'note-1' }, select: { id: true, title: true, content: true }, }) expect(prisma.noteVersion.create).toHaveBeenCalledWith({ data: { noteId: 'note-1', title: 'Test Title', content: 'Test Content', }, }) }) it('throws NotFoundError if note does not exist', async () => { ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(null) await expect(createVersion('note-1')).rejects.toThrow(NotFoundError) }) }) describe('getVersions', () => { it('returns all versions for a note ordered by createdAt desc', async () => { const mockNote = { id: 'note-1' } const mockVersions = [ { id: 'version-2', noteId: 'note-1', title: 'Title 2', content: 'Content 2', createdAt: new Date('2024-01-02') }, { id: 'version-1', noteId: 'note-1', title: 'Title 1', content: 'Content 1', createdAt: new Date('2024-01-01') }, ] ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(mockNote) ;(prisma.noteVersion.findMany as jest.Mock).mockResolvedValue(mockVersions) const result = await getVersions('note-1') expect(result).toEqual(mockVersions) expect(prisma.note.findUnique).toHaveBeenCalledWith({ where: { id: 'note-1' } }) expect(prisma.noteVersion.findMany).toHaveBeenCalledWith({ where: { noteId: 'note-1' }, orderBy: { createdAt: 'desc' }, select: { id: true, noteId: true, title: true, content: true, createdAt: true, }, }) }) it('throws NotFoundError if note does not exist', async () => { ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(null) await expect(getVersions('note-1')).rejects.toThrow(NotFoundError) }) }) describe('getVersion', () => { it('returns version by ID', async () => { const mockVersion = { id: 'version-1', noteId: 'note-1', title: 'Title', content: 'Content', createdAt: new Date() } ;(prisma.noteVersion.findUnique as jest.Mock).mockResolvedValue(mockVersion) const result = await getVersion('version-1') expect(result).toEqual(mockVersion) expect(prisma.noteVersion.findUnique).toHaveBeenCalledWith({ where: { id: 'version-1' } }) }) it('throws NotFoundError if version does not exist', async () => { ;(prisma.noteVersion.findUnique as jest.Mock).mockResolvedValue(null) await expect(getVersion('version-1')).rejects.toThrow(NotFoundError) }) }) describe('restoreVersion', () => { it('updates note title and content from version', async () => { const mockNote = { id: 'note-1', title: 'Old Title', content: 'Old Content' } const mockVersion = { id: 'version-1', noteId: 'note-1', title: 'Old Title', content: 'Old Content', createdAt: new Date() } const updatedNote = { id: 'note-1', title: 'Old Title', content: 'Old Content', updatedAt: new Date() } ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(mockNote) ;(prisma.noteVersion.findUnique as jest.Mock).mockResolvedValue(mockVersion) ;(prisma.note.update as jest.Mock).mockResolvedValue(updatedNote) const result = await restoreVersion('note-1', 'version-1') expect(result).toEqual(updatedNote) expect(prisma.note.update).toHaveBeenCalledWith({ where: { id: 'note-1' }, data: { title: 'Old Title', content: 'Old Content', updatedAt: expect.any(Date), }, select: { id: true, title: true, content: true, updatedAt: true, }, }) }) it('updates note updatedAt timestamp', async () => { const mockNote = { id: 'note-1', title: 'Title', content: 'Content' } const mockVersion = { id: 'version-1', noteId: 'note-1', title: 'Title', content: 'Content', createdAt: new Date() } const beforeUpdate = new Date('2024-01-01') const afterUpdate = new Date('2024-01-02') ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(mockNote) ;(prisma.noteVersion.findUnique as jest.Mock).mockResolvedValue(mockVersion) ;(prisma.note.update as jest.Mock).mockResolvedValue({ id: 'note-1', title: 'Title', content: 'Content', updatedAt: afterUpdate }) const result = await restoreVersion('note-1', 'version-1') expect(result.updatedAt).toEqual(afterUpdate) }) it('throws NotFoundError if note does not exist', async () => { ;(prisma.note.findUnique as jest.Mock).mockResolvedValue(null) await expect(restoreVersion('note-1', 'version-1')).rejects.toThrow(NotFoundError) }) it('throws NotFoundError if version does not exist', async () => { ;(prisma.note.findUnique as jest.Mock).mockResolvedValue({ id: 'note-1' }) ;(prisma.noteVersion.findUnique as jest.Mock).mockResolvedValue(null) await expect(restoreVersion('note-1', 'version-1')).rejects.toThrow(NotFoundError) }) it('throws NotFoundError if version does not belong to note', async () => { ;(prisma.note.findUnique as jest.Mock).mockResolvedValue({ id: 'note-1' }) ;(prisma.noteVersion.findUnique as jest.Mock).mockResolvedValue({ id: 'version-1', noteId: 'note-2' }) await expect(restoreVersion('note-1', 'version-1')).rejects.toThrow(NotFoundError) }) }) })