/** * chapter-nav 单元测试 * * 覆盖: * 1. 第一个章节:无 prev,next 为第二节 * 2. 中间章节:prev/next 都有 * 3. 最后一章:有 prev,无 next * 4. 章节不在列表中:返 0/nav 全部 null * 5. bookId=0 边界 * 6. DB 异常:返回零值 nav,不抛 */ import { describe, it, expect, vi, beforeEach } from 'vitest'; const mocks = vi.hoisted(() => ({ findMany: vi.fn(), })); vi.mock('@/models', () => ({ prisma: { bookChapter: { findMany: mocks.findMany, }, }, })); import { getChapterNav } from '@/modules/book-generator/chapter-nav'; describe('chapter-nav', () => { beforeEach(() => { vi.clearAllMocks(); }); it('第一章:prev=null, next=2', async () => { mocks.findMany.mockResolvedValue([{ id: 100 }, { id: 101 }, { id: 102 }]); const nav = await getChapterNav(1, 100); expect(nav.chapter_index).toBe(1); expect(nav.total_chapters).toBe(3); expect(nav.prev_chapter_id).toBeNull(); expect(nav.next_chapter_id).toBe(101); }); it('中间章:prev/next 都有', async () => { mocks.findMany.mockResolvedValue([{ id: 100 }, { id: 101 }, { id: 102 }]); const nav = await getChapterNav(1, 101); expect(nav.chapter_index).toBe(2); expect(nav.prev_chapter_id).toBe(100); expect(nav.next_chapter_id).toBe(102); }); it('最后一章:next=null', async () => { mocks.findMany.mockResolvedValue([{ id: 100 }, { id: 101 }, { id: 102 }]); const nav = await getChapterNav(1, 102); expect(nav.chapter_index).toBe(3); expect(nav.prev_chapter_id).toBe(101); expect(nav.next_chapter_id).toBeNull(); }); it('章节不在列表中:全部 nav null', async () => { mocks.findMany.mockResolvedValue([{ id: 100 }, { id: 101 }]); const nav = await getChapterNav(1, 999); expect(nav.chapter_index).toBe(0); expect(nav.total_chapters).toBe(2); expect(nav.prev_chapter_id).toBeNull(); expect(nav.next_chapter_id).toBeNull(); }); it('bookId/chapterId 非法:返零值', async () => { const nav1 = await getChapterNav(0, 100); expect(nav1).toEqual({ chapter_index: 0, total_chapters: 0, prev_chapter_id: null, next_chapter_id: null }); const nav2 = await getChapterNav(1, 0); expect(nav2).toEqual({ chapter_index: 0, total_chapters: 0, prev_chapter_id: null, next_chapter_id: null }); }); it('DB 异常:返回零值 nav,不抛', async () => { mocks.findMany.mockRejectedValue(new Error('DB down')); const nav = await getChapterNav(1, 100); expect(nav).toEqual({ chapter_index: 0, total_chapters: 0, prev_chapter_id: null, next_chapter_id: null }); }); });