Coverage for tests / test_rich_markup_mode.py: 100%

122 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-03-26 21:46 +0000

1import os 1abcdefg

2import subprocess 1abcdefg

3import sys 1abcdefg

4 

5import pytest 1abcdefg

6import typer 1abcdefg

7import typer.completion 1abcdefg

8from typer.testing import CliRunner 1abcdefg

9 

10runner = CliRunner() 1abcdefg

11rounded = ["╭", "─", "┬", "╮", "│", "├", "┼", "┤", "╰", "┴", "╯"] 1abcdefg

12 

13 

14def test_rich_markup_mode_none(): 1abcdefg

15 app = typer.Typer(rich_markup_mode=None) 1abcdefg

16 

17 @app.command() 1abcdefg

18 def main(arg: str): 1abcdefg

19 """Main function""" 

20 print(f"Hello {arg}") 1abcdefg

21 

22 assert app.rich_markup_mode is None 1abcdefg

23 

24 result = runner.invoke(app, ["World"]) 1abcdefg

25 assert "Hello World" in result.stdout 1abcdefg

26 

27 result = runner.invoke(app, ["--help"]) 1abcdefg

28 assert "ARG [required]" in result.stdout 1abcdefg

29 assert all(c not in result.stdout for c in rounded) 1abcdefg

30 

31 

32def test_rich_markup_mode_rich(): 1abcdefg

33 app = typer.Typer(rich_markup_mode="rich") 1abcdefg

34 

35 @app.command() 1abcdefg

36 def main(arg: str): 1abcdefg

37 """Main function""" 

38 print(f"Hello {arg}") 1abcdefg

39 

40 assert app.rich_markup_mode == "rich" 1abcdefg

41 

42 result = runner.invoke(app, ["World"]) 1abcdefg

43 assert "Hello World" in result.stdout 1abcdefg

44 

45 result = runner.invoke(app, ["--help"]) 1abcdefg

46 assert any(c in result.stdout for c in rounded) 1abcdefg

47 

48 

49@pytest.mark.parametrize( 1abcdefg

50 "env_var_value, expected_result", 

51 [ 

52 ("1", True), 

53 ("True", True), 

54 ("TRUE", True), 

55 ("true", True), 

56 ("0", False), 

57 ("False", False), 

58 ("FALSE", False), 

59 ("false", False), 

60 ("somerandomvalue", True), 

61 ], 

62) 

63def test_rich_markup_mode_envvar(env_var_value: str, expected_result: bool): 1abcdefg

64 result = subprocess.run( 1abcdefg

65 [ 

66 sys.executable, 

67 "-m", 

68 "coverage", 

69 "run", 

70 "-m", 

71 "typer", 

72 "tests/assets/cli/sample.py", 

73 "--help", 

74 ], 

75 capture_output=True, 

76 env={ 

77 **os.environ, 

78 "TYPER_USE_RICH": env_var_value, 

79 "PYTHONIOENCODING": "utf-8", 

80 }, 

81 encoding="utf-8", 

82 ) 

83 assert any(c in result.stdout for c in rounded) == expected_result 1abcdefg

84 

85 

86@pytest.mark.parametrize( 1abcdefg

87 "mode,lines", 

88 [ 

89 pytest.param( 

90 "markdown", 

91 ["First line", "", "Line 1", "", "Line 2", "", "Line 3", ""], 

92 ), 

93 pytest.param( 

94 "rich", ["First line", "", "Line 1", "", "Line 2", "", "Line 3", ""] 

95 ), 

96 pytest.param( 

97 None, ["First line", "", "Line 1", "", "Line 2", "", "Line 3", ""] 

98 ), 

99 ], 

100) 

101def test_markup_mode_newline_pr815(mode: str, lines: list[str]): 1abcdefg

102 app = typer.Typer(rich_markup_mode=mode) 1abcdefg

103 

104 @app.command() 1abcdefg

105 def main(arg: str): 1abcdefg

106 """First line 

107 

108 Line 1 

109 

110 Line 2 

111 

112 Line 3 

113 """ 

114 print(f"Hello {arg}") 1abcdefg

115 

