| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  | """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. | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  | 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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |     def is_tipwindow_shown(self, tooltip): | 
					
						
							|  |  |  |         return tooltip.tipwindow and tooltip.tipwindow.winfo_viewable() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |     def test_showtip(self): | 
					
						
							|  |  |  |         tooltip = Hovertip(self.button, 'ToolTip text') | 
					
						
							|  |  |  |         self.addCleanup(tooltip.hidetip) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         self.assertFalse(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         tooltip.showtip() | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         self.assertTrue(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_showtip_twice(self): | 
					
						
							|  |  |  |         tooltip = Hovertip(self.button, 'ToolTip text') | 
					
						
							|  |  |  |         self.addCleanup(tooltip.hidetip) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         self.assertFalse(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         tooltip.showtip() | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         self.assertTrue(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         orig_tipwindow = tooltip.tipwindow | 
					
						
							|  |  |  |         tooltip.showtip() | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         self.assertTrue(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.assertIs(tooltip.tipwindow, orig_tipwindow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_hidetip(self): | 
					
						
							|  |  |  |         tooltip = Hovertip(self.button, 'ToolTip text') | 
					
						
							|  |  |  |         self.addCleanup(tooltip.hidetip) | 
					
						
							|  |  |  |         tooltip.showtip() | 
					
						
							|  |  |  |         tooltip.hidetip() | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         self.assertFalse(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         root.update() | 
					
						
							|  |  |  |         self.assertFalse(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.button.event_generate('<Enter>', x=0, y=0) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         root.update() | 
					
						
							|  |  |  |         self.assertTrue(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.assertGreater(len(tooltip.showtip.call_args_list), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |     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)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.button.event_generate('<Enter>', x=0, y=0) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         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, []) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         root.update() | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.button.event_generate('<Enter>', x=0, y=0) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         root.update() | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.button.event_generate('<Leave>', x=0, y=0) | 
					
						
							| 
									
										
										
										
											2019-09-03 08:17:00 +03:00
										 |  |  |         root.update() | 
					
						
							|  |  |  |         self.assertFalse(self.is_tipwindow_shown(tooltip)) | 
					
						
							| 
									
										
										
										
											2018-08-05 09:21:08 +03:00
										 |  |  |         self.assertGreater(len(tooltip.showtip.call_args_list), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     unittest.main(verbosity=2) |