1+ import { DeepSeekHandler } from '../deepseek'
2+ import { ApiHandlerOptions } from '../../../shared/api'
3+ import OpenAI from 'openai'
4+ import { Anthropic } from '@anthropic-ai/sdk'
5+
6+ // Mock dependencies
7+ jest . mock ( 'openai' )
8+
9+ describe ( 'DeepSeekHandler' , ( ) => {
10+
11+ const mockOptions : ApiHandlerOptions = {
12+ deepSeekApiKey : 'test-key' ,
13+ deepSeekModelId : 'deepseek-chat' ,
14+ }
15+
16+ beforeEach ( ( ) => {
17+ jest . clearAllMocks ( )
18+ } )
19+
20+ test ( 'constructor initializes with correct options' , ( ) => {
21+ const handler = new DeepSeekHandler ( mockOptions )
22+ expect ( handler ) . toBeInstanceOf ( DeepSeekHandler )
23+ expect ( OpenAI ) . toHaveBeenCalledWith ( {
24+ baseURL : 'https://api.deepseek.com/v1' ,
25+ apiKey : mockOptions . deepSeekApiKey ,
26+ } )
27+ } )
28+
29+ test ( 'getModel returns correct model info' , ( ) => {
30+ const handler = new DeepSeekHandler ( mockOptions )
31+ const result = handler . getModel ( )
32+
33+ expect ( result ) . toEqual ( {
34+ id : mockOptions . deepSeekModelId ,
35+ info : expect . objectContaining ( {
36+ maxTokens : 8192 ,
37+ contextWindow : 64000 ,
38+ supportsPromptCache : false ,
39+ supportsImages : false ,
40+ inputPrice : 0.014 ,
41+ outputPrice : 0.28 ,
42+ } )
43+ } )
44+ } )
45+
46+ test ( 'getModel returns default model info when no model specified' , ( ) => {
47+ const handler = new DeepSeekHandler ( { deepSeekApiKey : 'test-key' } )
48+ const result = handler . getModel ( )
49+
50+ expect ( result . id ) . toBe ( 'deepseek-chat' )
51+ expect ( result . info . maxTokens ) . toBe ( 8192 )
52+ } )
53+
54+ test ( 'createMessage handles string content correctly' , async ( ) => {
55+ const handler = new DeepSeekHandler ( mockOptions )
56+ const mockStream = {
57+ async * [ Symbol . asyncIterator ] ( ) {
58+ yield {
59+ choices : [ {
60+ delta : {
61+ content : 'test response'
62+ }
63+ } ]
64+ }
65+ }
66+ }
67+
68+ const mockCreate = jest . fn ( ) . mockResolvedValue ( mockStream )
69+ ; ( OpenAI as jest . MockedClass < typeof OpenAI > ) . prototype . chat = {
70+ completions : { create : mockCreate }
71+ } as any
72+
73+ const systemPrompt = 'test system prompt'
74+ const messages : Anthropic . Messages . MessageParam [ ] = [
75+ { role : 'user' , content : 'test message' }
76+ ]
77+
78+ const generator = handler . createMessage ( systemPrompt , messages )
79+ const chunks = [ ]
80+
81+ for await ( const chunk of generator ) {
82+ chunks . push ( chunk )
83+ }
84+
85+ expect ( chunks ) . toHaveLength ( 1 )
86+ expect ( chunks [ 0 ] ) . toEqual ( {
87+ type : 'text' ,
88+ text : 'test response'
89+ } )
90+
91+ expect ( mockCreate ) . toHaveBeenCalledWith ( expect . objectContaining ( {
92+ model : mockOptions . deepSeekModelId ,
93+ messages : [
94+ { role : 'system' , content : systemPrompt } ,
95+ { role : 'user' , content : 'test message' }
96+ ] ,
97+ temperature : 0 ,
98+ stream : true ,
99+ max_tokens : 8192 ,
100+ stream_options : { include_usage : true }
101+ } ) )
102+ } )
103+
104+ test ( 'createMessage handles complex content correctly' , async ( ) => {
105+ const handler = new DeepSeekHandler ( mockOptions )
106+ const mockStream = {
107+ async * [ Symbol . asyncIterator ] ( ) {
108+ yield {
109+ choices : [ {
110+ delta : {
111+ content : 'test response'
112+ }
113+ } ]
114+ }
115+ }
116+ }
117+
118+ const mockCreate = jest . fn ( ) . mockResolvedValue ( mockStream )
119+ ; ( OpenAI as jest . MockedClass < typeof OpenAI > ) . prototype . chat = {
120+ completions : { create : mockCreate }
121+ } as any
122+
123+ const systemPrompt = 'test system prompt'
124+ const messages : Anthropic . Messages . MessageParam [ ] = [
125+ {
126+ role : 'user' ,
127+ content : [
128+ { type : 'text' , text : 'part 1' } ,
129+ { type : 'text' , text : 'part 2' }
130+ ]
131+ }
132+ ]
133+
134+ const generator = handler . createMessage ( systemPrompt , messages )
135+ await generator . next ( )
136+
137+ expect ( mockCreate ) . toHaveBeenCalledWith ( expect . objectContaining ( {
138+ messages : [
139+ { role : 'system' , content : systemPrompt } ,
140+ {
141+ role : 'user' ,
142+ content : [
143+ { type : 'text' , text : 'part 1' } ,
144+ { type : 'text' , text : 'part 2' }
145+ ]
146+ }
147+ ]
148+ } ) )
149+ } )
150+
151+ test ( 'createMessage handles API errors' , async ( ) => {
152+ const handler = new DeepSeekHandler ( mockOptions )
153+ const mockStream = {
154+ async * [ Symbol . asyncIterator ] ( ) {
155+ throw new Error ( 'API Error' )
156+ }
157+ }
158+
159+ const mockCreate = jest . fn ( ) . mockResolvedValue ( mockStream )
160+ ; ( OpenAI as jest . MockedClass < typeof OpenAI > ) . prototype . chat = {
161+ completions : { create : mockCreate }
162+ } as any
163+
164+ const generator = handler . createMessage ( 'test' , [ ] )
165+ await expect ( generator . next ( ) ) . rejects . toThrow ( 'API Error' )
166+ } )
167+ } )
0 commit comments