116 assert app.rich_markup_mode == mode 1abcdefg

117 

118 result = runner.invoke(app, ["World"]) 1abcdefg

119 assert "Hello World" in result.stdout 1abcdefg

120 

121 result = runner.invoke(app, ["--help"]) 1abcdefg

122 result_lines = [line.strip() for line in result.stdout.split("\n")] 1abcdefg

123 if mode: 1abcdefg

124 assert any(c in result.stdout for c in rounded) 1abcdefg

125 help_start = result_lines.index("First line") 1abcdefg

126 arg_start = [i for i, row in enumerate(result_lines) if "Arguments" in row][0] 1abcdefg

127 assert help_start != -1 1abcdefg

128 assert result_lines[help_start:arg_start] == lines 1abcdefg

129 

130 

131@pytest.mark.parametrize( 1abcdefg

132 "mode,lines", 

133 [ 

134 pytest.param("markdown", ["First line", "", "Line 1 Line 2 Line 3", ""]), 

135 pytest.param("rich", ["First line", "", "Line 1", "Line 2", "Line 3", ""]), 

136 pytest.param(None, ["First line", "", "Line 1 Line 2 Line 3", ""]), 

137 ], 

138) 

139def test_markup_mode_newline_issue447(mode: str, lines: list[str]): 1abcdefg

140 app = typer.Typer(rich_markup_mode=mode) 1abcdefg

141 

142 @app.command() 1abcdefg

143 def main(arg: str): 1abcdefg

144 """First line 

145 

146 Line 1 

147 Line 2 

148 Line 3 

149 """ 

150 print(f"Hello {arg}") 1abcdefg

151 

152 assert app.rich_markup_mode == mode 1abcdefg

153 

154 result = runner.invoke(app, ["World"]) 1abcdefg

155 assert "Hello World" in result.stdout 1abcdefg

156 

157 result = runner.invoke(app, ["--help"]) 1abcdefg

158 result_lines = [line.strip() for line in result.stdout.split("\n")] 1abcdefg

159 if mode: 1abcdefg

160 assert any(c in result.stdout for c in rounded) 1abcdefg

161 help_start = result_lines.index("First line") 1abcdefg

162 arg_start = [i for i, row in enumerate(result_lines) if "Arguments" in row][0] 1abcdefg

163 assert help_start != -1 1abcdefg

164 assert result_lines[help_start:arg_start] == lines 1abcdefg

165 

166 

167@pytest.mark.parametrize( 1abcdefg

168 "mode,lines", 

169 [ 

170 pytest.param( 

171 "markdown", 

172 [ 

173 "This header is long", 

174 "", 

175 "Line 1", 

176 "", 

177 "Line 2 continues here", 

178 "", 

179 "Line 3", 

180 "", 

181 ], 

182 ), 

183 pytest.param( 

184 "rich", 

185 [ 

186 "This header is long", 

187 "", 

188 "Line 1", 

189 "", 

190 "Line 2", 

191 "continues here", 

192 "", 

193 "Line 3", 

194 "", 

195 ], 

196 ), 

197 pytest.param( 

198 None, 

199 [ 

200 "This header is long", 

201 "", 

202 "Line 1", 

203 "", 

204 "Line 2 continues here", 

205 "", 

206 "Line 3", 

207 "", 

208 ], 

209 ), 

210 ], 

211) 

212def test_markup_mode_newline_mixed(mode: str, lines: list[str]): 1abcdefg

213 app = typer.Typer(rich_markup_mode=mode) 1abcdefg

214 

215 @app.command() 1abcdefg

216 def main(arg: str): 1abcdefg

217 """This header 

218 is long 

219 

220 Line 1 

221 

222 Line 2 

223 continues here 

224 

225 Line 3 

226 """ 

227 print(f"Hello {arg}") 1abcdefg

228 

229 assert app.rich_markup_mode == mode 1abcdefg

230 

231 result = runner.invoke(app, ["World"]) 1abcdefg

232 assert "Hello World" in result.stdout 1abcdefg

233 

234 result = runner.invoke(app, ["--help"]) 1abcdefg

235 result_lines = [line.strip() for line in result.stdout.split("\n")] 1abcdefg

