1
+ import pytest
2
+ from fastapi .testclient import TestClient
3
+ from unittest .mock import patch , MagicMock
4
+
5
+ from openai_api_client .main import app
6
+ from openai_api_client .dependencies .openai import OpenAIService
7
+ from openai_api_client .schemas .openai import OpenAIRequest , OpenAIResponse
8
+ from openai_api_client .services .openai import openai_service
9
+ from openai_api_client .models .user import User
10
+ from openai_api_client .schemas .user import UserCreate
11
+
12
+
13
+ @pytest .fixture
14
+ def client ():
15
+ return TestClient (app )
16
+
17
+
18
+ @pytest .fixture
19
+ def mock_openai ():
20
+ with patch ("openai_api_client.dependencies.openai.openai" ) as mock_openai :
21
+ yield mock_openai
22
+
23
+
24
+ @pytest .fixture
25
+ async def test_user (mock_user_service ):
26
+ user_data = UserCreate (
27
+ username = "testuser" ,
28
+ email = "test@example.com" ,
29
+ password = "testpassword" ,
30
+ )
31
+ user = await mock_user_service .create_user (user_data )
32
+ yield user
33
+ await mock_user_service .delete_user (user .id )
34
+
35
+
36
+ class TestOpenAIRoutes :
37
+ def test_complete_text_success (self , client , mock_openai , test_user ):
38
+ mock_openai .Completion .create .return_value = MagicMock (
39
+ choices = [MagicMock (text = "This is the completed text." )],
40
+ )
41
+ request = OpenAIRequest (text = "This is the prompt." )
42
+ response = client .post (
43
+ "/api/v1/openai/complete" ,
44
+ json = request .dict (),
45
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
46
+ )
47
+ assert response .status_code == 200
48
+ assert response .json () == {"response" : "This is the completed text." }
49
+ mock_openai .Completion .create .assert_called_once_with (
50
+ engine = request .model ,
51
+ prompt = request .text ,
52
+ temperature = request .temperature ,
53
+ max_tokens = request .max_tokens ,
54
+ )
55
+
56
+ def test_complete_text_invalid_model (self , client , mock_openai , test_user ):
57
+ mock_openai .Completion .create .side_effect = openai .error .InvalidRequestError (
58
+ "Invalid model."
59
+ )
60
+ request = OpenAIRequest (text = "This is the prompt." , model = "invalid_model" )
61
+ response = client .post (
62
+ "/api/v1/openai/complete" ,
63
+ json = request .dict (),
64
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
65
+ )
66
+ assert response .status_code == 400
67
+ assert "Invalid request to OpenAI API" in response .json ()["detail" ]
68
+
69
+ def test_complete_text_rate_limit (self , client , mock_openai , test_user ):
70
+ mock_openai .Completion .create .side_effect = openai .error .RateLimitError (
71
+ "Rate limit exceeded."
72
+ )
73
+ request = OpenAIRequest (text = "This is the prompt." )
74
+ response = client .post (
75
+ "/api/v1/openai/complete" ,
76
+ json = request .dict (),
77
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
78
+ )
79
+ assert response .status_code == 429
80
+ assert "OpenAI API rate limit exceeded" in response .json ()["detail" ]
81
+
82
+ def test_complete_text_authentication_error (self , client , mock_openai , test_user ):
83
+ mock_openai .Completion .create .side_effect = openai .error .AuthenticationError (
84
+ "Invalid API key."
85
+ )
86
+ request = OpenAIRequest (text = "This is the prompt." )
87
+ response = client .post (
88
+ "/api/v1/openai/complete" ,
89
+ json = request .dict (),
90
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
91
+ )
92
+ assert response .status_code == 401
93
+ assert "Invalid OpenAI API key" in response .json ()["detail" ]
94
+
95
+ def test_complete_text_timeout_error (self , client , mock_openai , test_user ):
96
+ mock_openai .Completion .create .side_effect = openai .error .TimeoutError (
97
+ "Request timed out."
98
+ )
99
+ request = OpenAIRequest (text = "This is the prompt." )
100
+ response = client .post (
101
+ "/api/v1/openai/complete" ,
102
+ json = request .dict (),
103
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
104
+ )
105
+ assert response .status_code == 504
106
+ assert "Request to OpenAI API timed out" in response .json ()["detail" ]
107
+
108
+ def test_complete_text_connection_error (self , client , mock_openai , test_user ):
109
+ mock_openai .Completion .create .side_effect = openai .error .APIConnectionError (
110
+ "Connection error."
111
+ )
112
+ request = OpenAIRequest (text = "This is the prompt." )
113
+ response = client .post (
114
+ "/api/v1/openai/complete" ,
115
+ json = request .dict (),
116
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
117
+ )
118
+ assert response .status_code == 500
119
+ assert "Error connecting to OpenAI API" in response .json ()["detail" ]
120
+
121
+ def test_complete_text_general_api_error (self , client , mock_openai , test_user ):
122
+ mock_openai .Completion .create .side_effect = openai .error .APIError (
123
+ "General API error."
124
+ )
125
+ request = OpenAIRequest (text = "This is the prompt." )
126
+ response = client .post (
127
+ "/api/v1/openai/complete" ,
128
+ json = request .dict (),
129
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
130
+ )
131
+ assert response .status_code == 500
132
+ assert "Error calling OpenAI API" in response .json ()["detail" ]
133
+
134
+ def test_translate_text_success (self , client , mock_openai , test_user ):
135
+ mock_openai .Translation .create .return_value = MagicMock (
136
+ choices = [MagicMock (text = "This is the translated text." )],
137
+ )
138
+ request = OpenAIRequest (
139
+ text = "This is the text to translate." ,
140
+ source_language = "en" ,
141
+ target_language = "fr" ,
142
+ )
143
+ response = client .post (
144
+ "/api/v1/openai/translate" ,
145
+ json = request .dict (),
146
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
147
+ )
148
+ assert response .status_code == 200
149
+ assert response .json () == {"response" : "This is the translated text." }
150
+ mock_openai .Translation .create .assert_called_once_with (
151
+ model = "gpt-3.5-turbo" ,
152
+ from_language = "en" ,
153
+ to_language = "fr" ,
154
+ text = "This is the text to translate." ,
155
+ )
156
+
157
+ def test_translate_text_invalid_request (self , client , mock_openai , test_user ):
158
+ mock_openai .Translation .create .side_effect = openai .error .InvalidRequestError (
159
+ "Invalid request."
160
+ )
161
+ request = OpenAIRequest (
162
+ text = "This is the text to translate." ,
163
+ source_language = "invalid" ,
164
+ target_language = "fr" ,
165
+ )
166
+ response = client .post (
167
+ "/api/v1/openai/translate" ,
168
+ json = request .dict (),
169
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
170
+ )
171
+ assert response .status_code == 400
172
+ assert "Invalid request to OpenAI API" in response .json ()["detail" ]
173
+
174
+ def test_translate_text_rate_limit (self , client , mock_openai , test_user ):
175
+ mock_openai .Translation .create .side_effect = openai .error .RateLimitError (
176
+ "Rate limit exceeded."
177
+ )
178
+ request = OpenAIRequest (
179
+ text = "This is the text to translate." ,
180
+ source_language = "en" ,
181
+ target_language = "fr" ,
182
+ )
183
+ response = client .post (
184
+ "/api/v1/openai/translate" ,
185
+ json = request .dict (),
186
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
187
+ )
188
+ assert response .status_code == 429
189
+ assert "OpenAI API rate limit exceeded" in response .json ()["detail" ]
190
+
191
+ def test_translate_text_authentication_error (
192
+ self , client , mock_openai , test_user
193
+ ):
194
+ mock_openai .Translation .create .side_effect = openai .error .AuthenticationError (
195
+ "Invalid API key."
196
+ )
197
+ request = OpenAIRequest (
198
+ text = "This is the text to translate." ,
199
+ source_language = "en" ,
200
+ target_language = "fr" ,
201
+ )
202
+ response = client .post (
203
+ "/api/v1/openai/translate" ,
204
+ json = request .dict (),
205
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
206
+ )
207
+ assert response .status_code == 401
208
+ assert "Invalid OpenAI API key" in response .json ()["detail" ]
209
+
210
+ def test_translate_text_timeout_error (self , client , mock_openai , test_user ):
211
+ mock_openai .Translation .create .side_effect = openai .error .TimeoutError (
212
+ "Request timed out."
213
+ )
214
+ request = OpenAIRequest (
215
+ text = "This is the text to translate." ,
216
+ source_language = "en" ,
217
+ target_language = "fr" ,
218
+ )
219
+ response = client .post (
220
+ "/api/v1/openai/translate" ,
221
+ json = request .dict (),
222
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
223
+ )
224
+ assert response .status_code == 504
225
+ assert "Request to OpenAI API timed out" in response .json ()["detail" ]
226
+
227
+ def test_translate_text_connection_error (self , client , mock_openai , test_user ):
228
+ mock_openai .Translation .create .side_effect = openai .error .APIConnectionError (
229
+ "Connection error."
230
+ )
231
+ request = OpenAIRequest (
232
+ text = "This is the text to translate." ,
233
+ source_language = "en" ,
234
+ target_language = "fr" ,
235
+ )
236
+ response = client .post (
237
+ "/api/v1/openai/translate" ,
238
+ json = request .dict (),
239
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
240
+ )
241
+ assert response .status_code == 500
242
+ assert "Error connecting to OpenAI API" in response .json ()["detail" ]
243
+
244
+ def test_translate_text_general_api_error (self , client , mock_openai , test_user ):
245
+ mock_openai .Translation .create .side_effect = openai .error .APIError (
246
+ "General API error."
247
+ )
248
+ request = OpenAIRequest (
249
+ text = "This is the text to translate." ,
250
+ source_language = "en" ,
251
+ target_language = "fr" ,
252
+ )
253
+ response = client .post (
254
+ "/api/v1/openai/translate" ,
255
+ json = request .dict (),
256
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
257
+ )
258
+ assert response .status_code == 500
259
+ assert "Error calling OpenAI API" in response .json ()["detail" ]
260
+
261
+ def test_summarize_text_success (self , client , mock_openai , test_user ):
262
+ mock_openai .Completion .create .return_value = MagicMock (
263
+ choices = [MagicMock (text = "This is the summarized text." )],
264
+ )
265
+ request = OpenAIRequest (text = "This is the text to summarize." )
266
+ response = client .post (
267
+ "/api/v1/openai/summarize" ,
268
+ json = request .dict (),
269
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
270
+ )
271
+ assert response .status_code == 200
272
+ assert response .json () == {"response" : "This is the summarized text." }
273
+ mock_openai .Completion .create .assert_called_once_with (
274
+ engine = request .model ,
275
+ prompt = f"Summarize the following text:\n \n { request .text } " ,
276
+ temperature = 0.7 ,
277
+ max_tokens = 256 ,
278
+ )
279
+
280
+ def test_summarize_text_invalid_request (self , client , mock_openai , test_user ):
281
+ mock_openai .Completion .create .side_effect = openai .error .InvalidRequestError (
282
+ "Invalid request."
283
+ )
284
+ request = OpenAIRequest (text = "This is the text to summarize." )
285
+ response = client .post (
286
+ "/api/v1/openai/summarize" ,
287
+ json = request .dict (),
288
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
289
+ )
290
+ assert response .status_code == 400
291
+ assert "Invalid request to OpenAI API" in response .json ()["detail" ]
292
+
293
+ def test_summarize_text_rate_limit (self , client , mock_openai , test_user ):
294
+ mock_openai .Completion .create .side_effect = openai .error .RateLimitError (
295
+ "Rate limit exceeded."
296
+ )
297
+ request = OpenAIRequest (text = "This is the text to summarize." )
298
+ response = client .post (
299
+ "/api/v1/openai/summarize" ,
300
+ json = request .dict (),
301
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
302
+ )
303
+ assert response .status_code == 429
304
+ assert "OpenAI API rate limit exceeded" in response .json ()["detail" ]
305
+
306
+ def test_summarize_text_authentication_error (
307
+ self , client , mock_openai , test_user
308
+ ):
309
+ mock_openai .Completion .create .side_effect = openai .error .AuthenticationError (
310
+ "Invalid API key."
311
+ )
312
+ request = OpenAIRequest (text = "This is the text to summarize." )
313
+ response = client .post (
314
+ "/api/v1/openai/summarize" ,
315
+ json = request .dict (),
316
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
317
+ )
318
+ assert response .status_code == 401
319
+ assert "Invalid OpenAI API key" in response .json ()["detail" ]
320
+
321
+ def test_summarize_text_timeout_error (self , client , mock_openai , test_user ):
322
+ mock_openai .Completion .create .side_effect = openai .error .TimeoutError (
323
+ "Request timed out."
324
+ )
325
+ request = OpenAIRequest (text = "This is the text to summarize." )
326
+ response = client .post (
327
+ "/api/v1/openai/summarize" ,
328
+ json = request .dict (),
329
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
330
+ )
331
+ assert response .status_code == 504
332
+ assert "Request to OpenAI API timed out" in response .json ()["detail" ]
333
+
334
+ def test_summarize_text_connection_error (self , client , mock_openai , test_user ):
335
+ mock_openai .Completion .create .side_effect = openai .error .APIConnectionError (
336
+ "Connection error."
337
+ )
338
+ request = OpenAIRequest (text = "This is the text to summarize." )
339
+ response = client .post (
340
+ "/api/v1/openai/summarize" ,
341
+ json = request .dict (),
342
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
343
+ )
344
+ assert response .status_code == 500
345
+ assert "Error connecting to OpenAI API" in response .json ()["detail" ]
346
+
347
+ def test_summarize_text_general_api_error (self , client , mock_openai , test_user ):
348
+ mock_openai .Completion .create .side_effect = openai .error .APIError (
349
+ "General API error."
350
+ )
351
+ request = OpenAIRequest (text = "This is the text to summarize." )
352
+ response = client .post (
353
+ "/api/v1/openai/summarize" ,
354
+ json = request .dict (),
355
+ headers = {"Authorization" : f"Bearer { test_user .api_key } " },
356
+ )
357
+ assert response .status_code == 500
358
+ assert "Error calling OpenAI API" in response .json ()["detail" ]
0 commit comments