|
| 1 | +"""Shared test fixtures for command tests.""" |
| 2 | + |
| 3 | +from collections.abc import Callable |
| 4 | +from unittest.mock import AsyncMock, Mock |
| 5 | + |
| 6 | +import pytest |
| 7 | + |
| 8 | +from workato_platform_cli.cli.utils.config import ConfigData, ProfileData |
| 9 | + |
| 10 | + |
| 11 | +@pytest.fixture |
| 12 | +def profile_data_factory() -> Callable[..., ProfileData]: |
| 13 | + """Create ProfileData instances for test scenarios.""" |
| 14 | + |
| 15 | + def _factory( |
| 16 | + *, |
| 17 | + region: str = "us", |
| 18 | + region_url: str = "https://app.workato.com", |
| 19 | + workspace_id: int = 123, |
| 20 | + ) -> ProfileData: |
| 21 | + return ProfileData( |
| 22 | + region=region, |
| 23 | + region_url=region_url, |
| 24 | + workspace_id=workspace_id, |
| 25 | + ) |
| 26 | + |
| 27 | + return _factory |
| 28 | + |
| 29 | + |
| 30 | +@pytest.fixture |
| 31 | +def make_config_manager() -> Callable[..., Mock]: |
| 32 | + """Factory for building config manager stubs with attached profile manager.""" |
| 33 | + |
| 34 | + def _factory(**profile_methods: Mock) -> Mock: |
| 35 | + profile_manager = Mock() |
| 36 | + config_manager = Mock() |
| 37 | + config_manager.profile_manager = profile_manager |
| 38 | + # Provide deterministic config data unless overridden in tests |
| 39 | + config_manager.load_config.return_value = ConfigData() |
| 40 | + |
| 41 | + config_methods = { |
| 42 | + "load_config", |
| 43 | + "save_config", |
| 44 | + "get_workspace_root", |
| 45 | + "get_project_directory", |
| 46 | + } |
| 47 | + |
| 48 | + for name, value in profile_methods.items(): |
| 49 | + if name in config_methods: |
| 50 | + setattr(config_manager, name, value) |
| 51 | + else: |
| 52 | + setattr(profile_manager, name, value) |
| 53 | + |
| 54 | + return config_manager |
| 55 | + |
| 56 | + return _factory |
| 57 | + |
| 58 | + |
| 59 | +@pytest.fixture |
| 60 | +def mock_workato_context() -> Callable[..., tuple[Mock, AsyncMock]]: |
| 61 | + """Create mock Workato client and context for async operations. |
| 62 | +
|
| 63 | + Returns: |
| 64 | + Callable that returns (mock_client, async_context) tuple |
| 65 | + """ |
| 66 | + |
| 67 | + def _factory() -> tuple[Mock, AsyncMock]: |
| 68 | + mock_client = Mock() |
| 69 | + context = AsyncMock() |
| 70 | + context.__aenter__.return_value = mock_client |
| 71 | + context.__aexit__.return_value = False |
| 72 | + return mock_client, context |
| 73 | + |
| 74 | + return _factory |
| 75 | + |
| 76 | + |
| 77 | +@pytest.fixture |
| 78 | +def mock_init_dependencies(monkeypatch) -> Callable[..., dict[str, Mock | AsyncMock]]: |
| 79 | + """Setup common init command dependencies and mocks. |
| 80 | +
|
| 81 | + Returns a factory that creates and patches all common init test dependencies. |
| 82 | +
|
| 83 | + Usage: |
| 84 | + mocks = mock_init_dependencies( |
| 85 | + profile="test-profile", |
| 86 | + token="test-token", |
| 87 | + api_url="https://api.workato.com" |
| 88 | + ) |
| 89 | + # mocks contains: config_manager, workato_client, initialize_mock, pull_mock |
| 90 | + """ |
| 91 | + |
| 92 | + def _factory( |
| 93 | + profile: str = "default", |
| 94 | + token: str = "test-token", |
| 95 | + api_url: str = "https://api.workato.com", |
| 96 | + project_id: int | None = None, |
| 97 | + **config_overrides, |
| 98 | + ) -> dict[str, Mock | AsyncMock]: |
| 99 | + from workato_platform_cli.cli.commands import init as init_module |
| 100 | + |
| 101 | + # Create mocks |
| 102 | + mock_config_manager = Mock() |
| 103 | + mock_workato_client = Mock() |
| 104 | + workato_context = AsyncMock() |
| 105 | + |
| 106 | + # Setup config manager defaults |
| 107 | + mock_config_manager.load_config.return_value = Mock(profile=profile) |
| 108 | + mock_config_manager.get_project_directory.return_value = project_id |
| 109 | + mock_config_manager.profile_manager.resolve_environment_variables.return_value = ( |
| 110 | + token, |
| 111 | + api_url, |
| 112 | + ) |
| 113 | + |
| 114 | + # Apply any config overrides |
| 115 | + for attr, value in config_overrides.items(): |
| 116 | + if "." in attr: |
| 117 | + # Support nested attributes like "profile_manager.get_profile" |
| 118 | + obj = mock_config_manager |
| 119 | + parts = attr.split(".") |
| 120 | + for part in parts[:-1]: |
| 121 | + obj = getattr(obj, part) |
| 122 | + setattr(obj, parts[-1], value) |
| 123 | + else: |
| 124 | + setattr(mock_config_manager, attr, value) |
| 125 | + |
| 126 | + # Setup Workato context |
| 127 | + workato_context.__aenter__.return_value = mock_workato_client |
| 128 | + workato_context.__aexit__.return_value = False |
| 129 | + |
| 130 | + # Create and patch initialize mock |
| 131 | + mock_initialize = AsyncMock(return_value=mock_config_manager) |
| 132 | + monkeypatch.setattr( |
| 133 | + init_module.ConfigManager, |
| 134 | + "initialize", |
| 135 | + mock_initialize, |
| 136 | + ) |
| 137 | + |
| 138 | + # Create and patch pull mock |
| 139 | + mock_pull = AsyncMock() |
| 140 | + monkeypatch.setattr(init_module, "_pull_project", mock_pull) |
| 141 | + |
| 142 | + # Patch Workato and Configuration |
| 143 | + monkeypatch.setattr(init_module, "Workato", lambda **_: workato_context) |
| 144 | + monkeypatch.setattr(init_module, "Configuration", lambda **_: Mock()) |
| 145 | + |
| 146 | + # Silence click.echo |
| 147 | + monkeypatch.setattr(init_module.click, "echo", lambda _="": None) |
| 148 | + |
| 149 | + return { |
| 150 | + "config_manager": mock_config_manager, |
| 151 | + "workato_client": mock_workato_client, |
| 152 | + "workato_context": workato_context, |
| 153 | + "initialize_mock": mock_initialize, |
| 154 | + "pull_mock": mock_pull, |
| 155 | + } |
| 156 | + |
| 157 | + return _factory |
0 commit comments