Coverage for idle_test/test_config_key.py: 39%

255 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-05-11 13:22 -0700

1"""Test config_key, coverage 98%. 

2 

3Coverage is effectively 100%. Tkinter dialog is mocked, Mac-only line 

4may be skipped, and dummy function in bind test should not be called. 

5Not tested: exit with 'self.advanced or self.keys_ok(keys) ...' False. 

6""" 

7 

8from idlelib import config_key 

9from test.support import requires 

10import unittest 

11from unittest import mock 

12from tkinter import Tk, TclError 

13from idlelib.idle_test.mock_idle import Func 

14from idlelib.idle_test.mock_tk import Mbox_func 

15 

16 

17class ValidationTest(unittest.TestCase): 

18 "Test validation methods: ok, keys_ok, bind_ok." 

19 

20 class Validator(config_key.GetKeysFrame): 

21 def __init__(self, *args, **kwargs): 

22 super().__init__(*args, **kwargs) 

23 class list_keys_final: 

24 get = Func() 

25 self.list_keys_final = list_keys_final 

26 get_modifiers = Func() 

27 showerror = Mbox_func() 

28 

29 @classmethod 

30 def setUpClass(cls): 

31 requires('gui') 

32 cls.root = Tk() 

33 cls.root.withdraw() 

34 keylist = [['<Key-F12>'], ['<Control-Key-x>', '<Control-Key-X>']] 

35 cls.dialog = cls.Validator(cls.root, '<<Test>>', keylist) 

36 

37 @classmethod 

38 def tearDownClass(cls): 

39 del cls.dialog 

40 cls.root.update_idletasks() 

41 cls.root.destroy() 

42 del cls.root 

43 

44 def setUp(self): 

45 self.dialog.showerror.message = '' 

46 # A test that needs a particular final key value should set it. 

47 # A test that sets a non-blank modifier list should reset it to []. 

48 

49 def test_ok_empty(self): 

50 self.dialog.key_string.set(' ') 

51 self.dialog.ok() 

52 self.assertEqual(self.dialog.result, '') 

53 self.assertEqual(self.dialog.showerror.message, 'No key specified.') 

54 

55 def test_ok_good(self): 

56 self.dialog.key_string.set('<Key-F11>') 

57 self.dialog.list_keys_final.get.result = 'F11' 

58 self.dialog.ok() 

59 self.assertEqual(self.dialog.result, '<Key-F11>') 

60 self.assertEqual(self.dialog.showerror.message, '') 

61 

62 def test_keys_no_ending(self): 

63 self.assertFalse(self.dialog.keys_ok('<Control-Shift')) 

64 self.assertIn('Missing the final', self.dialog.showerror.message) 

65 

66 def test_keys_no_modifier_bad(self): 

67 self.dialog.list_keys_final.get.result = 'A' 

68 self.assertFalse(self.dialog.keys_ok('<Key-A>')) 

69 self.assertIn('No modifier', self.dialog.showerror.message) 

70 

71 def test_keys_no_modifier_ok(self): 

72 self.dialog.list_keys_final.get.result = 'F11' 

73 self.assertTrue(self.dialog.keys_ok('<Key-F11>')) 

74 self.assertEqual(self.dialog.showerror.message, '') 

75 

76 def test_keys_shift_bad(self): 

77 self.dialog.list_keys_final.get.result = 'a' 

78 self.dialog.get_modifiers.result = ['Shift'] 

79 self.assertFalse(self.dialog.keys_ok('<a>')) 

80 self.assertIn('shift modifier', self.dialog.showerror.message) 

81 self.dialog.get_modifiers.result = [] 

82 

83 def test_keys_dup(self): 

84 for mods, final, seq in (([], 'F12', '<Key-F12>'), 

85 (['Control'], 'x', '<Control-Key-x>'), 

86 (['Control'], 'X', '<Control-Key-X>')): 

87 with self.subTest(m=mods, f=final, s=seq): 

88 self.dialog.list_keys_final.get.result = final 

89 self.dialog.get_modifiers.result = mods 

90 self.assertFalse(self.dialog.keys_ok(seq)) 

91 self.assertIn('already in use', self.dialog.showerror.message) 

92 self.dialog.get_modifiers.result = [] 

93 

94 def test_bind_ok(self): 

95 self.assertTrue(self.dialog.bind_ok('<Control-Shift-Key-a>')) 

96 self.assertEqual(self.dialog.showerror.message, '') 

97 

98 def test_bind_not_ok(self): 

99 self.assertFalse(self.dialog.bind_ok('<Control-Shift>')) 

100 self.assertIn('not accepted', self.dialog.showerror.message) 

101 

102 

103class ToggleLevelTest(unittest.TestCase): 

