mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	 132acaba5a
			
		
	
	
		132acaba5a
		
	
	
	
	
		
			
			Extending the hover delay in test_tooltip should avoid spurious test_idle failures. One longer delay instead of two shorter delays results in a net speedup.
		
			
				
	
	
		
			161 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Test tooltip, coverage 100%.
 | |
| 
 | |
| Coverage is 100% after excluding 6 lines with "# pragma: no cover".
 | |
| They involve TclErrors that either should or should not happen in a
 | |
| particular situation, and which are 'pass'ed if they do.
 | |
| """
 | |
| 
 | |
| from idlelib.tooltip import TooltipBase, Hovertip
 | |
| from test.support import requires
 | |
| requires('gui')
 | |
| 
 | |
| from functools import wraps
 | |
| import time
 | |
| from tkinter import Button, Tk, Toplevel
 | |
| import unittest
 | |
| 
 | |
| 
 | |
| def setUpModule():
 | |
|     global root
 | |
|     root = Tk()
 | |
| 
 | |
| def tearDownModule():
 | |
|     global root
 | |
|     root.update_idletasks()
 | |
|     root.destroy()
 | |
|     del root
 | |
| 
 | |
| 
 | |
| def add_call_counting(func):
 | |
|     @wraps(func)
 | |
|     def wrapped_func(*args, **kwargs):
 | |
|         wrapped_func.call_args_list.append((args, kwargs))
 | |
|         return func(*args, **kwargs)
 | |
|     wrapped_func.call_args_list = []
 | |
|     return wrapped_func
 | |
| 
 | |
| 
 | |
| def _make_top_and_button(testobj):
 | |
|     global root
 | |
|     top = Toplevel(root)
 | |
|     testobj.addCleanup(top.destroy)
 | |
|     top.title("Test tooltip")
 | |
|     button = Button(top, text='ToolTip test button')
 | |
|     button.pack()
 | |
|     testobj.addCleanup(button.destroy)
 | |
|     top.lift()
 | |
|     return top, button
 | |
| 
 | |
| 
 | |
| class ToolTipBaseTest(unittest.TestCase):
 | |
|     def setUp(self):
 | |
|         self.top, self.button = _make_top_and_button(self)
 | |
| 
 | |
|     def test_base_class_is_unusable(self):
 | |
|         global root
 | |
|         top = Toplevel(root)
 | |
|         self.addCleanup(top.destroy)
 | |
| 
 | |
|         button = Button(top, text='ToolTip test button')
 | |
|         button.pack()
 | |
|         self.addCleanup(button.destroy)
 | |
| 
 | |
|         with self.assertRaises(NotImplementedError):
 | |
|             tooltip = TooltipBase(button)
 | |
|             tooltip.showtip()
 | |
| 
 | |
| 
 | |
| class HovertipTest(unittest.TestCase):
 | |
|     def setUp(self):
 | |
|         self.top, self.button = _make_top_and_button(self)
 | |
| 
 | |
|     def is_tipwindow_shown(self, tooltip):
 | |
|         return tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()
 | |
| 
 | |
|     def test_showtip(self):
 | |
|         tooltip = Hovertip(self.button, 'ToolTip text')
 | |
|         self.addCleanup(tooltip.hidetip)
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip))
 | |
|         tooltip.showtip()
 | |
|         self.assertTrue(self.is_tipwindow_shown(tooltip))
 | |
| 
 | |
|     def test_showtip_twice(self):
 | |
|         tooltip = Hovertip(self.button, 'ToolTip text')
 | |
|         self.addCleanup(tooltip.hidetip)
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip))
 | |
|         tooltip.showtip()
 | |
|         self.assertTrue(self.is_tipwindow_shown(tooltip))
 | |
|         orig_tipwindow = tooltip.tipwindow
 | |
|         tooltip.showtip()
 | |
|         self.assertTrue(self.is_tipwindow_shown(tooltip))
 | |
|         self.assertIs(tooltip.tipwindow, orig_tipwindow)
 | |
| 
 | |
|     def test_hidetip(self):
 | |
|         tooltip = Hovertip(self.button, 'ToolTip text')
 | |
|         self.addCleanup(tooltip.hidetip)
 | |
|         tooltip.showtip()
 | |
|         tooltip.hidetip()
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip))
 | |
| 
 | |
|     def test_showtip_on_mouse_enter_no_delay(self):
 | |
|         tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
 | |
|         self.addCleanup(tooltip.hidetip)
 | |
|         tooltip.showtip = add_call_counting(tooltip.showtip)
 | |
|         root.update()
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip))
 | |
|         self.button.event_generate('<Enter>', x=0, y=0)
 | |
|         root.update()
 | |
|         self.assertTrue(self.is_tipwindow_shown(tooltip))
 | |
|         self.assertGreater(len(tooltip.showtip.call_args_list), 0)
 | |
| 
 | |
|     def test_hover_with_delay(self):
 | |
|         # Run multiple tests requiring an actual delay simultaneously.
 | |
| 
 | |
|         # Test #1: A hover tip with a non-zero delay appears after the delay.
 | |
|         tooltip1 = Hovertip(self.button, 'ToolTip text', hover_delay=100)
 | |
|         self.addCleanup(tooltip1.hidetip)
 | |
|         tooltip1.showtip = add_call_counting(tooltip1.showtip)
 | |
|         root.update()
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip1))
 | |
|         self.button.event_generate('<Enter>', x=0, y=0)
 | |
|         root.update()
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip1))
 | |
| 
 | |
|         # Test #2: A hover tip with a non-zero delay doesn't appear when
 | |
|         # the mouse stops hovering over the base widget before the delay
 | |
|         # expires.
 | |
|         tooltip2 = Hovertip(self.button, 'ToolTip text', hover_delay=100)
 | |
|         self.addCleanup(tooltip2.hidetip)
 | |
|         tooltip2.showtip = add_call_counting(tooltip2.showtip)
 | |
|         root.update()
 | |
|         self.button.event_generate('<Enter>', x=0, y=0)
 | |
|         root.update()
 | |
|         self.button.event_generate('<Leave>', x=0, y=0)
 | |
|         root.update()
 | |
| 
 | |
|         time.sleep(0.15)
 | |
|         root.update()
 | |
| 
 | |
|         # Test #1 assertions.
 | |
|         self.assertTrue(self.is_tipwindow_shown(tooltip1))
 | |
|         self.assertGreater(len(tooltip1.showtip.call_args_list), 0)
 | |
| 
 | |
|         # Test #2 assertions.
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip2))
 | |
|         self.assertEqual(tooltip2.showtip.call_args_list, [])
 | |
| 
 | |
|     def test_hidetip_on_mouse_leave(self):
 | |
|         tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
 | |
|         self.addCleanup(tooltip.hidetip)
 | |
|         tooltip.showtip = add_call_counting(tooltip.showtip)
 | |
|         root.update()
 | |
|         self.button.event_generate('<Enter>', x=0, y=0)
 | |
|         root.update()
 | |
|         self.button.event_generate('<Leave>', x=0, y=0)
 | |
|         root.update()
 | |
|         self.assertFalse(self.is_tipwindow_shown(tooltip))
 | |
|         self.assertGreater(len(tooltip.showtip.call_args_list), 0)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest.main(verbosity=2)
 |