Coverage for tests / test_completion / test_completion_install.py: 100%
80 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-09 00:15 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-11-09 00:15 +0000
1import os 1abfgcde
2import subprocess 1abfgcde
3import sys 1abfgcde
4from pathlib import Path 1abfgcde
5from unittest import mock 1abfgcde
7import shellingham 1abfgcde
8from typer.testing import CliRunner 1abfgcde
10from docs_src.typer_app import tutorial001_py310 as mod 1abfgcde
12from ..utils import requires_completion_permission 1abfgcde
14runner = CliRunner() 1abfgcde
15app = mod.app 1abfgcde
18@requires_completion_permission 1abfgcde
19def test_completion_install_no_shell(): 1abfgcde
20 result = subprocess.run( 1abfgcde
21 [sys.executable, "-m", "coverage", "run", mod.__file__, "--install-completion"],
22 capture_output=True,
23 encoding="utf-8",
24 env={
25 **os.environ,
26 "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True",
27 },
28 )
29 assert "Option '--install-completion' requires an argument" in result.stderr 1abfgcde
32@requires_completion_permission 1abfgcde
33def test_completion_install_bash(): 1abfgcde
34 bash_completion_path: Path = Path.home() / ".bashrc" 1abfgcde
35 text = "" 1abfgcde
36 if bash_completion_path.is_file(): 1abfgcde
37 text = bash_completion_path.read_text() 1abcde
38 result = subprocess.run( 1abfgcde
39 [
40 sys.executable,
41 "-m",
42 "coverage",
43 "run",
44 mod.__file__,
45 "--install-completion",
46 "bash",
47 ],
48 capture_output=True,
49 encoding="utf-8",
50 env={
51 **os.environ,
52 "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True",
53 },
54 )
55 new_text = bash_completion_path.read_text() 1abfgcde
56 bash_completion_path.write_text(text) 1abfgcde
57 install_source = Path(".bash_completions/tutorial001_py310.py.sh") 1abfgcde
58 assert str(install_source) not in text 1abfgcde
59 assert str(install_source) in new_text 1abfgcde
60 assert "completion installed in" in result.stdout 1abfgcde
61 assert "Completion will take effect once you restart the terminal" in result.stdout 1abfgcde
62 install_source_path = Path.home() / install_source 1abfgcde
63 assert install_source_path.is_file() 1abfgcde
64 install_content = install_source_path.read_text() 1abfgcde
65 install_source_path.unlink() 1abfgcde
66 assert ( 1abfgcde
67 "complete -o default -F _tutorial001_py310py_completion tutorial001_py310.py"
68 in install_content
69 )
72@requires_completion_permission 1abfgcde
73def test_completion_install_zsh(): 1abfgcde
74 completion_path: Path = Path.home() / ".zshrc" 1abfgcde
75 text = "" 1abfgcde
76 if not completion_path.is_file(): # pragma: no cover 1abfgcde
77 completion_path.write_text('echo "custom .zshrc"') 1abfgcde
78 if completion_path.is_file(): 1abfgcde
79 text = completion_path.read_text() 1abfgcde
80 result = subprocess.run( 1abfgcde
81 [
82 sys.executable,
83 "-m",
84 "coverage",
85 "run",
86 mod.__file__,
87 "--install-completion",
88 "zsh",
89 ],
90 capture_output=True,
91 encoding="utf-8",
92 env={
93 **os.environ,
94 "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True",
95 },
96 )
97 new_text = completion_path.read_text() 1abfgcde
98 completion_path.write_text(text) 1abfgcde
99 zfunc_fragment = "fpath+=~/.zfunc" 1abfgcde
100 assert zfunc_fragment in new_text 1abfgcde
101 assert "completion installed in" in result.stdout 1abfgcde
102 assert "Completion will take effect once you restart the terminal" in result.stdout 1abfgcde
103 install_source_path = Path.home() / ".zfunc/_tutorial001_py310.py" 1abfgcde
104 assert install_source_path.is_file() 1abfgcde
105 install_content = install_source_path.read_text() 1abfgcde
106 install_source_path.unlink() 1abfgcde
107 assert ( 1abfgcde
108 "compdef _tutorial001_py310py_completion tutorial001_py310.py"
109 in install_content
110 )
113@requires_completion_permission 1abfgcde
114def test_completion_install_fish(): 1abfgcde
115 script_path = Path(mod.__file__) 1abfgcde
116 completion_path: Path = ( 1abfgcde
117 Path.home() / f".config/fish/completions/{script_path.name}.fish"
118 )
119 result = subprocess.run( 1abfgcde
120 [
121 sys.executable,
122 "-m",
123 "coverage",
124 "run",
125 mod.__file__,
126 "--install-completion",
127 "fish",
128 ],
129 capture_output=True,
130 encoding="utf-8",
131 env={
132 **os.environ,
133 "_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION": "True",
134 },
135 )
136 new_text = completion_path.read_text() 1abfgcde
137 completion_path.unlink() 1abfgcde
138 assert "complete --command tutorial001_py310.py" in new_text 1abfgcde
139 assert "completion installed in" in result.stdout 1abfgcde
140 assert "Completion will take effect once you restart the terminal" in result.stdout 1abfgcde
143@requires_completion_permission 1abfgcde
144def test_completion_install_powershell(): 1abfgcde
145 completion_path: Path = ( 1abfgcde
146 Path.home() / ".config/powershell/Microsoft.PowerShell_profile.ps1"
147 )
148 completion_path_bytes = f"{completion_path}\n".encode("windows-1252") 1abfgcde
149 text = "" 1abfgcde
150 if completion_path.is_file(): # pragma: no cover 1abfgcde
151 text = completion_path.read_text()
153 with mock.patch.object( 1abfgcde
154 shellingham, "detect_shell", return_value=("pwsh", "/usr/bin/pwsh")
155 ):
156 with mock.patch.object( 1abfgcde
157 subprocess,
158 "run",
159 return_value=subprocess.CompletedProcess(
160 ["pwsh"], returncode=0, stdout=completion_path_bytes
161 ),
162 ):
163 result = runner.invoke(app, ["--install-completion"]) 1abfgcde
164 install_script = "Register-ArgumentCompleter -Native -CommandName mocked-typer-testing-app -ScriptBlock $scriptblock" 1abfgcde
165 parent: Path = completion_path.parent 1abfgcde
166 parent.mkdir(parents=True, exist_ok=True) 1abfgcde
167 completion_path.write_text(install_script) 1abfgcde
168 new_text = completion_path.read_text() 1abfgcde
169 completion_path.write_text(text) 1abfgcde
170 assert install_script not in text 1abfgcde
171 assert install_script in new_text 1abfgcde
172 assert "completion installed in" in result.stdout 1abfgcde
173 assert "Completion will take effect once you restart the terminal" in result.stdout 1abfgcde