Coverage for tests / test_completion / test_completion.py: 100%

60 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-11-09 00:15 +0000

1import os 1abcdefg

2import subprocess 1abcdefg

3import sys 1abcdefg

4from pathlib import Path 1abcdefg

5 

6from typer._click.shell_completion import CompletionItem 1abcdefg

7 

8from docs_src.typer_app import tutorial001_py310 as mod 1abcdefg

9 

10from ..utils import needs_bash, needs_linux, requires_completion_permission 1abcdefg

11from . import completion_option_then_argument as mod_option_arg 1abcdefg

12 

13 

14@needs_bash 1abcdefg

15@needs_linux 1abcdefg

16def test_show_completion(): 1abcdefg

17 result = subprocess.run( 1ab

18 [ 

19 "bash", 

20 "-c", 

21 f"'{sys.executable}' -m coverage run '{mod.__file__}' --show-completion", 

22 ], 

23 capture_output=True, 

24 encoding="utf-8", 

25 env={**os.environ, "SHELL": "/bin/bash", "_TYPER_COMPLETE_TESTING": "True"}, 

26 ) 

27 assert "_TUTORIAL001_PY310.PY_COMPLETE=complete_bash" in result.stdout 1ab

28 

29 

30@needs_bash 1abcdefg

31@needs_linux 1abcdefg

32@requires_completion_permission 1abcdefg

33def test_install_completion(): 1abcdefg

34 bash_completion_path: Path = Path.home() / ".bashrc" 1ab

35 text = "" 1ab

36 if bash_completion_path.is_file(): # pragma: no cover 1ab

37 text = bash_completion_path.read_text() 1ab

38 result = subprocess.run( 1ab

39 [ 

40 "bash", 

41 "-c", 

42 f"'{sys.executable}' -m coverage run '{mod.__file__}' --install-completion", 

43 ], 

44 capture_output=True, 

45 encoding="utf-8", 

46 env={**os.environ, "SHELL": "/bin/bash", "_TYPER_COMPLETE_TESTING": "True"}, 

47 ) 

48 new_text = bash_completion_path.read_text() 1ab

49 bash_completion_path.write_text(text) 1ab

50 assert "source" in new_text 1ab

51 assert str(Path(".bash_completions/tutorial001_py310.py.sh")) in new_text 1ab

52 assert "completion installed in" in result.stdout 1ab

53 assert "Completion will take effect once you restart the terminal" in result.stdout 1ab

54 

55 

56def test_completion_invalid_instruction(): 1abcdefg

57 result = subprocess.run( 1abcdefg

58 [sys.executable, "-m", "coverage", "run", mod.__file__], 

59 capture_output=True, 

60 encoding="utf-8", 

61 env={ 

62 **os.environ, 

63 "_TUTORIAL001_PY310.PY_COMPLETE": "sourcebash", 

64 }, 

65 ) 

66 assert result.returncode != 0 1abcdefg

67 assert "Invalid completion instruction." in result.stderr 1abcdefg

68 

69 

70def test_completion_source_bash(): 1abcdefg

71 result = subprocess.run( 1abcdefg

72 [sys.executable, "-m", "coverage", "run", mod.__file__], 

73 capture_output=True, 

74 encoding="utf-8", 

75 env={ 

76 **os.environ, 

77 "_TUTORIAL001_PY310.PY_COMPLETE": "source_bash", 

78 }, 

79 ) 

80 assert ( 1abcdefg

81 "complete -o default -F _tutorial001_py310py_completion tutorial001_py310.py" 

82 in result.stdout 

83 ) 

84 

85 

86def test_completion_source_invalid_shell(): 1abcdefg

87 result = subprocess.run( 1abcdefg

88 [sys.executable, "-m", "coverage", "run", mod.__file__], 

89 capture_output=True, 

90 encoding="utf-8", 

91 env={ 

92 **os.environ, 

93 "_TUTORIAL001_PY310.PY_COMPLETE": "source_xxx", 

94 }, 

95 ) 

