@@ -287,6 +287,60 @@ def test_job_info_pretty_still_works(_mock_require, _mock_api):
287287 assert "RUNNING" in out
288288
289289
290+ # ---------------------------------------------------------------------------
291+ # Stop command tests
292+ # ---------------------------------------------------------------------------
293+
294+
295+ @patch ("transformerlab_cli.commands.job.api.post" )
296+ @patch ("transformerlab_cli.commands.job.require_current_experiment" , return_value = "exp1" )
297+ @patch ("transformerlab_cli.commands.job.api.get" )
298+ def test_job_stop_also_sends_cluster_stop_when_provider_metadata_exists (_mock_get , _mock_require , mock_post ):
299+ """job stop should mirror GUI behavior and request provider cluster stop when possible."""
300+ stop_response = MagicMock ()
301+ stop_response .status_code = 200
302+ stop_response .json .return_value = {"message" : "OK" }
303+
304+ job_response = MagicMock ()
305+ job_response .status_code = 200
306+ job_response .json .return_value = {
307+ "id" : "42" ,
308+ "job_data" : {"provider_id" : "provider-1" , "cluster_name" : "cluster-a" },
309+ }
310+
311+ _mock_get .side_effect = [stop_response , job_response ]
312+
313+ cluster_stop_response = MagicMock ()
314+ cluster_stop_response .status_code = 200
315+ mock_post .return_value = cluster_stop_response
316+
317+ result = runner .invoke (app , ["job" , "stop" , "42" ])
318+ assert result .exit_code == 0 , result .output
319+ assert _mock_get .call_args_list [0 ].args [0 ] == "/experiment/exp1/jobs/42/stop"
320+ assert _mock_get .call_args_list [1 ].args [0 ] == "/experiment/exp1/jobs/42"
321+ mock_post .assert_called_once_with ("/compute_provider/providers/provider-1/clusters/cluster-a/stop?job_id=42" )
322+
323+
324+ @patch ("transformerlab_cli.commands.job.api.post" )
325+ @patch ("transformerlab_cli.commands.job.require_current_experiment" , return_value = "exp1" )
326+ @patch ("transformerlab_cli.commands.job.api.get" )
327+ def test_job_stop_skips_cluster_stop_without_provider_metadata (_mock_get , _mock_require , mock_post ):
328+ """job stop should not call cluster-stop when provider metadata is missing."""
329+ stop_response = MagicMock ()
330+ stop_response .status_code = 200
331+ stop_response .json .return_value = {"message" : "OK" }
332+
333+ job_response = MagicMock ()
334+ job_response .status_code = 200
335+ job_response .json .return_value = {"id" : "42" , "job_data" : {}}
336+
337+ _mock_get .side_effect = [stop_response , job_response ]
338+
339+ result = runner .invoke (app , ["job" , "stop" , "42" ])
340+ assert result .exit_code == 0 , result .output
341+ mock_post .assert_not_called ()
342+
343+
290344# ---------------------------------------------------------------------------
291345# Log command tests
292346# ---------------------------------------------------------------------------
0 commit comments