import { describe, it, expect, vi, beforeEach } from 'vitest'; vi.mock('../../prisma.js', () => ({ prisma: { board: { findMany: vi.fn(), findUnique: vi.fn(), findFirst: vi.fn(), create: vi.fn(), update: vi.fn(), updateMany: vi.fn(), delete: vi.fn() }, section: { findUnique: vi.fn(), findFirst: vi.fn(), create: vi.fn(), update: vi.fn(), delete: vi.fn() }, widget: { findUnique: vi.fn(), findFirst: vi.fn(), create: vi.fn(), update: vi.fn(), delete: vi.fn() } } })); import { prisma } from '../../prisma.js'; import * as boardService from '../boardService.js'; const mockBoard = prisma.board as unknown as Record>; const mockSection = prisma.section as unknown as Record>; const mockWidget = prisma.widget as unknown as Record>; describe('boardService', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('findAllBoards', () => { it('returns all boards', async () => { const boards = [{ id: '1', name: 'Main', _count: { sections: 2 } }]; mockBoard.findMany.mockResolvedValue(boards); const result = await boardService.findAllBoards(); expect(result).toEqual(boards); }); }); describe('findBoardById', () => { it('returns board with sections and widgets', async () => { const board = { id: '1', name: 'Main', sections: [] }; mockBoard.findUnique.mockResolvedValue(board); const result = await boardService.findBoardById('1'); expect(result.name).toBe('Main'); }); it('throws when not found', async () => { mockBoard.findUnique.mockResolvedValue(null); await expect(boardService.findBoardById('missing')).rejects.toThrow('Board not found'); }); }); describe('createBoard', () => { it('creates a board', async () => { mockBoard.create.mockResolvedValue({ id: '1', name: 'New Board' }); const result = await boardService.createBoard({ name: 'New Board' }); expect(result.name).toBe('New Board'); }); it('unsets other defaults when creating a default board', async () => { mockBoard.updateMany.mockResolvedValue({ count: 1 }); mockBoard.create.mockResolvedValue({ id: '1', name: 'Default', isDefault: true }); await boardService.createBoard({ name: 'Default', isDefault: true }); expect(mockBoard.updateMany).toHaveBeenCalledWith({ where: { isDefault: true }, data: { isDefault: false } }); }); }); describe('updateBoard', () => { it('updates board fields', async () => { mockBoard.findUnique.mockResolvedValue({ id: '1' }); mockBoard.update.mockResolvedValue({ id: '1', name: 'Updated' }); const result = await boardService.updateBoard('1', { name: 'Updated' }); expect(result.name).toBe('Updated'); }); }); describe('removeBoard', () => { it('deletes a board', async () => { mockBoard.findUnique.mockResolvedValue({ id: '1' }); mockBoard.delete.mockResolvedValue({}); await boardService.removeBoard('1'); expect(mockBoard.delete).toHaveBeenCalledWith({ where: { id: '1' } }); }); }); describe('createSection', () => { it('creates a section with auto-calculated order', async () => { mockSection.findFirst.mockResolvedValue({ order: 2 }); mockSection.create.mockResolvedValue({ id: 's1', title: 'Media', order: 3 }); const result = await boardService.createSection({ boardId: 'b1', title: 'Media' }); expect(result.order).toBe(3); }); it('starts order at 0 for first section', async () => { mockSection.findFirst.mockResolvedValue(null); mockSection.create.mockResolvedValue({ id: 's1', title: 'First', order: 0 }); await boardService.createSection({ boardId: 'b1', title: 'First' }); expect(mockSection.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ order: 0 }) }) ); }); }); describe('createWidget', () => { it('creates a widget', async () => { mockWidget.findFirst.mockResolvedValue(null); mockWidget.create.mockResolvedValue({ id: 'w1', type: 'app', order: 0 }); const result = await boardService.createWidget({ sectionId: 's1', type: 'app', config: JSON.stringify({ appId: 'test-app-1' }) }); expect(result.type).toBe('app'); }); }); describe('removeWidget', () => { it('deletes a widget', async () => { mockWidget.findUnique.mockResolvedValue({ id: 'w1' }); mockWidget.delete.mockResolvedValue({}); await boardService.removeWidget('w1'); expect(mockWidget.delete).toHaveBeenCalledWith({ where: { id: 'w1' } }); }); }); });