96 assert "Shell xxx not supported." in result.stderr 1abcdefg

97 

98 

99def test_completion_source_invalid_instruction(): 1abcdefg

100 result = subprocess.run( 1abcdefg

101 [sys.executable, "-m", "coverage", "run", mod.__file__], 

102 capture_output=True, 

103 encoding="utf-8", 

104 env={ 

105 **os.environ, 

106 "_TUTORIAL001_PY310.PY_COMPLETE": "explode_bash", 

107 }, 

108 ) 

109 assert 'Completion instruction "explode" not supported.' in result.stderr 1abcdefg

110 

111 

112def test_completion_source_zsh(): 1abcdefg

113 result = subprocess.run( 1abcdefg

114 [sys.executable, "-m", "coverage", "run", mod.__file__], 

115 capture_output=True, 

116 encoding="utf-8", 

117 env={ 

118 **os.environ, 

119 "_TUTORIAL001_PY310.PY_COMPLETE": "source_zsh", 

120 }, 

121 ) 

122 assert ( 1abcdefg

123 "compdef _tutorial001_py310py_completion tutorial001_py310.py" in result.stdout 

124 ) 

125 

126 

127def test_completion_source_fish(): 1abcdefg

128 result = subprocess.run( 1abcdefg

129 [sys.executable, "-m", "coverage", "run", mod.__file__], 

130 capture_output=True, 

131 encoding="utf-8", 

132 env={ 

133 **os.environ, 

134 "_TUTORIAL001_PY310.PY_COMPLETE": "source_fish", 

135 }, 

136 ) 

137 assert "complete --command tutorial001_py310.py --no-files" in result.stdout 1abcdefg

138 

139 

140def test_completion_source_powershell(): 1abcdefg

141 result = subprocess.run( 1abcdefg

142 [sys.executable, "-m", "coverage", "run", mod.__file__], 

143 capture_output=True, 

144 encoding="utf-8", 

145 env={ 

146 **os.environ, 

147 "_TUTORIAL001_PY310.PY_COMPLETE": "source_powershell", 

148 }, 

149 ) 

150 assert ( 1abcdefg

151 "Register-ArgumentCompleter -Native -CommandName tutorial001_py310.py -ScriptBlock $scriptblock" 

152 in result.stdout 

153 ) 

154 

155 

156def test_completion_source_pwsh(): 1abcdefg

157 result = subprocess.run( 1abcdefg

158 [sys.executable, "-m", "coverage", "run", mod.__file__], 

159 capture_output=True, 

160 encoding="utf-8", 

161 env={ 

162 **os.environ, 

163 "_TUTORIAL001_PY310.PY_COMPLETE": "source_pwsh", 

164 }, 

165 ) 

166 assert ( 1abcdefg

167 "Register-ArgumentCompleter -Native -CommandName tutorial001_py310.py -ScriptBlock $scriptblock" 

168 in result.stdout 

169 ) 

170 

171 

172def test_completion_option_argument() -> None: 1abcdefg

173 file_name = Path(mod_option_arg.__file__).name 1abcdefg

174 result = subprocess.run( 1abcdefg

175 [sys.executable, "-m", "coverage", "run", mod_option_arg.__file__, " "], 

176 capture_output=True, 

177 encoding="utf-8", 

178 env={ 

179 **os.environ, 

180 f"_{file_name.upper()}_COMPLETE": "complete_bash", 

181 "COMP_WORDS": f"{file_name} --name chosen ", 

182 "COMP_CWORD": "3", 

183 }, 

184 ) 

185 assert "arg-choice" in result.stdout 1abcdefg

186 assert "opt-choice" not in result.stdout 1abcdefg

187 

188 

189def test_completion_item_getattr() -> None: 1abcdefg

190 item = CompletionItem("demo", source="envvar") 1abcdefg

191 

192 assert item.source == "envvar" 1abcdefg

193 assert item.missing is None 1abcdefg