Skip to content

Commit d85f0ee

Browse files
committed
test: add admin mock to prevent UAC dialogs
Add is_admin() mocks to 6 test methods to prevent Windows UAC elevation dialogs during test execution. Also fix test data format and remove obsolete executable permission check for Unix systems. Changes: - Add @patch('setup_environment.is_admin', return_value=True) to all tests calling install_claude() - Fix test_main_success: dependencies list -> dict format - Remove executable permission check (no longer needed with uv run) - Prevents SystemExit from request_admin_elevation() - Ensures zero UAC prompts during pytest execution - All 311 tests pass on Windows, macOS, and Linux
1 parent 94cc17d commit d85f0ee

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

tests/test_setup_environment.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,10 +1197,12 @@ class TestMainFunction:
11971197
@patch('setup_environment.create_additional_settings')
11981198
@patch('setup_environment.create_launcher_script')
11991199
@patch('setup_environment.register_global_command')
1200+
@patch('setup_environment.is_admin', return_value=True)
12001201
@patch('pathlib.Path.mkdir')
12011202
def test_main_success(
12021203
self,
12031204
mock_mkdir,
1205+
mock_is_admin,
12041206
mock_register,
12051207
mock_launcher,
12061208
mock_settings,
@@ -1214,11 +1216,14 @@ def test_main_success(
12141216
"""Test successful main flow."""
12151217
# Verify mock configuration is available
12161218
assert mock_mkdir is not None
1219+
assert mock_is_admin.return_value is True
12171220
mock_load.return_value = (
12181221
{
12191222
'name': 'Test Environment',
12201223
'command-name': 'test-env',
1221-
'dependencies': ['npm install -g test'],
1224+
'dependencies': {
1225+
'windows': ['npm install -g test'],
1226+
},
12221227
'agents': ['agents/test.md'],
12231228
'slash-commands': ['commands/test.md'],
12241229
'mcp-servers': [{'name': 'test'}],
@@ -1252,8 +1257,10 @@ def test_main_no_config(self, mock_load):
12521257

12531258
@patch('setup_environment.load_config_from_source')
12541259
@patch('setup_environment.install_claude')
1255-
def test_main_install_failure(self, mock_install, mock_load):
1260+
@patch('setup_environment.is_admin', return_value=True)
1261+
def test_main_install_failure(self, mock_is_admin, mock_install, mock_load):
12561262
"""Test main with Claude installation failure."""
1263+
assert mock_is_admin.return_value is True # Verify admin check is mocked
12571264
mock_load.return_value = ({'name': 'Test'}, 'test.yaml')
12581265
mock_install.return_value = False
12591266

@@ -1263,8 +1270,10 @@ def test_main_install_failure(self, mock_install, mock_load):
12631270

12641271
@patch('setup_environment.load_config_from_source')
12651272
@patch('setup_environment.find_command')
1266-
def test_main_skip_install(self, mock_find, mock_load):
1273+
@patch('setup_environment.is_admin', return_value=True)
1274+
def test_main_skip_install(self, mock_is_admin, mock_find, mock_load):
12671275
"""Test main with --skip-install flag."""
1276+
assert mock_is_admin.return_value is True # Verify admin check is mocked
12681277
mock_load.return_value = (
12691278
{
12701279
'name': 'Test Environment',

tests/test_setup_environment_additional.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -506,12 +506,14 @@ def test_install_claude_windows_ssl_error(self, mock_is_admin, mock_run, mock_ur
506506
assert mock_urlopen.call_count == 2
507507
mock_is_admin.assert_called() # Verify is_admin was called
508508

509+
@patch('setup_environment.is_admin', return_value=True)
509510
@patch('platform.system', return_value='Windows')
510511
@patch('setup_environment.urlopen')
511512
@patch('setup_environment.run_command')
512-
def test_install_claude_windows_failure(self, mock_run, mock_urlopen, mock_system):
513+
def test_install_claude_windows_failure(self, mock_run, mock_urlopen, mock_system, mock_is_admin):
513514
"""Test Claude installation failure on Windows."""
514515
assert mock_system.return_value == 'Windows'
516+
assert mock_is_admin.return_value is True
515517
mock_urlopen.return_value = MagicMock(read=lambda: b'# Script')
516518
mock_run.return_value = subprocess.CompletedProcess([], 1, '', 'Error')
517519

@@ -536,10 +538,12 @@ def test_install_claude_linux_success(self, mock_run, _mock_system):
536538
result = setup_environment.install_claude()
537539
assert result is True
538540

541+
@patch('setup_environment.is_admin', return_value=True)
539542
@patch('platform.system', return_value='Windows')
540543
@patch('setup_environment.urlopen')
541-
def test_install_claude_windows_network_error(self, mock_urlopen, _mock_system):
544+
def test_install_claude_windows_network_error(self, mock_urlopen, _mock_system, mock_is_admin):
542545
"""Test Claude installation with network error."""
546+
assert mock_is_admin.return_value is True
543547
mock_urlopen.side_effect = urllib.error.URLError('Network error')
544548

545549
result = setup_environment.install_claude()
@@ -905,9 +909,8 @@ def test_create_additional_settings_hooks_linux(self, _mock_system, mock_downloa
905909
)
906910

907911
assert result is True
908-
# Skip executable check on Windows as chmod doesn't work the same way
909-
if sys.platform != 'win32':
910-
assert hook_file.stat().st_mode & 0o111 # Check executable
912+
# Note: With uv run, executable permissions are no longer needed
913+
# The script is executed via: uv run --python 3.12 script.py
911914

912915
def test_create_additional_settings_hooks_invalid(self):
913916
"""Test handling invalid hook configuration."""
@@ -1122,6 +1125,7 @@ def test_main_skip_install_claude_not_found(self, mock_find, mock_load):
11221125
@patch('setup_environment.install_dependencies', return_value=True)
11231126
@patch('setup_environment.process_resources', return_value=True)
11241127
@patch('setup_environment.handle_resource', return_value=True)
1128+
@patch('setup_environment.is_admin', return_value=True)
11251129
@patch('setup_environment.configure_all_mcp_servers', return_value=True)
11261130
@patch('setup_environment.create_additional_settings', return_value=True)
11271131
@patch('setup_environment.create_launcher_script', return_value=None)
@@ -1132,6 +1136,7 @@ def test_main_no_launcher_created(
11321136
mock_launcher,
11331137
mock_settings,
11341138
mock_mcp,
1139+
mock_is_admin,
11351140
mock_handle_resource,
11361141
mock_process_resources,
11371142
mock_deps,
@@ -1140,6 +1145,7 @@ def test_main_no_launcher_created(
11401145
mock_load,
11411146
):
11421147
"""Test main when launcher creation fails."""
1148+
assert mock_is_admin.return_value is True
11431149
del _mock_mkdir # Unused but required for patch
11441150
del mock_launcher # Unused but required for patch
11451151
del mock_settings # Unused but required for patch
@@ -1163,6 +1169,7 @@ def test_main_no_launcher_created(
11631169
setup_environment.main()
11641170
mock_exit.assert_not_called() # Should continue despite launcher failure
11651171

1172+
@patch('setup_environment.is_admin', return_value=True)
11661173
@patch.dict('os.environ', {'CLAUDE_ENV_CONFIG': 'env-config'})
11671174
@patch('setup_environment.load_config_from_source')
11681175
@patch('setup_environment.install_claude', return_value=True)
@@ -1184,8 +1191,10 @@ def test_main_from_env_variable(
11841191
mock_deps,
11851192
mock_install,
11861193
mock_load,
1194+
mock_is_admin,
11871195
):
11881196
"""Test main using CLAUDE_ENV_CONFIG environment variable."""
1197+
assert mock_is_admin.return_value is True
11891198
del _mock_mkdir # Unused but required for patch
11901199
del mock_register # Unused but required for patch
11911200
del mock_settings # Unused but required for patch
@@ -1204,6 +1213,7 @@ def test_main_from_env_variable(
12041213
mock_exit.assert_not_called()
12051214
mock_load.assert_called_with('env-config', None)
12061215

1216+
@patch('setup_environment.is_admin', return_value=True)
12071217
@patch('setup_environment.load_config_from_source')
12081218
@patch('setup_environment.validate_all_config_files')
12091219
@patch('setup_environment.install_claude', return_value=True)
@@ -1228,8 +1238,10 @@ def test_main_with_all_features(
12281238
mock_install,
12291239
mock_validate,
12301240
mock_load,
1241+
mock_is_admin,
12311242
):
12321243
"""Test main with all configuration features enabled."""
1244+
assert mock_is_admin.return_value is True
12331245
del _mock_mkdir # Unused but required for patch
12341246
del mock_download_resource # Unused but required for patch
12351247

@@ -1252,7 +1264,9 @@ def test_main_with_all_features(
12521264
'API_KEY': 'test123',
12531265
'DEBUG': 'true',
12541266
},
1255-
'dependencies': ['npm install test'],
1267+
'dependencies': {
1268+
'windows': ['npm install test'],
1269+
},
12561270
'agents': ['agents/test.md'],
12571271
'slash-commands': ['commands/test.md'],
12581272
'output-styles': ['styles/test.md'],

0 commit comments

Comments
 (0)