1from idlelib.tooltip import TooltipBase, Hovertip 2from test.support import requires 3requires('gui') 4 5from functools import wraps 6import time 7from tkinter import Button, Tk, Toplevel 8import unittest 9 10 11def setUpModule(): 12 global root 13 root = Tk() 14 15def root_update(): 16 global root 17 root.update() 18 19def tearDownModule(): 20 global root 21 root.update_idletasks() 22 root.destroy() 23 del root 24 25def add_call_counting(func): 26 @wraps(func) 27 def wrapped_func(*args, **kwargs): 28 wrapped_func.call_args_list.append((args, kwargs)) 29 return func(*args, **kwargs) 30 wrapped_func.call_args_list = [] 31 return wrapped_func 32 33 34def _make_top_and_button(testobj): 35 global root 36 top = Toplevel(root) 37 testobj.addCleanup(top.destroy) 38 top.title("Test tooltip") 39 button = Button(top, text='ToolTip test button') 40 button.pack() 41 testobj.addCleanup(button.destroy) 42 top.lift() 43 return top, button 44 45 46class ToolTipBaseTest(unittest.TestCase): 47 def setUp(self): 48 self.top, self.button = _make_top_and_button(self) 49 50 def test_base_class_is_unusable(self): 51 global root 52 top = Toplevel(root) 53 self.addCleanup(top.destroy) 54 55 button = Button(top, text='ToolTip test button') 56 button.pack() 57 self.addCleanup(button.destroy) 58 59 with self.assertRaises(NotImplementedError): 60 tooltip = TooltipBase(button) 61 tooltip.showtip() 62 63 64class HovertipTest(unittest.TestCase): 65 def setUp(self): 66 self.top, self.button = _make_top_and_button(self) 67 68 def test_showtip(self): 69 tooltip = Hovertip(self.button, 'ToolTip text') 70 self.addCleanup(tooltip.hidetip) 71 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 72 tooltip.showtip() 73 self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 74 75 def test_showtip_twice(self): 76 tooltip = Hovertip(self.button, 'ToolTip text') 77 self.addCleanup(tooltip.hidetip) 78 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 79 tooltip.showtip() 80 self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 81 orig_tipwindow = tooltip.tipwindow 82 tooltip.showtip() 83 self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 84 self.assertIs(tooltip.tipwindow, orig_tipwindow) 85 86 def test_hidetip(self): 87 tooltip = Hovertip(self.button, 'ToolTip text') 88 self.addCleanup(tooltip.hidetip) 89 tooltip.showtip() 90 tooltip.hidetip() 91 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 92 93 def test_showtip_on_mouse_enter_no_delay(self): 94 tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None) 95 self.addCleanup(tooltip.hidetip) 96 tooltip.showtip = add_call_counting(tooltip.showtip) 97 root_update() 98 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 99 self.button.event_generate('<Enter>', x=0, y=0) 100 root_update() 101 self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 102 self.assertGreater(len(tooltip.showtip.call_args_list), 0) 103 104 def test_showtip_on_mouse_enter_hover_delay(self): 105 tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50) 106 self.addCleanup(tooltip.hidetip) 107 tooltip.showtip = add_call_counting(tooltip.showtip) 108 root_update() 109 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 110 self.button.event_generate('<Enter>', x=0, y=0) 111 root_update() 112 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 113 time.sleep(0.1) 114 root_update() 115 self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 116 self.assertGreater(len(tooltip.showtip.call_args_list), 0) 117 118 def test_hidetip_on_mouse_leave(self): 119 tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None) 120 self.addCleanup(tooltip.hidetip) 121 tooltip.showtip = add_call_counting(tooltip.showtip) 122 root_update() 123 self.button.event_generate('<Enter>', x=0, y=0) 124 root_update() 125 self.button.event_generate('<Leave>', x=0, y=0) 126 root_update() 127 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 128 self.assertGreater(len(tooltip.showtip.call_args_list), 0) 129 130 def test_dont_show_on_mouse_leave_before_delay(self): 131 tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50) 132 self.addCleanup(tooltip.hidetip) 133 tooltip.showtip = add_call_counting(tooltip.showtip) 134 root_update() 135 self.button.event_generate('<Enter>', x=0, y=0) 136 root_update() 137 self.button.event_generate('<Leave>', x=0, y=0) 138 root_update() 139 time.sleep(0.1) 140 root_update() 141 self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()) 142 self.assertEqual(tooltip.showtip.call_args_list, []) 143 144 145if __name__ == '__main__': 146 unittest.main(verbosity=2) 147