22from pathlib import Path
33from unittest .mock import patch
44
5- from easy_django_cli .cli import execute_django_command , find_manage_py , main
5+ from easy_django_cli .cli import (
6+ _get_top_level_directory ,
7+ execute_django_command ,
8+ find_manage_py ,
9+ main ,
10+ )
611
712
813class TestFindManagePy :
@@ -12,55 +17,240 @@ def test_find_manage_py_in_current_dir(self, temp_dir: Path) -> None:
1217 WHEN: Searching for manage.py in that directory
1318 THEN: The manage.py file should be found
1419 """
20+ import os
21+
1522 manage_py = temp_dir / "manage.py"
1623 manage_py .write_text ("# manage.py" )
1724
18- result = find_manage_py (temp_dir )
25+ original_cwd = os .getcwd ()
26+ try :
27+ os .chdir (temp_dir )
28+ result = find_manage_py ()
1929
20- assert result is not None
21- assert result .resolve () == manage_py .resolve ()
30+ assert result is not None
31+ assert result .resolve () == manage_py .resolve ()
32+ finally :
33+ os .chdir (original_cwd )
2234
2335 def test_find_manage_py_in_parent_dir (self , temp_dir : Path ) -> None :
2436 """
2537 GIVEN: A parent directory with manage.py and a subdirectory
2638 WHEN: Searching for manage.py from the subdirectory
2739 THEN: The manage.py in the parent directory should be found
2840 """
41+ import os
42+
2943 manage_py = temp_dir / "manage.py"
3044 manage_py .write_text ("# manage.py" )
3145 subdir = temp_dir / "subdir"
3246 subdir .mkdir ()
3347
34- result = find_manage_py (subdir )
48+ original_cwd = os .getcwd ()
49+ try :
50+ os .chdir (subdir )
51+ result = find_manage_py ()
3552
36- assert result is not None
37- assert result .resolve () == manage_py .resolve ()
53+ assert result is not None
54+ assert result .resolve () == manage_py .resolve ()
55+ finally :
56+ os .chdir (original_cwd )
3857
3958 def test_find_manage_py_not_found (self , temp_dir : Path ) -> None :
4059 """
4160 GIVEN: A directory without manage.py file
4261 WHEN: Searching for manage.py in that directory
4362 THEN: No manage.py should be found
4463 """
45- result = find_manage_py ( temp_dir )
64+ import os
4665
47- assert result is None
66+ original_cwd = os .getcwd ()
67+ try :
68+ os .chdir (temp_dir )
69+ result = find_manage_py ()
70+
71+ assert result is None
72+ finally :
73+ os .chdir (original_cwd )
4874
4975 def test_find_manage_py_max_depth (self , temp_dir : Path ) -> None :
5076 """
5177 GIVEN: A manage.py at the root and a deeply nested directory
5278 WHEN: Searching for manage.py from the deeply nested directory
5379 THEN: The manage.py at the root should be found
5480 """
81+ import os
82+
83+ manage_py = temp_dir / "manage.py"
84+ manage_py .write_text ("# manage.py" )
85+ deep_dir = temp_dir / "a" / "b" / "c"
86+ deep_dir .mkdir (parents = True )
87+
88+ original_cwd = os .getcwd ()
89+ try :
90+ os .chdir (deep_dir )
91+ result = find_manage_py ()
92+
93+ assert result is not None
94+ assert result .resolve () == manage_py .resolve ()
95+ finally :
96+ os .chdir (original_cwd )
97+
98+ def test_find_manage_py_max_depth_fails (self , temp_dir : Path ) -> None :
99+ """
100+ GIVEN: A manage.py beyond the max search depth
101+ WHEN: Searching for manage.py from a deeply nested directory
102+ THEN: No manage.py should be found
103+ """
104+ import os
105+
55106 manage_py = temp_dir / "manage.py"
56107 manage_py .write_text ("# manage.py" )
57- deep_dir = temp_dir / "a" / "b" / "c" / "d" / "e" / "f"
108+ deep_dir = temp_dir / "a" / "b" / "c" / "d"
58109 deep_dir .mkdir (parents = True )
59110
60- result = find_manage_py (deep_dir )
111+ original_cwd = os .getcwd ()
112+ try :
113+ os .chdir (deep_dir )
114+ result = find_manage_py ()
115+
116+ assert result is None
117+ finally :
118+ os .chdir (original_cwd )
119+
120+ def test_find_manage_py_stops_at_git_boundary (self , temp_dir : Path ) -> None :
121+ """
122+ GIVEN: A git repository without manage.py and a parent directory with manage.py
123+ WHEN: Searching for manage.py from inside the git repo
124+ THEN: The search should stop at the git boundary and not find the parent's manage.py
125+ """
126+ import os
127+
128+ # Create a manage.py in the parent directory
129+ parent_manage_py = temp_dir / "manage.py"
130+ parent_manage_py .write_text ("# parent manage.py" )
131+
132+ # Create a subdirectory with .git (simulating a git repo)
133+ git_repo = temp_dir / "git_repo"
134+ git_repo .mkdir ()
135+ git_dir = git_repo / ".git"
136+ git_dir .mkdir ()
137+
138+ # Create a subdirectory inside the git repo
139+ subdir = git_repo / "subdir"
140+ subdir .mkdir ()
141+
142+ # Change to the subdir and search from there
143+ original_cwd = os .getcwd ()
144+ try :
145+ os .chdir (subdir )
146+ result = find_manage_py ()
147+
148+ # Should not find the parent's manage.py due to git boundary
149+ assert result is None
150+ finally :
151+ os .chdir (original_cwd )
152+
153+ def test_find_manage_py_finds_within_git_repo (self , temp_dir : Path ) -> None :
154+ """
155+ GIVEN: A git repository with manage.py inside it
156+ WHEN: Searching for manage.py from a subdirectory in the repo
157+ THEN: The manage.py inside the git repo should be found
158+ """
159+ import os
160+
161+ # Create a git repo directory with .git
162+ git_repo = temp_dir / "git_repo"
163+ git_repo .mkdir ()
164+ git_dir = git_repo / ".git"
165+ git_dir .mkdir ()
166+
167+ # Create manage.py inside the git repo
168+ manage_py = git_repo / "manage.py"
169+ manage_py .write_text ("# manage.py" )
170+
171+ # Create a subdirectory inside the git repo
172+ subdir = git_repo / "subdir"
173+ subdir .mkdir ()
174+
175+ # Change to the subdir and search from there
176+ original_cwd = os .getcwd ()
177+ try :
178+ os .chdir (subdir )
179+ result = find_manage_py ()
180+
181+ # Should find manage.py inside the git repo
182+ assert result is not None
183+ assert result .resolve () == manage_py .resolve ()
184+ finally :
185+ os .chdir (original_cwd )
186+
187+
188+ class TestGetTopLevelDirectory :
189+ def test_get_top_level_directory_no_django (self ) -> None :
190+ """
191+ GIVEN: Django is not installed or not configured
192+ WHEN: Calling _get_top_level_directory
193+ THEN: Should return None without raising exceptions
194+ """
195+ result = _get_top_level_directory ()
196+
197+ # Should handle missing Django gracefully
198+ assert result is None
199+
200+ def test_get_top_level_directory_with_django_configured (
201+ self , temp_dir : Path
202+ ) -> None :
203+ """
204+ GIVEN: Django is configured with BASE_DIR in settings
205+ WHEN: Calling _get_top_level_directory
206+ THEN: Should return the parent of BASE_DIR
207+ """
208+ # Create a mock settings module with BASE_DIR
209+ base_dir = temp_dir / "project"
210+ base_dir .mkdir ()
211+
212+ with patch ("django.conf.settings" ) as mock_settings :
213+ mock_settings .BASE_DIR = str (base_dir )
214+ result = _get_top_level_directory ()
215+
216+ assert result is not None
217+ assert result .resolve () == temp_dir .resolve ()
218+
219+ def test_get_top_level_directory_no_base_dir (self ) -> None :
220+ """
221+ GIVEN: Django is configured but settings has no BASE_DIR
222+ WHEN: Calling _get_top_level_directory
223+ THEN: Should return None
224+ """
225+ with patch ("django.conf.settings" ) as mock_settings :
226+ # Mock settings without BASE_DIR attribute
227+ del mock_settings .BASE_DIR
228+ mock_settings .BASE_DIR = None
229+
230+ result = _get_top_level_directory ()
231+
232+ assert result is None
233+
234+ def test_get_top_level_directory_handles_improperly_configured (self ) -> None :
235+ """
236+ GIVEN: Django raises ImproperlyConfigured when accessing settings
237+ WHEN: Calling _get_top_level_directory
238+ THEN: Should return None without raising exceptions
239+ """
240+ from django .core .exceptions import ImproperlyConfigured
241+
242+ with patch ("django.conf.settings" ) as mock_settings :
243+ # Simulate ImproperlyConfigured error
244+ type(mock_settings ).BASE_DIR = property (
245+ lambda self : (_ for _ in ()).throw (
246+ ImproperlyConfigured ("Django is not configured" )
247+ )
248+ )
249+
250+ result = _get_top_level_directory ()
61251
62- assert result is not None
63- assert result . resolve () == manage_py . resolve ()
252+ # Should catch the exception and return None
253+ assert result is None
64254
65255
66256class TestExecuteDjangoCommand :
0 commit comments