104 "Test toggle between Basic and Advanced frames." 

105 

106 @classmethod 

107 def setUpClass(cls): 

108 requires('gui') 

109 cls.root = Tk() 

110 cls.root.withdraw() 

111 cls.dialog = config_key.GetKeysFrame(cls.root, '<<Test>>', []) 

112 

113 @classmethod 

114 def tearDownClass(cls): 

115 del cls.dialog 

116 cls.root.update_idletasks() 

117 cls.root.destroy() 

118 del cls.root 

119 

120 def test_toggle_level(self): 

121 dialog = self.dialog 

122 

123 def stackorder(): 

124 """Get the stack order of the children of the frame. 

125 

126 winfo_children() stores the children in stack order, so 

127 this can be used to check whether a frame is above or 

128 below another one. 

129 """ 

130 for index, child in enumerate(dialog.winfo_children()): 

131 if child._name == 'keyseq_basic': 

132 basic = index 

133 if child._name == 'keyseq_advanced': 

134 advanced = index 

135 return basic, advanced 

136 

137 # New window starts at basic level. 

138 self.assertFalse(dialog.advanced) 

139 self.assertIn('Advanced', dialog.button_level['text']) 

140 basic, advanced = stackorder() 

141 self.assertGreater(basic, advanced) 

142 

143 # Toggle to advanced. 

144 dialog.toggle_level() 

145 self.assertTrue(dialog.advanced) 

146 self.assertIn('Basic', dialog.button_level['text']) 

147 basic, advanced = stackorder() 

148 self.assertGreater(advanced, basic) 

149 

150 # Toggle to basic. 

151 dialog.button_level.invoke() 

152 self.assertFalse(dialog.advanced) 

153 self.assertIn('Advanced', dialog.button_level['text']) 

154 basic, advanced = stackorder() 

155 self.assertGreater(basic, advanced) 

156 

157 

158class KeySelectionTest(unittest.TestCase): 

159 "Test selecting key on Basic frames." 

160 

161 class Basic(config_key.GetKeysFrame): 

162 def __init__(self, *args, **kwargs): 

163 super().__init__(*args, **kwargs) 

164 class list_keys_final: 

165 get = Func() 

166 select_clear = Func() 

167 yview = Func() 

168 self.list_keys_final = list_keys_final 

169 def set_modifiers_for_platform(self): 

170 self.modifiers = ['foo', 'bar', 'BAZ'] 

171 self.modifier_label = {'BAZ': 'ZZZ'} 

172 showerror = Mbox_func() 

173 

174 @classmethod 

175 def setUpClass(cls): 

176 requires('gui') 

177 cls.root = Tk() 

178 cls.root.withdraw() 

179 cls.dialog = cls.Basic(cls.root, '<<Test>>', []) 

180 

181 @classmethod 

182 def tearDownClass(cls): 

183 del cls.dialog 

184 cls.root.update_idletasks() 

185 cls.root.destroy() 

186 del cls.root 

187 

188 def setUp(self): 

189 self.dialog.clear_key_seq() 

190 

191 def test_get_modifiers(self): 

192 dialog = self.dialog 

193 gm = dialog.get_modifiers 

194 eq = self.assertEqual 

195 

196 # Modifiers are set on/off by invoking the checkbutton. 

197 dialog.modifier_checkbuttons['foo'].invoke() 

198 eq(gm(), ['foo']) 

199 

200 dialog.modifier_checkbuttons['BAZ'].invoke() 

201 eq(gm(), ['foo', 'BAZ']) 

202 

203 dialog.modifier_checkbuttons['foo'].invoke() 

204 eq(gm(), ['BAZ']) 

205 

206 @mock.patch.object(config_key.GetKeysFrame, 'get_modifiers') 

207 def test_build_key_string(self, mock_modifiers): 

208 dialog = self.dialog 

209 key = dialog.list_keys_final 

210 string = dialog.key_string.get 

211 eq = self.assertEqual 

212 

213 key.get.result = 'a' 

214 mock_modifiers.return_value = [] 

215 dialog.build_key_string() 

216 eq(string(), '<Key-a>') 

217 

218 mock_modifiers.return_value = ['mymod'] 

219 dialog.build_key_string() 

220 eq(string(), '<mymod-Key-a>') 

221 

222 key.get.result = '' 

223 mock_modifiers.return_value = ['mymod', 'test'] 

224 dialog.build_key_string() 

225 eq(string(), '<mymod-test>') 

226 

227 @mock.patch.object(config_key.GetKeysFrame, 'get_modifiers') 

228 def test_final_key_selected(self, mock_modifiers): 

229 dialog = self.dialog 

230 key = dialog.list_keys_final 

231 string = dialog.key_string.get 

