From 7ec39c7d0a464d94822845406c3b35ba294ad173 Mon Sep 17 00:00:00 2001 From: "gitauto-ai[bot]" <161652217+gitauto-ai[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 00:00:37 +0000 Subject: [PATCH 1/4] Initial empty commit to create PR From 0aa779d0a84c19c5d09290c353fbeb6ec6863352 Mon Sep 17 00:00:00 2001 From: "gitauto-ai[bot]" <161652217+gitauto-ai[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 00:01:25 +0000 Subject: [PATCH 2/4] Update services/supabase/llm_requests/test_clear_old_content.py [skip ci] --- .../llm_requests/test_clear_old_content.py | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 services/supabase/llm_requests/test_clear_old_content.py diff --git a/services/supabase/llm_requests/test_clear_old_content.py b/services/supabase/llm_requests/test_clear_old_content.py new file mode 100644 index 000000000..c3710265d --- /dev/null +++ b/services/supabase/llm_requests/test_clear_old_content.py @@ -0,0 +1,116 @@ +from datetime import datetime, timedelta +from unittest.mock import Mock, patch +from services.supabase.llm_requests.clear_old_content import clear_old_content + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_success(mock_supabase): + mock_result = Mock() + mock_result.data = [{"id": 1}, {"id": 2}] + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content(retention_days=14) + + assert result == [{"id": 1}, {"id": 2}] + mock_supabase.table.assert_called_once_with("llm_requests") + mock_supabase.table.return_value.update.assert_called_once_with( + {"input_content": "", "output_content": ""} + ) + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_with_custom_retention_days(mock_supabase): + mock_result = Mock() + mock_result.data = [{"id": 3}] + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content(retention_days=30) + + assert result == [{"id": 3}] + mock_supabase.table.assert_called_once_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_with_zero_retention_days(mock_supabase): + mock_result = Mock() + mock_result.data = [{"id": 4}] + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content(retention_days=0) + + assert result == [{"id": 4}] + mock_supabase.table.assert_called_once_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_with_large_retention_days(mock_supabase): + mock_result = Mock() + mock_result.data = [] + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content(retention_days=365) + + assert result is None + mock_supabase.table.assert_called_once_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_empty_result(mock_supabase): + mock_result = Mock() + mock_result.data = [] + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content(retention_days=14) + + assert result is None + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_none_data(mock_supabase): + mock_result = Mock() + mock_result.data = None + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content(retention_days=14) + + assert result is None + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_database_error(mock_supabase): + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.side_effect = ( + Exception("Database error") + ) + + result = clear_old_content(retention_days=14) + + assert result is None + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +def test_clear_old_content_default_retention_days(mock_supabase): + mock_result = Mock() + mock_result.data = [{"id": 5}] + mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( + mock_result + ) + + result = clear_old_content() + + assert result == [{"id": 5}] + mock_supabase.table.assert_called_once_with("llm_requests") + mock_supabase.table.return_value.update.assert_called_once_with( + {"input_content": "", "output_content": ""} + ) From 627120801b229d84ffdf4e4174d350cab0661e3b Mon Sep 17 00:00:00 2001 From: "gitauto-ai[bot]" <161652217+gitauto-ai[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 00:03:29 +0000 Subject: [PATCH 3/4] Replace content of services/supabase/llm_requests/test_clear_old_content.py [skip ci] --- .../llm_requests/test_clear_old_content.py | 384 +++++++++++++++--- 1 file changed, 327 insertions(+), 57 deletions(-) diff --git a/services/supabase/llm_requests/test_clear_old_content.py b/services/supabase/llm_requests/test_clear_old_content.py index c3710265d..af1a9e454 100644 --- a/services/supabase/llm_requests/test_clear_old_content.py +++ b/services/supabase/llm_requests/test_clear_old_content.py @@ -1,116 +1,386 @@ from datetime import datetime, timedelta from unittest.mock import Mock, patch + from services.supabase.llm_requests.clear_old_content import clear_old_content @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_success(mock_supabase): +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_success_default_retention(mock_datetime, mock_supabase): + """Test successful clearing of old content with default retention days (14).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + expected_cutoff = (fixed_now - timedelta(days=14)).isoformat() + mock_result = Mock() - mock_result.data = [{"id": 1}, {"id": 2}] - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) + mock_result.data = [ + {"id": 1, "created_at": "2025-11-10T12:00:00"}, + {"id": 2, "created_at": "2025-11-11T12:00:00"}, + ] - result = clear_old_content(retention_days=14) + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() - assert result == [{"id": 1}, {"id": 2}] - mock_supabase.table.assert_called_once_with("llm_requests") - mock_supabase.table.return_value.update.assert_called_once_with( - {"input_content": "", "output_content": ""} - ) + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content() + + assert result == mock_result.data + mock_supabase.table.assert_called_with("llm_requests") + mock_table.update.assert_called_with({"input_content": "", "output_content": ""}) + mock_update.lt.assert_called_with("created_at", expected_cutoff) + mock_lt.execute.assert_called_once() @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_with_custom_retention_days(mock_supabase): +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_custom_retention_days(mock_datetime, mock_supabase): + """Test clearing old content with custom retention days.""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + retention_days = 30 + expected_cutoff = (fixed_now - timedelta(days=retention_days)).isoformat() + mock_result = Mock() - mock_result.data = [{"id": 3}] - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) + mock_result.data = [{"id": 3, "created_at": "2025-10-15T12:00:00"}] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() - result = clear_old_content(retention_days=30) + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result - assert result == [{"id": 3}] - mock_supabase.table.assert_called_once_with("llm_requests") + result = clear_old_content(retention_days=retention_days) + + assert result == mock_result.data + mock_supabase.table.assert_called_with("llm_requests") + mock_update.lt.assert_called_with("created_at", expected_cutoff) @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_with_zero_retention_days(mock_supabase): +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_no_data_to_clear(mock_datetime, mock_supabase): + """Test when no old content is found to clear.""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + mock_result = Mock() - mock_result.data = [{"id": 4}] - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) + mock_result.data = [] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content() + + assert result is None + mock_supabase.table.assert_called_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_result_data_is_none(mock_datetime, mock_supabase): + """Test when result.data is None.""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + + mock_result = Mock() + mock_result.data = None + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content() + + assert result is None + mock_supabase.table.assert_called_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_zero_retention_days(mock_datetime, mock_supabase): + """Test clearing content with zero retention days (clear all).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + expected_cutoff = fixed_now.isoformat() + + mock_result = Mock() + mock_result.data = [{"id": 4}, {"id": 5}] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result result = clear_old_content(retention_days=0) - assert result == [{"id": 4}] - mock_supabase.table.assert_called_once_with("llm_requests") + assert result == mock_result.data + mock_supabase.table.assert_called_with("llm_requests") + mock_update.lt.assert_called_with("created_at", expected_cutoff) @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_with_large_retention_days(mock_supabase): +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_large_retention_days(mock_datetime, mock_supabase): + """Test clearing content with large retention days (e.g., 365 days).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + mock_result = Mock() - mock_result.data = [] - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) + mock_result.data = [{"id": 7}] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result result = clear_old_content(retention_days=365) - assert result is None - mock_supabase.table.assert_called_once_with("llm_requests") + assert result == mock_result.data + mock_supabase.table.assert_called_with("llm_requests") @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_empty_result(mock_supabase): +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_negative_retention_days(mock_datetime, mock_supabase): + """Test clearing content with negative retention days (future dates - edge case).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + expected_cutoff = (fixed_now - timedelta(days=-7)).isoformat() + mock_result = Mock() mock_result.data = [] - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) - result = clear_old_content(retention_days=14) + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content(retention_days=-7) assert result is None + mock_supabase.table.assert_called_with("llm_requests") + mock_update.lt.assert_called_with("created_at", expected_cutoff) @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_none_data(mock_supabase): - mock_result = Mock() - mock_result.data = None - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_database_exception(mock_datetime, mock_supabase): + """Test handling of database exceptions (decorator should catch and return None).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now - result = clear_old_content(retention_days=14) + mock_table = Mock() + mock_supabase.table.return_value = mock_table + mock_table.update.side_effect = Exception("Database connection error") + + result = clear_old_content() assert result is None + mock_supabase.table.assert_called_with("llm_requests") @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_database_error(mock_supabase): - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.side_effect = ( - Exception("Database error") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_attribute_error(mock_datetime, mock_supabase): + """Test handling of AttributeError (decorator should catch and return None).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.side_effect = AttributeError( + "'NoneType' object has no attribute 'data'" ) - result = clear_old_content(retention_days=14) + result = clear_old_content() + + assert result is None + mock_supabase.table.assert_called_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_type_error(mock_datetime, mock_supabase): + """Test handling of TypeError (decorator should catch and return None).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + + mock_table = Mock() + mock_update = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.side_effect = TypeError("Invalid type for comparison") + + result = clear_old_content() assert result is None + mock_supabase.table.assert_called_with("llm_requests") @patch("services.supabase.llm_requests.clear_old_content.supabase") -def test_clear_old_content_default_retention_days(mock_supabase): +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_key_error(mock_datetime, mock_supabase): + """Test handling of KeyError (decorator should catch and return None).""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.side_effect = KeyError("created_at") + + result = clear_old_content() + + assert result is None + mock_supabase.table.assert_called_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_single_record(mock_datetime, mock_supabase): + """Test clearing a single old record.""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + mock_result = Mock() - mock_result.data = [{"id": 5}] - mock_supabase.table.return_value.update.return_value.lt.return_value.execute.return_value = ( - mock_result - ) + mock_result.data = [{"id": 100, "created_at": "2025-11-01T12:00:00"}] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result result = clear_old_content() - assert result == [{"id": 5}] - mock_supabase.table.assert_called_once_with("llm_requests") - mock_supabase.table.return_value.update.assert_called_once_with( + assert result == mock_result.data + assert len(result) == 1 + mock_supabase.table.assert_called_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_multiple_records(mock_datetime, mock_supabase): + """Test clearing multiple old records.""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + + mock_result = Mock() + mock_result.data = [ + {"id": 1, "created_at": "2025-11-01T12:00:00"}, + {"id": 2, "created_at": "2025-11-05T12:00:00"}, + {"id": 3, "created_at": "2025-11-10T12:00:00"}, + ] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content() + + assert result == mock_result.data + assert len(result) == 3 + mock_supabase.table.assert_called_with("llm_requests") + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_verifies_update_payload(mock_datetime, mock_supabase): + """Test that the update payload contains correct empty strings.""" + fixed_now = datetime(2025, 12, 1, 12, 0, 0) + mock_datetime.now.return_value = fixed_now + + mock_result = Mock() + mock_result.data = [{"id": 1}] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content() + + mock_table.update.assert_called_once_with( {"input_content": "", "output_content": ""} ) + assert result == mock_result.data + + +@patch("services.supabase.llm_requests.clear_old_content.supabase") +@patch("services.supabase.llm_requests.clear_old_content.datetime") +def test_clear_old_content_verifies_cutoff_calculation(mock_datetime, mock_supabase): + """Test that the cutoff date is calculated correctly.""" + fixed_now = datetime(2025, 12, 15, 10, 30, 45) + mock_datetime.now.return_value = fixed_now + retention_days = 7 + expected_cutoff = (fixed_now - timedelta(days=retention_days)).isoformat() + + mock_result = Mock() + mock_result.data = [{"id": 1}] + + mock_table = Mock() + mock_update = Mock() + mock_lt = Mock() + + mock_supabase.table.return_value = mock_table + mock_table.update.return_value = mock_update + mock_update.lt.return_value = mock_lt + mock_lt.execute.return_value = mock_result + + result = clear_old_content(retention_days=retention_days) + + mock_update.lt.assert_called_once_with("created_at", expected_cutoff) + assert result == mock_result.data From 31ae697c3a542b3e7f9773f7a6ae715c2be8125f Mon Sep 17 00:00:00 2001 From: "gitauto-ai[bot]" <161652217+gitauto-ai[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 00:04:59 +0000 Subject: [PATCH 4/4] Empty commit to trigger final tests