|
1 | 1 | import os |
2 | 2 | from pathlib import Path |
3 | | -from unittest import mock |
4 | 3 | from unittest.mock import Mock, patch |
5 | 4 |
|
6 | 5 | import pytest |
7 | 6 | from click.testing import CliRunner |
8 | 7 |
|
9 | 8 | from ggshield.__main__ import cli |
| 9 | +from ggshield.cmd.install import get_default_global_hook_dir_path |
10 | 10 | from ggshield.core.errors import ExitCode |
11 | 11 | from tests.unit.conftest import assert_invoke_exited_with, assert_invoke_ok |
12 | 12 |
|
|
20 | 20 | """ |
21 | 21 |
|
22 | 22 |
|
23 | | -@pytest.fixture(scope="class") |
24 | | -def mockHookDirPath(): |
25 | | - with mock.patch( |
26 | | - "ggshield.cmd.install.get_global_hook_dir_path", |
27 | | - return_value=Path("global/hooks"), |
28 | | - ): |
29 | | - yield |
30 | | - |
31 | | - |
32 | 23 | class TestInstallLocal: |
33 | 24 | def test_local_exist_is_dir(self, cli_fs_runner): |
34 | 25 | os.system("git init") |
@@ -187,69 +178,122 @@ def test_prepush_install( |
187 | 178 | assert_invoke_ok(result) |
188 | 179 |
|
189 | 180 |
|
| 181 | +@pytest.fixture() |
| 182 | +def custom_global_git_config_path(tmp_path, monkeypatch): |
| 183 | + config_path = tmp_path / "global-git-config" |
| 184 | + monkeypatch.setenv("GIT_CONFIG_GLOBAL", str(config_path)) |
| 185 | + yield config_path |
| 186 | + |
| 187 | + |
190 | 188 | class TestInstallGlobal: |
191 | | - def test_global_exist_is_dir(self, cli_fs_runner, mockHookDirPath): |
192 | | - global_hook_path = Path("global/hooks/pre-commit") |
193 | | - global_hook_path.mkdir(parents=True) |
| 189 | + """ |
| 190 | + These tests use the cli_runner fixture and not the cli_fs_runner one. The reason for |
| 191 | + this is they execute git commands and git commands are not run in the fake |
| 192 | + filesystem created by cli_fs_runner so the fake filesystem is useless here. |
| 193 | + """ |
| 194 | + |
| 195 | + def test_global_exist_is_dir( |
| 196 | + self, cli_runner: CliRunner, custom_global_git_config_path: Path |
| 197 | + ): |
| 198 | + global_pre_commit_hook_path = get_default_global_hook_dir_path() / "pre-commit" |
| 199 | + global_pre_commit_hook_path.mkdir(parents=True) |
194 | 200 |
|
195 | | - result = cli_fs_runner.invoke(cli, ["install", "-m", "global"]) |
| 201 | + result = cli_runner.invoke(cli, ["install", "-m", "global"]) |
196 | 202 | assert_invoke_exited_with(result, ExitCode.USAGE_ERROR) |
197 | 203 | assert result.exception |
198 | 204 |
|
199 | | - def test_global_not_exist(self, cli_fs_runner, mockHookDirPath): |
200 | | - global_hook_path = Path("global/hooks/pre-commit") |
201 | | - assert not global_hook_path.exists() |
| 205 | + def test_global_not_exist(self, cli_runner, custom_global_git_config_path: Path): |
| 206 | + global_pre_commit_hook_path = get_default_global_hook_dir_path() / "pre-commit" |
| 207 | + assert not global_pre_commit_hook_path.exists() |
| 208 | + |
| 209 | + result = cli_runner.invoke(cli, ["install", "-m", "global"]) |
| 210 | + assert global_pre_commit_hook_path.is_file() |
| 211 | + assert_invoke_ok(result) |
| 212 | + assert ( |
| 213 | + f"pre-commit successfully added in {global_pre_commit_hook_path}" |
| 214 | + in result.output |
| 215 | + ) |
| 216 | + |
| 217 | + def test_install_custom_global_hook_dir( |
| 218 | + self, cli_runner: CliRunner, tmp_path: Path, custom_global_git_config_path: Path |
| 219 | + ): |
| 220 | + """ |
| 221 | + GIVEN an existing global git config |
| 222 | + AND a custom value for core.hooksPath in the global git config |
| 223 | + WHEN `install -m global` is called |
| 224 | + THEN it installs the hook in the custom core.hooksPath dir |
| 225 | + """ |
| 226 | + custom_hooks_dir = tmp_path / "custom-hooks-dir" |
| 227 | + custom_pre_commit_path = custom_hooks_dir / "pre-commit" |
| 228 | + custom_global_git_config_path.write_text( |
| 229 | + f"[core]\nhooksPath = {custom_hooks_dir.as_posix()}\n", encoding="utf-8" |
| 230 | + ) |
202 | 231 |
|
203 | | - result = cli_fs_runner.invoke(cli, ["install", "-m", "global"]) |
204 | | - assert global_hook_path.is_file() |
| 232 | + result = cli_runner.invoke(cli, ["install", "-m", "global"]) |
205 | 233 | assert_invoke_ok(result) |
206 | | - assert f"pre-commit successfully added in {global_hook_path}" in result.output |
| 234 | + assert custom_pre_commit_path.is_file() |
| 235 | + assert ( |
| 236 | + f"pre-commit successfully added in {custom_pre_commit_path}" |
| 237 | + in result.output |
| 238 | + ) |
207 | 239 |
|
208 | 240 | @pytest.mark.parametrize("hook_type", ["pre-push", "pre-commit"]) |
209 | | - @patch("ggshield.cmd.install.get_global_hook_dir_path") |
210 | 241 | def test_install_global( |
211 | 242 | self, |
212 | | - get_global_hook_dir_path_mock: Mock, |
213 | 243 | hook_type: str, |
214 | | - cli_fs_runner: CliRunner, |
| 244 | + cli_runner: CliRunner, |
| 245 | + custom_global_git_config_path: Path, |
215 | 246 | ): |
216 | 247 | """ |
217 | 248 | GIVEN None |
218 | 249 | WHEN the command is run |
219 | 250 | THEN it should create a pre-push git hook script in the global path |
220 | 251 | """ |
221 | | - global_hooks_dir = Path("global_hooks") |
222 | | - get_global_hook_dir_path_mock.return_value = global_hooks_dir |
223 | | - result = cli_fs_runner.invoke( |
| 252 | + |
| 253 | + result = cli_runner.invoke( |
224 | 254 | cli, |
225 | 255 | ["install", "-m", "global", "-t", hook_type], |
226 | 256 | ) |
227 | 257 |
|
228 | | - hook_path = global_hooks_dir / hook_type |
| 258 | + hook_path = get_default_global_hook_dir_path() / hook_type |
229 | 259 | hook_str = hook_path.read_text() |
230 | 260 | assert f"if [ -f .git/hooks/{hook_type} ]; then" in hook_str |
231 | 261 | assert f"ggshield secret scan {hook_type}" in hook_str |
232 | 262 |
|
233 | 263 | assert f"{hook_type} successfully added in {hook_path}\n" in result.output |
234 | 264 | assert_invoke_ok(result) |
235 | 265 |
|
236 | | - def test_global_exist_not_force(self, cli_fs_runner, mockHookDirPath): |
237 | | - hook_path = Path("global/hooks/pre-commit") |
| 266 | + def test_global_exist_not_force( |
| 267 | + self, cli_runner: CliRunner, custom_global_git_config_path: Path |
| 268 | + ): |
| 269 | + """ |
| 270 | + GIVEN a global hook dir with an exising pre-commit script |
| 271 | + WHEN install is called |
| 272 | + THEN it fails |
| 273 | + """ |
| 274 | + hook_path = get_default_global_hook_dir_path() / "pre-commit" |
238 | 275 | hook_path.parent.mkdir(parents=True, exist_ok=True) |
239 | 276 | hook_path.write_text("pre-commit file") |
240 | 277 | assert hook_path.is_file() |
241 | 278 |
|
242 | | - result = cli_fs_runner.invoke(cli, ["install", "-m", "global"]) |
| 279 | + result = cli_runner.invoke(cli, ["install", "-m", "global"]) |
243 | 280 | assert_invoke_exited_with(result, ExitCode.UNEXPECTED_ERROR) |
244 | 281 | assert result.exception |
245 | 282 | assert f"Error: {hook_path} already exists." in result.output |
246 | 283 |
|
247 | | - def test_global_exist_force(self, cli_fs_runner, mockHookDirPath): |
248 | | - hook_path = Path("global/hooks/pre-commit") |
| 284 | + def test_global_exist_force( |
| 285 | + self, cli_runner: CliRunner, custom_global_git_config_path: Path |
| 286 | + ): |
| 287 | + """ |
| 288 | + GIVEN a global hook dir with an exising pre-commit script |
| 289 | + WHEN install is called with -f |
| 290 | + THEN it ignores the fact that the pre-commit script exists and succeeds |
| 291 | + """ |
| 292 | + hook_path = get_default_global_hook_dir_path() / "pre-commit" |
249 | 293 | hook_path.parent.mkdir(parents=True, exist_ok=True) |
250 | 294 | hook_path.write_text("pre-commit file") |
251 | 295 | assert hook_path.is_file() |
252 | 296 |
|
253 | | - result = cli_fs_runner.invoke(cli, ["install", "-m", "global", "-f"]) |
| 297 | + result = cli_runner.invoke(cli, ["install", "-m", "global", "-f"]) |
254 | 298 | assert_invoke_ok(result) |
255 | 299 | assert f"pre-commit successfully added in {hook_path}" in result.output |
0 commit comments