236 if mode: 1abcdefg

237 assert any(c in result.stdout for c in rounded) 1abcdefg

238 help_start = [i for i, row in enumerate(result_lines) if "This header" in row][0] 1abcdefg

239 arg_start = [i for i, row in enumerate(result_lines) if "Arguments" in row][0] 1abcdefg

240 assert help_start != -1 1abcdefg

241 assert result_lines[help_start:arg_start] == lines 1abcdefg

242 

243 

244@pytest.mark.parametrize( 1abcdefg

245 "mode,lines", 

246 [ 

247 pytest.param( 

248 "markdown", 

249 ["First line", "", "• 1", "• 2", "• 3", ""], 

250 marks=pytest.mark.xfail, 

251 ), 

252 pytest.param("rich", ["First line", "", "- 1", "- 2", "- 3", ""]), 

253 pytest.param(None, ["First line", "", "- 1 - 2 - 3", ""]), 

254 ], 

255) 

256def test_markup_mode_bullets_single_newline(mode: str, lines: list[str]): 1abcdefg

257 app = typer.Typer(rich_markup_mode=mode) 1abcdefg

258 

259 @app.command() 1abcdefg

260 def main(arg: str): 1abcdefg

261 """First line 

262 

263 - 1 

264 - 2 

265 - 3 

266 """ 

267 print(f"Hello {arg}") 1abcdefg

268 

269 assert app.rich_markup_mode == mode 1abcdefg

270 

271 result = runner.invoke(app, ["World"]) 1abcdefg

272 assert "Hello World" in result.stdout 1abcdefg

273 

274 result = runner.invoke(app, ["--help"]) 1abcdefg

275 result_lines = [line.strip() for line in result.stdout.split("\n")] 1abcdefg

276 if mode: 1abcdefg

277 assert any(c in result.stdout for c in rounded) 1abcdefg

278 help_start = result_lines.index("First line") 1abcdefg

279 arg_start = [i for i, row in enumerate(result_lines) if "Arguments" in row][0] 1abcdefg

280 assert help_start != -1 1abcdefg

281 assert result_lines[help_start:arg_start] == lines 1abcdefg

282 

283 

284@pytest.mark.parametrize( 1abcdefg

285 "mode,lines", 

286 [ 

287 pytest.param( 

288 "markdown", 

289 ["First line", "", "• 1", "• 2", "• 3", ""], 

290 marks=pytest.mark.xfail, 

291 ), 

292 ( 

293 "rich", 

294 ["First line", "", "- 1", "", "- 2", "", "- 3", ""], 

295 ), 

296 (None, ["First line", "", "- 1", "", "- 2", "", "- 3", ""]), 

297 ], 

298) 

299def test_markup_mode_bullets_double_newline(mode: str, lines: list[str]): 1abcdefg

300 app = typer.Typer(rich_markup_mode=mode) 1abcdefg

301 

302 @app.command() 1abcdefg

303 def main(arg: str): 1abcdefg

304 """First line 

305 

306 - 1 

307 

308 - 2 

309 

310 - 3 

311 """ 

312 print(f"Hello {arg}") 1abcdefg

313 

314 assert app.rich_markup_mode == mode 1abcdefg

315 

316 result = runner.invoke(app, ["World"]) 1abcdefg

317 assert "Hello World" in result.stdout 1abcdefg

318 

319 result = runner.invoke(app, ["--help"]) 1abcdefg

320 result_lines = [line.strip() for line in result.stdout.split("\n")] 1abcdefg

321 if mode: 1abcdefg

322 assert any(c in result.stdout for c in rounded) 1abcdefg

323 help_start = result_lines.index("First line") 1abcdefg

324 arg_start = [i for i, row in enumerate(result_lines) if "Arguments" in row][0] 1abcdefg

325 assert help_start != -1 1abcdefg

326 assert result_lines[help_start:arg_start] == lines 1abcdefg

327 

328 

329def test_markup_mode_default(): 1abcdefg

330 # We're assuming the test suite is run with rich installed 

331 app = typer.Typer() 1abcdefg

332 assert app.rich_markup_mode == "rich" 1abcdefg