返回 AiToEarn
relay.service.spec.ts
根目录 / project / aitoearn-backend / apps / aitoearn-ai / src / core / ai / libs / relay / relay.service.spec.ts
1 import type { AiAvailabilityService } from '../../../ai-availability'
2 import { AppException, ResponseCode } from '@yikart/common'
3 import { beforeEach, describe, expect, it, vi } from 'vitest'
4 import { RelayConfig } from './relay.config'
5 import { RelayLibService } from './relay.service'
6
7 vi.mock('../../../ai-availability', () => ({
8 AiAvailabilityService: class AiAvailabilityService {},
9 }))
10
11 describe('relayLibService', () => {
12 let service: RelayLibService
13 let httpClient: {
14 post: ReturnType<typeof vi.fn>
15 get: ReturnType<typeof vi.fn>
16 }
17
18 beforeEach(() => {
19 service = new RelayLibService(
20 { url: 'https://relay.example.com', apiKey: 'relay-key', timeout: 1000 } as RelayConfig,
21 { execute: vi.fn((_context, fn) => fn()) } as unknown as AiAvailabilityService,
22 )
23 httpClient = {
24 post: vi.fn(),
25 get: vi.fn(),
26 }
27 Object.assign(service as unknown as { httpClient: typeof httpClient }, { httpClient })
28 })
29
30 function normalizeResponse(data: unknown) {
31 return (service as unknown as {
32 normalizeResponse: (response: { data: unknown }) => { data: unknown }
33 }).normalizeResponse({ data }).data
34 }
35
36 it('returns relay video task response when creating relay video tasks', async () => {
37 httpClient.post.mockResolvedValue({
38 data: { id: 'remote-task-1', status: 'generating' },
39 })
40
41 await expect(service.createVideo({
42 model: 'relay-video-model',
43 prompt: 'video',
44 })).resolves.toEqual({ id: 'remote-task-1', status: 'generating' })
45 })
46
47 it('unwraps common and legacy data-only responses in response interceptor', () => {
48 expect(normalizeResponse({
49 code: ResponseCode.Success,
50 message: 'ok',
51 data: { id: 'remote-task-1', status: 'generating' },
52 })).toEqual({ id: 'remote-task-1', status: 'generating' })
53 expect(normalizeResponse({
54 data: {
55 id: 'remote-task-2',
56 status: 'generating',
57 },
58 })).toEqual({ id: 'remote-task-2', status: 'generating' })
59 })
60
61 it('returns relay video task status when polling relay video tasks', async () => {
62 httpClient.get.mockResolvedValue({
63 data: { id: 'remote-task-1', status: 'success', videoUrl: 'videos/out.mp4' },
64 })
65
66 await expect(service.getVideo('remote-task-1')).resolves.toEqual({
67 id: 'remote-task-1',
68 status: 'success',
69 videoUrl: 'videos/out.mp4',
70 })
71 })
72
73 it('throws AppException with original response code when common response code is not success', () => {
74 expect(() => normalizeResponse({
75 code: ResponseCode.InvalidModel,
76 message: 'upstream rejected image url',
77 data: null,
78 })).toThrow(AppException)
79
80 try {
81 normalizeResponse({
82 code: ResponseCode.InvalidModel,
83 message: 'upstream rejected image url',
84 data: null,
85 })
86 }
87 catch (error) {
88 expect(error).toBeInstanceOf(AppException)
89 expect((error as AppException).code).toBe(ResponseCode.InvalidModel)
90 }
91 })
92
93 it('throws AiCallFailed when relay video submit response has no id', async () => {
94 httpClient.post.mockResolvedValue({
95 data: { status: 'failed', error: 'invalid image url' },
96 })
97
98 await expect(service.createVideo({
99 model: 'relay-video-model',
100 prompt: 'video',
101 })).rejects.toMatchObject({ code: ResponseCode.AiCallFailed })
102 })
103 })
104
104 lines TYPESCRIPT