17db96d56Sopenharmony_ci"""Test config_key, coverage 98%. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciCoverage is effectively 100%. Tkinter dialog is mocked, Mac-only line 47db96d56Sopenharmony_cimay be skipped, and dummy function in bind test should not be called. 57db96d56Sopenharmony_ciNot tested: exit with 'self.advanced or self.keys_ok(keys) ...' False. 67db96d56Sopenharmony_ci""" 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_cifrom idlelib import config_key 97db96d56Sopenharmony_cifrom test.support import requires 107db96d56Sopenharmony_ciimport unittest 117db96d56Sopenharmony_cifrom unittest import mock 127db96d56Sopenharmony_cifrom tkinter import Tk, TclError 137db96d56Sopenharmony_cifrom idlelib.idle_test.mock_idle import Func 147db96d56Sopenharmony_cifrom idlelib.idle_test.mock_tk import Mbox_func 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ciclass ValidationTest(unittest.TestCase): 187db96d56Sopenharmony_ci "Test validation methods: ok, keys_ok, bind_ok." 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci class Validator(config_key.GetKeysFrame): 217db96d56Sopenharmony_ci def __init__(self, *args, **kwargs): 227db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 237db96d56Sopenharmony_ci class list_keys_final: 247db96d56Sopenharmony_ci get = Func() 257db96d56Sopenharmony_ci self.list_keys_final = list_keys_final 267db96d56Sopenharmony_ci get_modifiers = Func() 277db96d56Sopenharmony_ci showerror = Mbox_func() 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci @classmethod 307db96d56Sopenharmony_ci def setUpClass(cls): 317db96d56Sopenharmony_ci requires('gui') 327db96d56Sopenharmony_ci cls.root = Tk() 337db96d56Sopenharmony_ci cls.root.withdraw() 347db96d56Sopenharmony_ci keylist = [['<Key-F12>'], ['<Control-Key-x>', '<Control-Key-X>']] 357db96d56Sopenharmony_ci cls.dialog = cls.Validator(cls.root, '<<Test>>', keylist) 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci @classmethod 387db96d56Sopenharmony_ci def tearDownClass(cls): 397db96d56Sopenharmony_ci del cls.dialog 407db96d56Sopenharmony_ci cls.root.update_idletasks() 417db96d56Sopenharmony_ci cls.root.destroy() 427db96d56Sopenharmony_ci del cls.root 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci def setUp(self): 457db96d56Sopenharmony_ci self.dialog.showerror.message = '' 467db96d56Sopenharmony_ci # A test that needs a particular final key value should set it. 477db96d56Sopenharmony_ci # A test that sets a non-blank modifier list should reset it to []. 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci def test_ok_empty(self): 507db96d56Sopenharmony_ci self.dialog.key_string.set(' ') 517db96d56Sopenharmony_ci self.dialog.ok() 527db96d56Sopenharmony_ci self.assertEqual(self.dialog.result, '') 537db96d56Sopenharmony_ci self.assertEqual(self.dialog.showerror.message, 'No key specified.') 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci def test_ok_good(self): 567db96d56Sopenharmony_ci self.dialog.key_string.set('<Key-F11>') 577db96d56Sopenharmony_ci self.dialog.list_keys_final.get.result = 'F11' 587db96d56Sopenharmony_ci self.dialog.ok() 597db96d56Sopenharmony_ci self.assertEqual(self.dialog.result, '<Key-F11>') 607db96d56Sopenharmony_ci self.assertEqual(self.dialog.showerror.message, '') 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci def test_keys_no_ending(self): 637db96d56Sopenharmony_ci self.assertFalse(self.dialog.keys_ok('<Control-Shift')) 647db96d56Sopenharmony_ci self.assertIn('Missing the final', self.dialog.showerror.message) 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci def test_keys_no_modifier_bad(self): 677db96d56Sopenharmony_ci self.dialog.list_keys_final.get.result = 'A' 687db96d56Sopenharmony_ci self.assertFalse(self.dialog.keys_ok('<Key-A>')) 697db96d56Sopenharmony_ci self.assertIn('No modifier', self.dialog.showerror.message) 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci def test_keys_no_modifier_ok(self): 727db96d56Sopenharmony_ci self.dialog.list_keys_final.get.result = 'F11' 737db96d56Sopenharmony_ci self.assertTrue(self.dialog.keys_ok('<Key-F11>')) 747db96d56Sopenharmony_ci self.assertEqual(self.dialog.showerror.message, '') 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci def test_keys_shift_bad(self): 777db96d56Sopenharmony_ci self.dialog.list_keys_final.get.result = 'a' 787db96d56Sopenharmony_ci self.dialog.get_modifiers.result = ['Shift'] 797db96d56Sopenharmony_ci self.assertFalse(self.dialog.keys_ok('<a>')) 807db96d56Sopenharmony_ci self.assertIn('shift modifier', self.dialog.showerror.message) 817db96d56Sopenharmony_ci self.dialog.get_modifiers.result = [] 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci def test_keys_dup(self): 847db96d56Sopenharmony_ci for mods, final, seq in (([], 'F12', '<Key-F12>'), 857db96d56Sopenharmony_ci (['Control'], 'x', '<Control-Key-x>'), 867db96d56Sopenharmony_ci (['Control'], 'X', '<Control-Key-X>')): 877db96d56Sopenharmony_ci with self.subTest(m=mods, f=final, s=seq): 887db96d56Sopenharmony_ci self.dialog.list_keys_final.get.result = final 897db96d56Sopenharmony_ci self.dialog.get_modifiers.result = mods 907db96d56Sopenharmony_ci self.assertFalse(self.dialog.keys_ok(seq)) 917db96d56Sopenharmony_ci self.assertIn('already in use', self.dialog.showerror.message) 927db96d56Sopenharmony_ci self.dialog.get_modifiers.result = [] 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci def test_bind_ok(self): 957db96d56Sopenharmony_ci self.assertTrue(self.dialog.bind_ok('<Control-Shift-Key-a>')) 967db96d56Sopenharmony_ci self.assertEqual(self.dialog.showerror.message, '') 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci def test_bind_not_ok(self): 997db96d56Sopenharmony_ci self.assertFalse(self.dialog.bind_ok('<Control-Shift>')) 1007db96d56Sopenharmony_ci self.assertIn('not accepted', self.dialog.showerror.message) 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ciclass ToggleLevelTest(unittest.TestCase): 1047db96d56Sopenharmony_ci "Test toggle between Basic and Advanced frames." 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci @classmethod 1077db96d56Sopenharmony_ci def setUpClass(cls): 1087db96d56Sopenharmony_ci requires('gui') 1097db96d56Sopenharmony_ci cls.root = Tk() 1107db96d56Sopenharmony_ci cls.root.withdraw() 1117db96d56Sopenharmony_ci cls.dialog = config_key.GetKeysFrame(cls.root, '<<Test>>', []) 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci @classmethod 1147db96d56Sopenharmony_ci def tearDownClass(cls): 1157db96d56Sopenharmony_ci del cls.dialog 1167db96d56Sopenharmony_ci cls.root.update_idletasks() 1177db96d56Sopenharmony_ci cls.root.destroy() 1187db96d56Sopenharmony_ci del cls.root 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci def test_toggle_level(self): 1217db96d56Sopenharmony_ci dialog = self.dialog 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci def stackorder(): 1247db96d56Sopenharmony_ci """Get the stack order of the children of the frame. 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci winfo_children() stores the children in stack order, so 1277db96d56Sopenharmony_ci this can be used to check whether a frame is above or 1287db96d56Sopenharmony_ci below another one. 1297db96d56Sopenharmony_ci """ 1307db96d56Sopenharmony_ci for index, child in enumerate(dialog.winfo_children()): 1317db96d56Sopenharmony_ci if child._name == 'keyseq_basic': 1327db96d56Sopenharmony_ci basic = index 1337db96d56Sopenharmony_ci if child._name == 'keyseq_advanced': 1347db96d56Sopenharmony_ci advanced = index 1357db96d56Sopenharmony_ci return basic, advanced 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci # New window starts at basic level. 1387db96d56Sopenharmony_ci self.assertFalse(dialog.advanced) 1397db96d56Sopenharmony_ci self.assertIn('Advanced', dialog.button_level['text']) 1407db96d56Sopenharmony_ci basic, advanced = stackorder() 1417db96d56Sopenharmony_ci self.assertGreater(basic, advanced) 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci # Toggle to advanced. 1447db96d56Sopenharmony_ci dialog.toggle_level() 1457db96d56Sopenharmony_ci self.assertTrue(dialog.advanced) 1467db96d56Sopenharmony_ci self.assertIn('Basic', dialog.button_level['text']) 1477db96d56Sopenharmony_ci basic, advanced = stackorder() 1487db96d56Sopenharmony_ci self.assertGreater(advanced, basic) 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci # Toggle to basic. 1517db96d56Sopenharmony_ci dialog.button_level.invoke() 1527db96d56Sopenharmony_ci self.assertFalse(dialog.advanced) 1537db96d56Sopenharmony_ci self.assertIn('Advanced', dialog.button_level['text']) 1547db96d56Sopenharmony_ci basic, advanced = stackorder() 1557db96d56Sopenharmony_ci self.assertGreater(basic, advanced) 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci 1587db96d56Sopenharmony_ciclass KeySelectionTest(unittest.TestCase): 1597db96d56Sopenharmony_ci "Test selecting key on Basic frames." 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci class Basic(config_key.GetKeysFrame): 1627db96d56Sopenharmony_ci def __init__(self, *args, **kwargs): 1637db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 1647db96d56Sopenharmony_ci class list_keys_final: 1657db96d56Sopenharmony_ci get = Func() 1667db96d56Sopenharmony_ci select_clear = Func() 1677db96d56Sopenharmony_ci yview = Func() 1687db96d56Sopenharmony_ci self.list_keys_final = list_keys_final 1697db96d56Sopenharmony_ci def set_modifiers_for_platform(self): 1707db96d56Sopenharmony_ci self.modifiers = ['foo', 'bar', 'BAZ'] 1717db96d56Sopenharmony_ci self.modifier_label = {'BAZ': 'ZZZ'} 1727db96d56Sopenharmony_ci showerror = Mbox_func() 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci @classmethod 1757db96d56Sopenharmony_ci def setUpClass(cls): 1767db96d56Sopenharmony_ci requires('gui') 1777db96d56Sopenharmony_ci cls.root = Tk() 1787db96d56Sopenharmony_ci cls.root.withdraw() 1797db96d56Sopenharmony_ci cls.dialog = cls.Basic(cls.root, '<<Test>>', []) 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci @classmethod 1827db96d56Sopenharmony_ci def tearDownClass(cls): 1837db96d56Sopenharmony_ci del cls.dialog 1847db96d56Sopenharmony_ci cls.root.update_idletasks() 1857db96d56Sopenharmony_ci cls.root.destroy() 1867db96d56Sopenharmony_ci del cls.root 1877db96d56Sopenharmony_ci 1887db96d56Sopenharmony_ci def setUp(self): 1897db96d56Sopenharmony_ci self.dialog.clear_key_seq() 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci def test_get_modifiers(self): 1927db96d56Sopenharmony_ci dialog = self.dialog 1937db96d56Sopenharmony_ci gm = dialog.get_modifiers 1947db96d56Sopenharmony_ci eq = self.assertEqual 1957db96d56Sopenharmony_ci 1967db96d56Sopenharmony_ci # Modifiers are set on/off by invoking the checkbutton. 1977db96d56Sopenharmony_ci dialog.modifier_checkbuttons['foo'].invoke() 1987db96d56Sopenharmony_ci eq(gm(), ['foo']) 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci dialog.modifier_checkbuttons['BAZ'].invoke() 2017db96d56Sopenharmony_ci eq(gm(), ['foo', 'BAZ']) 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci dialog.modifier_checkbuttons['foo'].invoke() 2047db96d56Sopenharmony_ci eq(gm(), ['BAZ']) 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci @mock.patch.object(config_key.GetKeysFrame, 'get_modifiers') 2077db96d56Sopenharmony_ci def test_build_key_string(self, mock_modifiers): 2087db96d56Sopenharmony_ci dialog = self.dialog 2097db96d56Sopenharmony_ci key = dialog.list_keys_final 2107db96d56Sopenharmony_ci string = dialog.key_string.get 2117db96d56Sopenharmony_ci eq = self.assertEqual 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci key.get.result = 'a' 2147db96d56Sopenharmony_ci mock_modifiers.return_value = [] 2157db96d56Sopenharmony_ci dialog.build_key_string() 2167db96d56Sopenharmony_ci eq(string(), '<Key-a>') 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci mock_modifiers.return_value = ['mymod'] 2197db96d56Sopenharmony_ci dialog.build_key_string() 2207db96d56Sopenharmony_ci eq(string(), '<mymod-Key-a>') 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci key.get.result = '' 2237db96d56Sopenharmony_ci mock_modifiers.return_value = ['mymod', 'test'] 2247db96d56Sopenharmony_ci dialog.build_key_string() 2257db96d56Sopenharmony_ci eq(string(), '<mymod-test>') 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci @mock.patch.object(config_key.GetKeysFrame, 'get_modifiers') 2287db96d56Sopenharmony_ci def test_final_key_selected(self, mock_modifiers): 2297db96d56Sopenharmony_ci dialog = self.dialog 2307db96d56Sopenharmony_ci key = dialog.list_keys_final 2317db96d56Sopenharmony_ci string = dialog.key_string.get 2327db96d56Sopenharmony_ci eq = self.assertEqual 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci mock_modifiers.return_value = ['Shift'] 2357db96d56Sopenharmony_ci key.get.result = '{' 2367db96d56Sopenharmony_ci dialog.final_key_selected() 2377db96d56Sopenharmony_ci eq(string(), '<Shift-Key-braceleft>') 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ciclass CancelWindowTest(unittest.TestCase): 2417db96d56Sopenharmony_ci "Simulate user clicking [Cancel] button." 2427db96d56Sopenharmony_ci 2437db96d56Sopenharmony_ci @classmethod 2447db96d56Sopenharmony_ci def setUpClass(cls): 2457db96d56Sopenharmony_ci requires('gui') 2467db96d56Sopenharmony_ci cls.root = Tk() 2477db96d56Sopenharmony_ci cls.root.withdraw() 2487db96d56Sopenharmony_ci cls.dialog = config_key.GetKeysWindow( 2497db96d56Sopenharmony_ci cls.root, 'Title', '<<Test>>', [], _utest=True) 2507db96d56Sopenharmony_ci 2517db96d56Sopenharmony_ci @classmethod 2527db96d56Sopenharmony_ci def tearDownClass(cls): 2537db96d56Sopenharmony_ci cls.dialog.cancel() 2547db96d56Sopenharmony_ci del cls.dialog 2557db96d56Sopenharmony_ci cls.root.update_idletasks() 2567db96d56Sopenharmony_ci cls.root.destroy() 2577db96d56Sopenharmony_ci del cls.root 2587db96d56Sopenharmony_ci 2597db96d56Sopenharmony_ci @mock.patch.object(config_key.GetKeysFrame, 'ok') 2607db96d56Sopenharmony_ci def test_cancel(self, mock_frame_ok): 2617db96d56Sopenharmony_ci self.assertEqual(self.dialog.winfo_class(), 'Toplevel') 2627db96d56Sopenharmony_ci self.dialog.button_cancel.invoke() 2637db96d56Sopenharmony_ci with self.assertRaises(TclError): 2647db96d56Sopenharmony_ci self.dialog.winfo_class() 2657db96d56Sopenharmony_ci self.assertEqual(self.dialog.result, '') 2667db96d56Sopenharmony_ci mock_frame_ok.assert_not_called() 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ciclass OKWindowTest(unittest.TestCase): 2707db96d56Sopenharmony_ci "Simulate user clicking [OK] button." 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_ci @classmethod 2737db96d56Sopenharmony_ci def setUpClass(cls): 2747db96d56Sopenharmony_ci requires('gui') 2757db96d56Sopenharmony_ci cls.root = Tk() 2767db96d56Sopenharmony_ci cls.root.withdraw() 2777db96d56Sopenharmony_ci cls.dialog = config_key.GetKeysWindow( 2787db96d56Sopenharmony_ci cls.root, 'Title', '<<Test>>', [], _utest=True) 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci @classmethod 2817db96d56Sopenharmony_ci def tearDownClass(cls): 2827db96d56Sopenharmony_ci cls.dialog.cancel() 2837db96d56Sopenharmony_ci del cls.dialog 2847db96d56Sopenharmony_ci cls.root.update_idletasks() 2857db96d56Sopenharmony_ci cls.root.destroy() 2867db96d56Sopenharmony_ci del cls.root 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci @mock.patch.object(config_key.GetKeysFrame, 'ok') 2897db96d56Sopenharmony_ci def test_ok(self, mock_frame_ok): 2907db96d56Sopenharmony_ci self.assertEqual(self.dialog.winfo_class(), 'Toplevel') 2917db96d56Sopenharmony_ci self.dialog.button_ok.invoke() 2927db96d56Sopenharmony_ci with self.assertRaises(TclError): 2937db96d56Sopenharmony_ci self.dialog.winfo_class() 2947db96d56Sopenharmony_ci mock_frame_ok.assert_called() 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ciclass WindowResultTest(unittest.TestCase): 2987db96d56Sopenharmony_ci "Test window result get and set." 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci @classmethod 3017db96d56Sopenharmony_ci def setUpClass(cls): 3027db96d56Sopenharmony_ci requires('gui') 3037db96d56Sopenharmony_ci cls.root = Tk() 3047db96d56Sopenharmony_ci cls.root.withdraw() 3057db96d56Sopenharmony_ci cls.dialog = config_key.GetKeysWindow( 3067db96d56Sopenharmony_ci cls.root, 'Title', '<<Test>>', [], _utest=True) 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci @classmethod 3097db96d56Sopenharmony_ci def tearDownClass(cls): 3107db96d56Sopenharmony_ci cls.dialog.cancel() 3117db96d56Sopenharmony_ci del cls.dialog 3127db96d56Sopenharmony_ci cls.root.update_idletasks() 3137db96d56Sopenharmony_ci cls.root.destroy() 3147db96d56Sopenharmony_ci del cls.root 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci def test_result(self): 3177db96d56Sopenharmony_ci dialog = self.dialog 3187db96d56Sopenharmony_ci eq = self.assertEqual 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_ci dialog.result = '' 3217db96d56Sopenharmony_ci eq(dialog.result, '') 3227db96d56Sopenharmony_ci eq(dialog.frame.result,'') 3237db96d56Sopenharmony_ci 3247db96d56Sopenharmony_ci dialog.result = 'bar' 3257db96d56Sopenharmony_ci eq(dialog.result,'bar') 3267db96d56Sopenharmony_ci eq(dialog.frame.result,'bar') 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci dialog.frame.result = 'foo' 3297db96d56Sopenharmony_ci eq(dialog.result, 'foo') 3307db96d56Sopenharmony_ci eq(dialog.frame.result,'foo') 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ciclass HelperTest(unittest.TestCase): 3347db96d56Sopenharmony_ci "Test module level helper functions." 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci def test_translate_key(self): 3377db96d56Sopenharmony_ci tr = config_key.translate_key 3387db96d56Sopenharmony_ci eq = self.assertEqual 3397db96d56Sopenharmony_ci 3407db96d56Sopenharmony_ci # Letters return unchanged with no 'Shift'. 3417db96d56Sopenharmony_ci eq(tr('q', []), 'Key-q') 3427db96d56Sopenharmony_ci eq(tr('q', ['Control', 'Alt']), 'Key-q') 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci # 'Shift' uppercases single lowercase letters. 3457db96d56Sopenharmony_ci eq(tr('q', ['Shift']), 'Key-Q') 3467db96d56Sopenharmony_ci eq(tr('q', ['Control', 'Shift']), 'Key-Q') 3477db96d56Sopenharmony_ci eq(tr('q', ['Control', 'Alt', 'Shift']), 'Key-Q') 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci # Convert key name to keysym. 3507db96d56Sopenharmony_ci eq(tr('Page Up', []), 'Key-Prior') 3517db96d56Sopenharmony_ci # 'Shift' doesn't change case when it's not a single char. 3527db96d56Sopenharmony_ci eq(tr('*', ['Shift']), 'Key-asterisk') 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ciif __name__ == '__main__': 3567db96d56Sopenharmony_ci unittest.main(verbosity=2) 357