Skip to content

Commit 59f9004

Browse files
committed
Add context manager for mock local Claude settings setup
Extract redundant mock home directory setup into a reusable context manager that handles directory creation, settings file writing, and HOME environment patching in one place.
1 parent d4e82a2 commit 59f9004

File tree

1 file changed

+51
-44
lines changed

1 file changed

+51
-44
lines changed

tests/integration/test_install_requirements.py

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
"""
2222

2323
import json
24+
from collections.abc import Iterator
25+
from contextlib import contextmanager
2426
from pathlib import Path
2527
from unittest.mock import patch
2628

@@ -74,6 +76,33 @@ def assert_install_added_hooks(settings_before: dict, settings_after: dict) -> N
7476
)
7577

7678

79+
@contextmanager
80+
def mock_local_claude_settings(
81+
tmp_path: Path, content: str | dict = '{"local": "unchanged"}'
82+
) -> Iterator[Path]:
83+
"""Create mock local Claude settings and patch HOME to use them.
84+
85+
Args:
86+
tmp_path: Temporary directory to create mock home in
87+
content: Settings content (string or dict to be JSON-serialized)
88+
89+
Yields:
90+
Path to the local settings file (for verification after install)
91+
"""
92+
mock_home = tmp_path / "mock_home"
93+
mock_local_claude_dir = mock_home / ".claude"
94+
mock_local_claude_dir.mkdir(parents=True)
95+
96+
local_settings_file = mock_local_claude_dir / "settings.json"
97+
if isinstance(content, dict):
98+
local_settings_file.write_text(json.dumps(content, indent=2))
99+
else:
100+
local_settings_file.write_text(content)
101+
102+
with patch.dict("os.environ", {"HOME": str(mock_home)}):
103+
yield local_settings_file
104+
105+
77106
# =============================================================================
78107
# REQ-001: Install MUST NOT modify local (user home) Claude settings
79108
# =============================================================================
@@ -114,44 +143,30 @@ def test_install_does_not_modify_local_claude_settings(
114143
115144
DO NOT MODIFY THIS TEST.
116145
"""
117-
# Create a mock local Claude settings directory in tmp_path
118-
mock_home = tmp_path / "mock_home"
119-
mock_local_claude_dir = mock_home / ".claude"
120-
mock_local_claude_dir.mkdir(parents=True)
121-
122-
# Create local settings with known content
123-
local_settings_file = mock_local_claude_dir / "settings.json"
124146
original_local_settings = {
125147
"user_preference": "do_not_change",
126148
"api_key_encrypted": "sensitive_data_here",
127149
"custom_config": {"setting1": True, "setting2": "value"},
128150
}
129-
local_settings_file.write_text(json.dumps(original_local_settings, indent=2))
130151

131-
# Record the original file modification time
132-
original_mtime = local_settings_file.stat().st_mtime
133-
134-
# Run install with mocked home directory
135-
with patch.dict("os.environ", {"HOME": str(mock_home)}):
152+
with mock_local_claude_settings(tmp_path, original_local_settings) as local_file:
153+
original_mtime = local_file.stat().st_mtime
136154
run_install(mock_claude_project)
137155

138-
# CRITICAL: Verify local settings were NOT modified
139-
assert local_settings_file.exists(), "Local settings file should still exist"
156+
# CRITICAL: Verify local settings were NOT modified
157+
assert local_file.exists(), "Local settings file should still exist"
140158

141-
# Check content is unchanged
142-
current_local_settings = json.loads(local_settings_file.read_text())
143-
assert current_local_settings == original_local_settings, (
144-
"LOCAL SETTINGS WERE MODIFIED! "
145-
"Install MUST NOT touch user's home directory Claude settings. "
146-
f"Expected: {original_local_settings}, Got: {current_local_settings}"
147-
)
159+
current_local_settings = json.loads(local_file.read_text())
160+
assert current_local_settings == original_local_settings, (
161+
"LOCAL SETTINGS WERE MODIFIED! "
162+
"Install MUST NOT touch user's home directory Claude settings. "
163+
f"Expected: {original_local_settings}, Got: {current_local_settings}"
164+
)
148165

149-
# Check modification time is unchanged
150-
current_mtime = local_settings_file.stat().st_mtime
151-
assert current_mtime == original_mtime, (
152-
"LOCAL SETTINGS FILE WAS TOUCHED! "
153-
"Install MUST NOT access user's home directory Claude settings."
154-
)
166+
assert local_file.stat().st_mtime == original_mtime, (
167+
"LOCAL SETTINGS FILE WAS TOUCHED! "
168+
"Install MUST NOT access user's home directory Claude settings."
169+
)
155170

156171
def test_install_only_modifies_project_settings(
157172
self, mock_claude_project: Path, tmp_path: Path
@@ -164,27 +179,19 @@ def test_install_only_modifies_project_settings(
164179
165180
DO NOT MODIFY THIS TEST.
166181
"""
167-
# Create mock local Claude settings
168-
mock_home = tmp_path / "mock_home"
169-
mock_local_claude_dir = mock_home / ".claude"
170-
mock_local_claude_dir.mkdir(parents=True)
171-
172-
local_settings_file = mock_local_claude_dir / "settings.json"
173182
original_local_content = '{"local": "unchanged"}'
174-
local_settings_file.write_text(original_local_content)
175183

176-
# Run install
177-
with patch.dict("os.environ", {"HOME": str(mock_home)}):
184+
with mock_local_claude_settings(tmp_path, original_local_content) as local_file:
178185
run_install(mock_claude_project)
179186

180-
# Verify LOCAL settings unchanged
181-
assert local_settings_file.read_text() == original_local_content, (
182-
"Local settings were modified! Install must only modify project settings."
183-
)
187+
# Verify LOCAL settings unchanged
188+
assert local_file.read_text() == original_local_content, (
189+
"Local settings were modified! Install must only modify project settings."
190+
)
184191

185-
# Verify PROJECT settings were modified (hooks should be added)
186-
project_settings = get_project_settings(mock_claude_project)
187-
assert "hooks" in project_settings, "Project settings should have hooks after install"
192+
# Verify PROJECT settings were modified (hooks should be added)
193+
project_settings = get_project_settings(mock_claude_project)
194+
assert "hooks" in project_settings, "Project settings should have hooks after install"
188195

189196

190197
# =============================================================================

0 commit comments

Comments
 (0)