|
3 | 3 |
|
4 | 4 | import os |
5 | 5 | import platform |
6 | | -from unittest.mock import patch |
| 6 | +from argparse import Namespace |
| 7 | +from unittest.mock import MagicMock, patch |
7 | 8 |
|
8 | 9 | import pytest |
9 | 10 | import yaml |
@@ -354,3 +355,68 @@ def test_deploy_with_home_directory_path_success( |
354 | 355 | mock_print_done.assert_called() |
355 | 356 | assert "Deployment completed successfully" in str( |
356 | 357 | mock_print_done.call_args) |
| 358 | + |
| 359 | + def _run_deploy_with_config_file(self, deploy_with_config, params=None): |
| 360 | + """Invoke deploy_with_config_file with fabric-cicd symbols patched (no network).""" |
| 361 | + from fabric_cli.commands.fs.deploy import ( |
| 362 | + fab_fs_deploy_config_file as deploy_mod, |
| 363 | + ) |
| 364 | + |
| 365 | + args = Namespace( |
| 366 | + config="config.yml", |
| 367 | + target_env="dev", |
| 368 | + command_path="deploy", |
| 369 | + params=params if params is not None else [], |
| 370 | + ) |
| 371 | + |
| 372 | + with ( |
| 373 | + patch.object(deploy_mod, "deploy_with_config", deploy_with_config), |
| 374 | + patch.object( |
| 375 | + deploy_mod, "create_fabric_token_credential", MagicMock()), |
| 376 | + patch.object(deploy_mod, "append_feature_flag", MagicMock()), |
| 377 | + patch.object(deploy_mod, "disable_file_logging", MagicMock()), |
| 378 | + patch.object( |
| 379 | + deploy_mod, "configure_external_file_logging", MagicMock()), |
| 380 | + patch.object( |
| 381 | + deploy_mod.fab_state_config, "get_config", return_value="false" |
| 382 | + ), |
| 383 | + patch.object(deploy_mod.fab_ui, |
| 384 | + "print_output_format", MagicMock()), |
| 385 | + ): |
| 386 | + deploy_mod.deploy_with_config_file(args) |
| 387 | + |
| 388 | + def _capture_deploy_host_app(self, params=None): |
| 389 | + """Run deploy_with_config_file and return the host_app passed to fabric-cicd.""" |
| 390 | + captured = {} |
| 391 | + |
| 392 | + def fake_deploy_with_config( |
| 393 | + *, |
| 394 | + config_file_path, |
| 395 | + token_credential, |
| 396 | + environment="N/A", |
| 397 | + config_override=None, |
| 398 | + host_app=None, |
| 399 | + ): |
| 400 | + captured["host_app"] = host_app |
| 401 | + return MagicMock(message="Deployment completed successfully") |
| 402 | + |
| 403 | + self._run_deploy_with_config_file( |
| 404 | + fake_deploy_with_config, params=params) |
| 405 | + |
| 406 | + return captured["host_app"] |
| 407 | + |
| 408 | + def test_deploy_passes_host_app_success(self): |
| 409 | + """CLI passes host_app as 'ms-fabric-cli/<version>'.""" |
| 410 | + from fabric_cli.core import fab_constant |
| 411 | + |
| 412 | + host_app = self._capture_deploy_host_app() |
| 413 | + |
| 414 | + assert host_app == f"{fab_constant.API_USER_AGENT}/{fab_constant.FAB_VERSION}" |
| 415 | + |
| 416 | + def test_deploy_host_app_cannot_be_spoofed_via_params_success(self): |
| 417 | + """A user-supplied host_app (via -P) is overridden by the CLI-controlled value.""" |
| 418 | + from fabric_cli.core import fab_constant |
| 419 | + |
| 420 | + host_app = self._capture_deploy_host_app(params=["host_app=spoofed"]) |
| 421 | + |
| 422 | + assert host_app == f"{fab_constant.API_USER_AGENT}/{fab_constant.FAB_VERSION}" |
0 commit comments