11import os
22import sys
3+ import tempfile
34import unittest
45from unittest .mock import MagicMock , mock_open , patch
56
@@ -98,6 +99,33 @@ def test_returns_default_when_no_relevant_files(self, mock_walk, mock_exists):
9899 result = get_repo_context ("pr_code" )
99100 self .assertEqual (result , "No relevant source files found in repository." )
100101
102+ def test_lib_exclusion (self ):
103+ with tempfile .TemporaryDirectory () as temp_dir :
104+ with open (os .path .join (temp_dir , "main.py" ), "w" ) as f :
105+ f .write ("print('included')" )
106+ lib_dir = os .path .join (temp_dir , "lib" )
107+ os .makedirs (lib_dir )
108+ with open (os .path .join (lib_dir , "ignored.py" ), "w" ) as f :
109+ f .write ("print('ignored')" )
110+ deep_lib_dir = os .path .join (
111+ temp_dir ,
112+ "openwisp_controller" ,
113+ "config" ,
114+ "static" ,
115+ "config" ,
116+ "js" ,
117+ "lib" ,
118+ )
119+ os .makedirs (deep_lib_dir )
120+ with open (os .path .join (deep_lib_dir , "jquery.js" ), "w" ) as f :
121+ f .write ("console.log('massive library ignored')" )
122+ result = get_repo_context (temp_dir )
123+ self .assertIn ("main.py" , result )
124+ self .assertNotIn ("ignored.py" , result )
125+ self .assertNotIn ("jquery.js" , result )
126+ self .assertNotIn ("print('ignored')" , result )
127+ self .assertNotIn ("massive library ignored" , result )
128+
101129
102130class TestMain (unittest .TestCase ):
103131 """Tests for the main execution block."""
@@ -106,15 +134,19 @@ class TestMain(unittest.TestCase):
106134 @patch .dict (os .environ , {}, clear = True )
107135 def test_exits_early_without_api_key (self , mock_print ):
108136 main ()
109- mock_print .assert_any_call ("::warning::Skipping: No API Key found." )
137+ mock_print .assert_called_once_with (
138+ "::warning::Skipping: No API Key found." , file = sys .stderr
139+ )
110140
111141 @patch ("builtins.print" )
112142 @patch ("analyze_failure.get_error_logs" )
113143 @patch .dict (os .environ , {"GEMINI_API_KEY" : "fake_key" })
114144 def test_exits_early_without_failed_logs (self , mock_get_logs , mock_print ):
115145 mock_get_logs .return_value = "No failed logs found."
116146 main ()
117- mock_print .assert_any_call ("::warning::Skipping: No failure logs to analyse." )
147+ mock_print .assert_called_once_with (
148+ "::warning::Skipping: No failure logs to analyse." , file = sys .stderr
149+ )
118150
119151 @patch ("builtins.print" )
120152 @patch ("analyze_failure.genai" )
@@ -140,7 +172,7 @@ def test_successful_api_call_prints_response(
140172 mock_client .models .generate_content .return_value = mock_response
141173 mock_genai .Client .return_value = mock_client
142174 main ()
143- mock_print .assert_any_call (
175+ mock_print .assert_called_once_with (
144176 "### Test Failed\n "
145177 "Hello @testuser\n "
146178 "*(Analysis for commit abc1234)*\n "
@@ -168,8 +200,9 @@ def test_fails_format_validation(
168200 with self .assertRaises (SystemExit ) as context :
169201 main ()
170202 self .assertEqual (context .exception .code , 0 )
171- mock_print .assert_any_call (
172- "::warning::LLM output failed format validation; skipping comment."
203+ mock_print .assert_called_once_with (
204+ "::warning::LLM output failed format validation; skipping comment." ,
205+ file = sys .stderr ,
173206 )
174207
175208 @patch ("builtins.print" )
@@ -189,8 +222,9 @@ def test_handles_empty_api_response(
189222 mock_genai .Client .return_value = mock_client
190223 with self .assertRaises (SystemExit ):
191224 main ()
192- mock_print .assert_any_call (
193- "::warning::Generation returned an empty response; skipping report."
225+ mock_print .assert_called_once_with (
226+ "::warning::Generation returned an empty response; skipping report." ,
227+ file = sys .stderr ,
194228 )
195229
196230 @patch ("builtins.print" )
@@ -206,8 +240,9 @@ def test_handles_api_exception(self, mock_repo, mock_logs, mock_genai, mock_prin
206240 mock_genai .Client .return_value = mock_client
207241 with self .assertRaises (SystemExit ):
208242 main ()
209- mock_print .assert_any_call (
210- "::warning::API Error (Max retries reached or fatal error): Quota Exceeded"
243+ mock_print .assert_called_once_with (
244+ "::warning::API Error (Max retries reached or fatal error): Quota Exceeded" ,
245+ file = sys .stderr ,
211246 )
212247
213248 @patch ("builtins.print" )
@@ -230,6 +265,7 @@ def test_truncates_large_api_response(
230265 mock_client .models .generate_content .return_value = mock_response
231266 mock_genai .Client .return_value = mock_client
232267 main ()
268+ self .assertEqual (mock_print .call_count , 1 )
233269 printed_text = mock_print .call_args [0 ][0 ]
234270 self .assertIn (
235271 "*(Warning: Output truncated due to length limits)*" , printed_text
0 commit comments