11"""Unit tests for deferred API logging functionality."""
22
3- import json
43from typing import Any
5- from unittest .mock import patch , MagicMock
6- from flask import Flask , g
4+ from unittest .mock import patch
5+
76import pytest
7+ from flask import Flask
8+ from flask import g
89
910from spiffworkflow_backend .models .api_log_model import APILogModel
1011from spiffworkflow_backend .models .db import db
11- from spiffworkflow_backend .utils .api_logging import (
12- log_api_interaction ,
13- setup_deferred_logging ,
14- _queue_api_log_entry ,
15- _process_log_queue ,
16- _log_queue
17- )
12+ from spiffworkflow_backend .utils .api_logging import _log_queue
13+ from spiffworkflow_backend .utils .api_logging import _process_log_queue
14+ from spiffworkflow_backend .utils .api_logging import _queue_api_log_entry
15+ from spiffworkflow_backend .utils .api_logging import log_api_interaction
1816from tests .spiffworkflow_backend .helpers .base_test import BaseTest
1917
2018
@@ -23,6 +21,7 @@ class TestDeferredAPILogging(BaseTest):
2321
2422 def test_decorator_respects_config_setting (self , app : Flask ) -> None :
2523 """Test that the decorator only logs when enabled."""
24+
2625 @log_api_interaction
2726 def test_function () -> tuple [dict [str , str ], int ]:
2827 return {"result" : "success" }, 200
@@ -43,6 +42,7 @@ def test_function() -> tuple[dict[str, str], int]:
4342
4443 def test_decorator_creates_log_when_enabled (self , app : Flask ) -> None :
4544 """Test that the decorator creates logs when enabled."""
45+
4646 @log_api_interaction
4747 def test_function () -> tuple [dict [str , str ], int ]:
4848 return {"result" : "success" }, 200
@@ -62,7 +62,7 @@ def test_function() -> tuple[dict[str, str], int]:
6262 assert result == ({"result" : "success" }, 200 )
6363
6464 # Process any queued logs (simulating teardown)
65- if hasattr (g , ' has_pending_api_logs' ) and g .has_pending_api_logs :
65+ if hasattr (g , " has_pending_api_logs" ) and g .has_pending_api_logs :
6666 _process_log_queue ()
6767
6868 # Should create a log entry
@@ -81,6 +81,7 @@ def test_function() -> tuple[dict[str, str], int]:
8181
8282 def test_decorator_logs_exceptions (self , app : Flask ) -> None :
8383 """Test that the decorator logs when the decorated function raises exceptions."""
84+
8485 @log_api_interaction
8586 def test_function () -> None :
8687 raise ValueError ("Test error" )
@@ -100,7 +101,7 @@ def test_function() -> None:
100101 test_function ()
101102
102103 # Process any queued logs
103- if hasattr (g , ' has_pending_api_logs' ) and g .has_pending_api_logs :
104+ if hasattr (g , " has_pending_api_logs" ) and g .has_pending_api_logs :
104105 _process_log_queue ()
105106
106107 # Should still create a log entry for the failed request
@@ -139,7 +140,7 @@ def test_function() -> None:
139140 test_function ()
140141
141142 # Process any queued logs
142- if hasattr (g , ' has_pending_api_logs' ) and g .has_pending_api_logs :
143+ if hasattr (g , " has_pending_api_logs" ) and g .has_pending_api_logs :
143144 _process_log_queue ()
144145
145146 # Should create a log entry with API error details
@@ -154,6 +155,7 @@ def test_function() -> None:
154155
155156 def test_process_instance_id_extraction (self , app : Flask ) -> None :
156157 """Test extraction of process_instance_id from various sources."""
158+
157159 @log_api_interaction
158160 def test_function_with_kwargs (process_instance_id : int | None = None ) -> tuple [dict [str , dict [str , int ]], int ]:
159161 return {"process_instance" : {"id" : 456 }}, 200
@@ -170,10 +172,10 @@ def test_function_with_kwargs(process_instance_id: int | None = None) -> tuple[d
170172 try :
171173 with app .test_request_context ("/test" ):
172174 # Test extraction from kwargs
173- result = test_function_with_kwargs (process_instance_id = 123 )
175+ test_function_with_kwargs (process_instance_id = 123 )
174176
175177 # Process any queued logs
176- if hasattr (g , ' has_pending_api_logs' ) and g .has_pending_api_logs :
178+ if hasattr (g , " has_pending_api_logs" ) and g .has_pending_api_logs :
177179 _process_log_queue ()
178180
179181 logs = db .session .query (APILogModel ).all ()
@@ -197,12 +199,7 @@ def test_queue_processing_outside_flask_context(self, app: Flask) -> None:
197199 _log_queue .get_nowait ()
198200
199201 # Create a log entry outside request context
200- log_entry = APILogModel (
201- endpoint = "/test" ,
202- method = "POST" ,
203- status_code = 200 ,
204- duration_ms = 100
205- )
202+ log_entry = APILogModel (endpoint = "/test" , method = "POST" , status_code = 200 , duration_ms = 100 )
206203
207204 # This should process immediately since we're outside Flask context
208205 _queue_api_log_entry (log_entry )
@@ -225,12 +222,7 @@ def test_batch_log_processing(self, app: Flask) -> None:
225222
226223 # Add multiple entries to queue
227224 for i in range (3 ):
228- log_entry = APILogModel (
229- endpoint = f"/test{ i } " ,
230- method = "GET" ,
231- status_code = 200 ,
232- duration_ms = 50 + i
233- )
225+ log_entry = APILogModel (endpoint = f"/test{ i } " , method = "GET" , status_code = 200 , duration_ms = 50 + i )
234226 _log_queue .put (log_entry )
235227
236228 # Process the queue
@@ -259,41 +251,31 @@ def test_teardown_handler_setup(self, app: Flask) -> None:
259251 g .has_pending_api_logs = True
260252
261253 # Create a mock log entry in the queue
262- log_entry = APILogModel (
263- endpoint = "/teardown_test" ,
264- method = "POST" ,
265- status_code = 201 ,
266- duration_ms = 75
267- )
254+ log_entry = APILogModel (endpoint = "/teardown_test" , method = "POST" , status_code = 201 , duration_ms = 75 )
268255 _log_queue .put (log_entry )
269256
270257 # Manually call what the teardown handler would do
271- if hasattr (g , ' has_pending_api_logs' ) and g .has_pending_api_logs :
258+ if hasattr (g , " has_pending_api_logs" ) and g .has_pending_api_logs :
272259 _process_log_queue ()
273260
274261 # Verify the log was processed
275262 logs = db .session .query (APILogModel ).filter_by (endpoint = "/teardown_test" ).all ()
276263 assert len (logs ) == 1
277264 assert logs [0 ].status_code == 201
278265
279- @patch (' spiffworkflow_backend.utils.api_logging.logger' )
266+ @patch (" spiffworkflow_backend.utils.api_logging.logger" )
280267 def test_error_handling_in_log_processing (self , mock_logger : Any , app : Flask ) -> None :
281268 """Test error handling when log processing fails."""
282269 with app .app_context ():
283270 # Create a valid log entry but mock db.session.commit to raise an exception
284- test_entry = APILogModel (
285- endpoint = "/error_test" ,
286- method = "GET" ,
287- status_code = 200 ,
288- duration_ms = 100
289- )
271+ test_entry = APILogModel (endpoint = "/error_test" , method = "GET" , status_code = 200 , duration_ms = 100 )
290272
291273 # Mock db.session.commit to raise an exception
292- with patch (' spiffworkflow_backend.models.db.db.session.commit' , side_effect = Exception ("DB Error" )):
274+ with patch (" spiffworkflow_backend.models.db.db.session.commit" , side_effect = Exception ("DB Error" )):
293275 _log_queue .put (test_entry )
294276 _process_log_queue ()
295277
296278 # Should log the error
297279 mock_logger .error .assert_called ()
298280 call_args = mock_logger .error .call_args [0 ][0 ]
299- assert "Failed to commit API log entries" in call_args
281+ assert "Failed to commit API log entries" in call_args
0 commit comments