232 eq = self.assertEqual 

233 

234 mock_modifiers.return_value = ['Shift'] 

235 key.get.result = '{' 

236 dialog.final_key_selected() 

237 eq(string(), '<Shift-Key-braceleft>') 

238 

239 

240class CancelWindowTest(unittest.TestCase): 

241 "Simulate user clicking [Cancel] button." 

242 

243 @classmethod 

244 def setUpClass(cls): 

245 requires('gui') 

246 cls.root = Tk() 

247 cls.root.withdraw() 

248 cls.dialog = config_key.GetKeysWindow( 

249 cls.root, 'Title', '<<Test>>', [], _utest=True) 

250 

251 @classmethod 

252 def tearDownClass(cls): 

253 cls.dialog.cancel() 

254 del cls.dialog 

255 cls.root.update_idletasks() 

256 cls.root.destroy() 

257 del cls.root 

258 

259 @mock.patch.object(config_key.GetKeysFrame, 'ok') 

260 def test_cancel(self, mock_frame_ok): 

261 self.assertEqual(self.dialog.winfo_class(), 'Toplevel') 

262 self.dialog.button_cancel.invoke() 

263 with self.assertRaises(TclError): 

264 self.dialog.winfo_class() 

265 self.assertEqual(self.dialog.result, '') 

266 mock_frame_ok.assert_not_called() 

267 

268 

269class OKWindowTest(unittest.TestCase): 

270 "Simulate user clicking [OK] button." 

271 

272 @classmethod 

273 def setUpClass(cls): 

274 requires('gui') 

275 cls.root = Tk() 

276 cls.root.withdraw() 

277 cls.dialog = config_key.GetKeysWindow( 

278 cls.root, 'Title', '<<Test>>', [], _utest=True) 

279 

280 @classmethod 

281 def tearDownClass(cls): 

282 cls.dialog.cancel() 

283 del cls.dialog 

284 cls.root.update_idletasks() 

285 cls.root.destroy() 

286 del cls.root 

287 

288 @mock.patch.object(config_key.GetKeysFrame, 'ok') 

289 def test_ok(self, mock_frame_ok): 

290 self.assertEqual(self.dialog.winfo_class(), 'Toplevel') 

291 self.dialog.button_ok.invoke() 

292 with self.assertRaises(TclError): 

293 self.dialog.winfo_class() 

294 mock_frame_ok.assert_called() 

295 

296 

297class WindowResultTest(unittest.TestCase): 

298 "Test window result get and set." 

299 

300 @classmethod 

301 def setUpClass(cls): 

302 requires('gui') 

303 cls.root = Tk() 

304 cls.root.withdraw() 

305 cls.dialog = config_key.GetKeysWindow( 

306 cls.root, 'Title', '<<Test>>', [], _utest=True) 

307 

308 @classmethod 

309 def tearDownClass(cls): 

310 cls.dialog.cancel() 

311 del cls.dialog 

312 cls.root.update_idletasks() 

313 cls.root.destroy() 

314 del cls.root 

315 

316 def test_result(self): 

317 dialog = self.dialog 

318 eq = self.assertEqual 

319 

320 dialog.result = '' 

321 eq(dialog.result, '') 

322 eq(dialog.frame.result,'') 

323 

324 dialog.result = 'bar' 

325 eq(dialog.result,'bar') 

326 eq(dialog.frame.result,'bar') 

327 

328 dialog.frame.result = 'foo' 

329 eq(dialog.result, 'foo') 

330 eq(dialog.frame.result,'foo') 

331 

332 

333class HelperTest(unittest.TestCase): 

334 "Test module level helper functions." 

335 

336 def test_translate_key(self): 

337 tr = config_key.translate_key 1b

338 eq = self.assertEqual 1b

339 

340 # Letters return unchanged with no 'Shift'. 

341 eq(tr('q', []), 'Key-q') 1b

342 eq(tr('q', ['Control', 'Alt']), 'Key-q') 1b

343 

344 # 'Shift' uppercases single lowercase letters. 

345 eq(tr('q', ['Shift']), 'Key-Q') 1b

346 eq(tr('q', ['Control', 'Shift']), 'Key-Q') 1b

347 eq(tr('q', ['Control', 'Alt', 'Shift']), 'Key-Q') 1b

348 

349 # Convert key name to keysym. 

350 eq(tr('Page Up', []), 'Key-Prior') 1b

351 # 'Shift' doesn't change case when it's not a single char. 

352 eq(tr('*', ['Shift']), 'Key-asterisk') 1b

353 

354 

355if __name__ == '__main__': 355 ↛ 356line 355 didn't jump to line 356, because the condition on line 355 was never true

356 unittest.main(verbosity=2)