返回 oh-my-ppt
session-thumbnail.test.ts
根目录 / tests / unit / session / session-thumbnail.test.ts
1 import { afterEach, describe, expect, it, vi } from 'vitest'
2
3 const state = vi.hoisted(() => ({
4 getFreshHtmlThumbnailPaths: vi.fn(),
5 enqueueHtmlThumbnails: vi.fn()
6 }))
7
8 vi.mock('../../../src/main/io/thumbnails/html-thumbnail-service', () => ({
9 getFreshHtmlThumbnailPaths: state.getFreshHtmlThumbnailPaths,
10 enqueueHtmlThumbnails: state.enqueueHtmlThumbnails
11 }))
12
13 describe('session first page thumbnails', () => {
14 afterEach(() => {
15 vi.clearAllMocks()
16 })
17
18 it('batches thumbnail lookups for many sessions in one service call', async () => {
19 state.getFreshHtmlThumbnailPaths.mockResolvedValue(new Map([['session-1', '/cache/1.png']]))
20
21 const { getSessionFirstPageThumbnails } = await import(
22 '../../../src/main/session/session-thumbnail'
23 )
24 const result = await getSessionFirstPageThumbnails([
25 { sessionId: 'session-1', pageId: 'p-1', sourcePath: '/tmp/page-1.html' },
26 { sessionId: 'session-2', sourcePath: null },
27 { sessionId: ' ', sourcePath: '/tmp/page-2.html' }
28 ])
29
30 expect(result.get('session-1')).toBe('/cache/1.png')
31 expect(state.getFreshHtmlThumbnailPaths).toHaveBeenCalledWith([
32 {
33 resourceType: 'session',
34 resourceId: 'session-1',
35 variant: 'first-page',
36 sourcePath: '/tmp/page-1.html',
37 pageId: 'p-1'
38 }
39 ])
40 })
41
42 it('enqueues only the sessions whose fresh thumbnail is missing', async () => {
43 state.getFreshHtmlThumbnailPaths.mockResolvedValue(new Map([['session-1', '/cache/1.png']]))
44 state.enqueueHtmlThumbnails.mockResolvedValue([])
45
46 const { warmSessionFirstPageThumbnails } = await import(
47 '../../../src/main/session/session-thumbnail'
48 )
49 const result = await warmSessionFirstPageThumbnails([
50 { sessionId: 'session-1', pageId: 'p-1', sourcePath: '/tmp/page-1.html' },
51 { sessionId: 'session-2', pageId: 'p-2', sourcePath: '/tmp/page-2.html' },
52 { sessionId: ' ', sourcePath: '/tmp/page-3.html' }
53 ])
54
55 expect(result.get('session-1')).toBe('/cache/1.png')
56 expect(result.has('session-2')).toBe(false)
57 expect(state.enqueueHtmlThumbnails).toHaveBeenCalledTimes(1)
58 expect(state.enqueueHtmlThumbnails).toHaveBeenCalledWith([
59 {
60 resourceType: 'session',
61 resourceId: 'session-2',
62 variant: 'first-page',
63 sourcePath: '/tmp/page-2.html',
64 pageId: 'p-2'
65 }
66 ])
67 })
68
69 it('does not enqueue anything when every thumbnail is already fresh', async () => {
70 state.getFreshHtmlThumbnailPaths.mockResolvedValue(
71 new Map([
72 ['session-1', '/cache/1.png'],
73 ['session-2', '/cache/2.png']
74 ])
75 )
76
77 const { warmSessionFirstPageThumbnails } = await import(
78 '../../../src/main/session/session-thumbnail'
79 )
80 const result = await warmSessionFirstPageThumbnails([
81 { sessionId: 'session-1', sourcePath: '/tmp/page-1.html' },
82 { sessionId: 'session-2', sourcePath: '/tmp/page-2.html' }
83 ])
84
85 expect(result.size).toBe(2)
86 expect(state.enqueueHtmlThumbnails).not.toHaveBeenCalled()
87 })
88
89 it('returns an empty result without enqueueing when the cache lookup fails', async () => {
90 state.getFreshHtmlThumbnailPaths.mockRejectedValue(new Error('database unavailable'))
91 const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined)
92
93 const { warmSessionFirstPageThumbnails } = await import(
94 '../../../src/main/session/session-thumbnail'
95 )
96 const result = await warmSessionFirstPageThumbnails([
97 { sessionId: 'session-1', pageId: 'p-1', sourcePath: '/tmp/page-1.html' }
98 ])
99
100 expect(result.size).toBe(0)
101 expect(state.enqueueHtmlThumbnails).not.toHaveBeenCalled()
102 expect(warn).toHaveBeenCalledWith(
103 '[session-thumbnail] fresh thumbnail lookup failed',
104 expect.any(Error)
105 )
106 })
107 })
108
108 lines TYPESCRIPT