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