@@ -154,6 +154,67 @@ def test_scan_json_output(self):
154154 assert "prod" in data
155155
156156
157+ def test_scan_nonexistent_dir_warning (self ):
158+ """Scan with a non-directory path should warn and skip."""
159+ with tempfile .TemporaryDirectory () as tmpdir :
160+ dev_dir = Path (tmpdir ) / "dev"
161+ dev_dir .mkdir ()
162+ (dev_dir / "c.yaml" ).write_text (yaml .dump ({"host" : "localhost" }))
163+ fake_dir = Path (tmpdir ) / "nonexistent"
164+
165+ result = runner .invoke (app , ["scan" , str (dev_dir ), str (fake_dir )])
166+ assert "is not a" in result .stdout .replace ("\n " , " " )
167+
168+ def test_scan_unreadable_file_in_dir (self ):
169+ """Scan should warn when a config file in a directory can't be loaded."""
170+ with tempfile .TemporaryDirectory () as tmpdir :
171+ dev_dir = Path (tmpdir ) / "dev"
172+ prod_dir = Path (tmpdir ) / "prod"
173+ dev_dir .mkdir ()
174+ prod_dir .mkdir ()
175+ (dev_dir / "app.yaml" ).write_text (yaml .dump ({"host" : "localhost" }))
176+ # Write invalid YAML that will cause a load error
177+ (prod_dir / "broken.yaml" ).write_text ("{{invalid yaml::" )
178+ (prod_dir / "good.yaml" ).write_text (yaml .dump ({"host" : "prod.example.com" }))
179+
180+ result = runner .invoke (app , ["scan" , str (dev_dir ), str (prod_dir )])
181+ # Should still succeed but may include a warning about the broken file
182+ assert result .exit_code == 0 or "could not load" in result .stdout
183+
184+ def test_scan_breaking_drift_exit_code (self ):
185+ """Scan with breaking drift should exit 1."""
186+ with tempfile .TemporaryDirectory () as tmpdir :
187+ dev_dir = Path (tmpdir ) / "dev"
188+ prod_dir = Path (tmpdir ) / "prod"
189+ dev_dir .mkdir ()
190+ prod_dir .mkdir ()
191+ (dev_dir / "c.yaml" ).write_text (yaml .dump ({"database_url" : "postgres://dev" }))
192+ (prod_dir / "c.yaml" ).write_text (yaml .dump ({"database_url" : "postgres://prod" }))
193+
194+ result = runner .invoke (app , ["scan" , str (dev_dir ), str (prod_dir )])
195+ assert result .exit_code == 1
196+ assert "BREAKING" in result .stdout
197+
198+ def test_scan_no_args_no_config (self ):
199+ """Scan with no directories and no config should error."""
200+ result = runner .invoke (app , ["scan" ])
201+ assert result .exit_code == 1
202+ assert "Provide either" in result .stdout
203+
204+ def test_scan_silent_breaking_drift (self ):
205+ """Scan silent mode should exit 1 when breaking drift exists."""
206+ with tempfile .TemporaryDirectory () as tmpdir :
207+ dev_dir = Path (tmpdir ) / "dev"
208+ prod_dir = Path (tmpdir ) / "prod"
209+ dev_dir .mkdir ()
210+ prod_dir .mkdir ()
211+ (dev_dir / "c.yaml" ).write_text (yaml .dump ({"database_url" : "postgres://dev" }))
212+ (prod_dir / "c.yaml" ).write_text (yaml .dump ({"database_url" : "postgres://prod" }))
213+
214+ result = runner .invoke (app , ["scan" , str (dev_dir ), str (prod_dir ), "--output" , "silent" ])
215+ assert result .exit_code == 1
216+
217+
157218class TestInitCommand :
158219 def test_init_creates_file (self ):
159220 """Init should create .configdrift.yaml."""
0 commit comments