File size: 2,230 Bytes
68722e4
5fe2e71
68722e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5fe2e71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cancelJob, generateAnimation, getJobStatus } from './api'
import { setCurrentLocale } from '../../shared/i18n/runtime'

describe('api error parsing', () => {
  afterEach(() => {
    vi.restoreAllMocks()
    setCurrentLocale('en-US')
  })

  it('falls back to a stable message when job status returns an empty error body', async () => {
    vi.stubGlobal('fetch', vi.fn(async () => new Response('', { status: 500 })))

    await expect(getJobStatus('job-1')).rejects.toThrow('Failed to fetch job status')
  })

  it('falls back to a stable message when cancel returns invalid json', async () => {
    setCurrentLocale('zh-CN')
    vi.stubGlobal('fetch', vi.fn(async () => new Response('oops', { status: 500 })))

    await expect(cancelJob('job-2')).rejects.toThrow('取消任务失败')
  })
})

describe('narration request pass-through', () => {
  afterEach(() => {
    vi.unstubAllGlobals()
    localStorage.clear()
  })

  it('sends the full videoConfig narration settings on generate', async () => {
    localStorage.setItem('manimcat_settings', JSON.stringify({
      video: {
        quality: 'medium',
        frameRate: 60,
        timeout: 1200,
        narration: { enabled: true, voice: 'zh-CN-YunxiNeural', rate: '-10%' },
      },
    }))
    localStorage.setItem('manimcat_settings_version', '8')

    const fetchMock = vi.fn(async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
      expect(String(input)).toBe('/api/generate')
      expect(init?.method).toBe('POST')
      return new Response(JSON.stringify({
        success: true,
        jobId: 'job-narration',
        message: 'ok',
        status: 'queued',
        submittedAt: '2026-10-27T00:00:00.000Z',
      }), { status: 200, headers: { 'Content-Type': 'application/json' } })
    })
    vi.stubGlobal('fetch', fetchMock)

    await generateAnimation({ concept: 'narration test', outputMode: 'video' })

    const body = JSON.parse(String(fetchMock.mock.calls[0][1]?.body))
    expect(body.videoConfig).toMatchObject({
      quality: 'medium',
      frameRate: 60,
      narration: { enabled: true, voice: 'zh-CN-YunxiNeural', rate: '-10%' },
    })
  })
})