返回 oh-my-ppt
edit-job-finalization.test.ts
根目录 / tests / unit / edit-jobs / edit-job-finalization.test.ts
1 import { describe, expect, it, vi } from 'vitest'
2
3 const { finalizeGenerationFailureMock, logErrorMock } = vi.hoisted(() => ({
4 finalizeGenerationFailureMock: vi.fn(),
5 logErrorMock: vi.fn()
6 }))
7
8 vi.mock('electron-log/main.js', () => ({ default: { error: logErrorMock } }))
9 vi.mock('../../../src/main/generation/finalization', () => ({
10 finalizeGenerationFailure: finalizeGenerationFailureMock,
11 resolveGenerationFailureSessionStatus: () => 'failed'
12 }))
13
14 import {
15 settleEditJobFailure,
16 settleEditJobSuccess
17 } from '../../../src/main/edit-jobs/edit-job-finalization'
18
19 describe('edit job terminal finalization', () => {
20 it('persists a successful edit job before publishing its terminal event', async () => {
21 const updateSessionJobStatus = vi.fn().mockResolvedValue(undefined)
22 const emitRuntimeJobTerminal = vi.fn()
23
24 await settleEditJobSuccess({
25 ctx: { db: { updateSessionJobStatus }, emitRuntimeJobTerminal } as never,
26 context: { sessionId: 'session-1', runId: 'run-1' } as never
27 })
28
29 expect(updateSessionJobStatus).toHaveBeenCalledWith('run-1', 'finished')
30 expect(emitRuntimeJobTerminal).toHaveBeenCalledWith({
31 sessionId: 'session-1',
32 jobId: 'run-1',
33 domain: 'edit',
34 status: 'completed'
35 })
36 expect(updateSessionJobStatus.mock.invocationCallOrder[0]).toBeLessThan(
37 emitRuntimeJobTerminal.mock.invocationCallOrder[0]
38 )
39 })
40
41 it('persists a fallback domain terminal state before ending an edit job', async () => {
42 const updateSessionJobStatus = vi.fn().mockResolvedValue(undefined)
43 const updateGenerationRunStatus = vi.fn().mockResolvedValue(undefined)
44 const updateSessionStatus = vi.fn().mockResolvedValue(undefined)
45 const emitGenerateChunk = vi.fn()
46 const emitRuntimeJobTerminal = vi.fn()
47 finalizeGenerationFailureMock.mockRejectedValueOnce(new Error('database temporarily unavailable'))
48
49 await settleEditJobFailure({
50 ctx: {
51 db: { updateSessionJobStatus, updateGenerationRunStatus, updateSessionStatus },
52 emitGenerateChunk,
53 emitRuntimeJobTerminal
54 } as never,
55 context: { sessionId: 'session-1', runId: 'run-1' } as never,
56 error: new Error('edit failed'),
57 cancelled: false,
58 hasPersistedJob: true,
59 logPrefix: '[test]'
60 })
61
62 expect(logErrorMock).toHaveBeenCalledOnce()
63 expect(updateGenerationRunStatus).toHaveBeenCalledWith('run-1', 'failed', 'edit failed')
64 expect(updateSessionStatus).toHaveBeenCalledWith('session-1', 'failed')
65 expect(emitGenerateChunk).toHaveBeenCalledWith('session-1', {
66 type: 'run_error',
67 payload: { runId: 'run-1', message: 'edit failed', cancelled: false }
68 })
69 expect(updateSessionJobStatus).toHaveBeenCalledWith('run-1', 'finished', undefined)
70 expect(emitRuntimeJobTerminal).toHaveBeenCalledWith({
71 sessionId: 'session-1',
72 jobId: 'run-1',
73 domain: 'edit',
74 status: 'failed',
75 errorCode: 'edit_failed',
76 errorMessage: 'edit failed'
77 })
78 expect(updateSessionJobStatus.mock.invocationCallOrder[0]).toBeLessThan(
79 emitRuntimeJobTerminal.mock.invocationCallOrder[0]
80 )
81 })
82
83 it('keeps an edit job recoverable when neither finalization nor fallback can settle it', async () => {
84 const updateSessionJobStatus = vi.fn().mockResolvedValue(undefined)
85 const updateGenerationRunStatus = vi.fn().mockResolvedValue(undefined)
86 const updateSessionStatus = vi.fn().mockRejectedValue(new Error('session database unavailable'))
87 const emitGenerateChunk = vi.fn()
88 const emitRuntimeJobTerminal = vi.fn()
89 finalizeGenerationFailureMock.mockRejectedValueOnce(new Error('database temporarily unavailable'))
90
91 await settleEditJobFailure({
92 ctx: {
93 db: { updateSessionJobStatus, updateGenerationRunStatus, updateSessionStatus },
94 emitGenerateChunk,
95 emitRuntimeJobTerminal
96 } as never,
97 context: { sessionId: 'session-1', runId: 'run-1' } as never,
98 error: new Error('edit failed'),
99 cancelled: false,
100 hasPersistedJob: true,
101 logPrefix: '[test]'
102 })
103
104 expect(updateGenerationRunStatus).toHaveBeenCalledWith('run-1', 'failed', 'edit failed')
105 expect(updateSessionStatus).toHaveBeenCalledWith('session-1', 'failed')
106 expect(updateSessionJobStatus).not.toHaveBeenCalled()
107 expect(emitGenerateChunk).not.toHaveBeenCalled()
108 expect(emitRuntimeJobTerminal).not.toHaveBeenCalled()
109 })
110 })
111
111 lines TYPESCRIPT