1+ """Test tooltip, coverage 100%.
2+
3+ Coverage is 100% after excluding 6 lines with "# pragma: no cover".
4+ They involve TclErrors that either should or should not happen in a
5+ particular situation, and which are 'pass'ed if they do.
6+ """
7+
18from idlelib .tooltip import TooltipBase , Hovertip
29from test .support import requires
310requires ('gui' )
@@ -12,16 +19,13 @@ def setUpModule():
1219 global root
1320 root = Tk ()
1421
15- def root_update ():
16- global root
17- root .update ()
18-
1922def tearDownModule ():
2023 global root
2124 root .update_idletasks ()
2225 root .destroy ()
2326 del root
2427
28+
2529def add_call_counting (func ):
2630 @wraps (func )
2731 def wrapped_func (* args , ** kwargs ):
@@ -65,82 +69,93 @@ class HovertipTest(unittest.TestCase):
6569 def setUp (self ):
6670 self .top , self .button = _make_top_and_button (self )
6771
72+ def is_tipwindow_shown (self , tooltip ):
73+ return tooltip .tipwindow and tooltip .tipwindow .winfo_viewable ()
74+
6875 def test_showtip (self ):
6976 tooltip = Hovertip (self .button , 'ToolTip text' )
7077 self .addCleanup (tooltip .hidetip )
71- self .assertFalse (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
78+ self .assertFalse (self . is_tipwindow_shown ( tooltip ))
7279 tooltip .showtip ()
73- self .assertTrue (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
80+ self .assertTrue (self . is_tipwindow_shown ( tooltip ))
7481
7582 def test_showtip_twice (self ):
7683 tooltip = Hovertip (self .button , 'ToolTip text' )
7784 self .addCleanup (tooltip .hidetip )
78- self .assertFalse (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
85+ self .assertFalse (self . is_tipwindow_shown ( tooltip ))
7986 tooltip .showtip ()
80- self .assertTrue (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
87+ self .assertTrue (self . is_tipwindow_shown ( tooltip ))
8188 orig_tipwindow = tooltip .tipwindow
8289 tooltip .showtip ()
83- self .assertTrue (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
90+ self .assertTrue (self . is_tipwindow_shown ( tooltip ))
8491 self .assertIs (tooltip .tipwindow , orig_tipwindow )
8592
8693 def test_hidetip (self ):
8794 tooltip = Hovertip (self .button , 'ToolTip text' )
8895 self .addCleanup (tooltip .hidetip )
8996 tooltip .showtip ()
9097 tooltip .hidetip ()
91- self .assertFalse (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
98+ self .assertFalse (self . is_tipwindow_shown ( tooltip ))
9299
93100 def test_showtip_on_mouse_enter_no_delay (self ):
94101 tooltip = Hovertip (self .button , 'ToolTip text' , hover_delay = None )
95102 self .addCleanup (tooltip .hidetip )
96103 tooltip .showtip = add_call_counting (tooltip .showtip )
97- root_update ()
98- self .assertFalse (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
104+ root . update ()
105+ self .assertFalse (self . is_tipwindow_shown ( tooltip ))
99106 self .button .event_generate ('<Enter>' , x = 0 , y = 0 )
100- root_update ()
101- self .assertTrue (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
107+ root . update ()
108+ self .assertTrue (self . is_tipwindow_shown ( tooltip ))
102109 self .assertGreater (len (tooltip .showtip .call_args_list ), 0 )
103110
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 ())
111+ def test_hover_with_delay (self ):
112+ # Run multiple tests requiring an actual delay simultaneously.
113+
114+ # Test #1: A hover tip with a non-zero delay appears after the delay.
115+ tooltip1 = Hovertip (self .button , 'ToolTip text' , hover_delay = 100 )
116+ self .addCleanup (tooltip1 .hidetip )
117+ tooltip1 .showtip = add_call_counting (tooltip1 .showtip )
118+ root .update ()
119+ self .assertFalse (self .is_tipwindow_shown (tooltip1 ))
110120 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 )
121+ root .update ()
122+ self .assertFalse (self .is_tipwindow_shown (tooltip1 ))
123+
124+ # Test #2: A hover tip with a non-zero delay doesn't appear when
125+ # the mouse stops hovering over the base widget before the delay
126+ # expires.
127+ tooltip2 = Hovertip (self .button , 'ToolTip text' , hover_delay = 100 )
128+ self .addCleanup (tooltip2 .hidetip )
129+ tooltip2 .showtip = add_call_counting (tooltip2 .showtip )
130+ root .update ()
131+ self .button .event_generate ('<Enter>' , x = 0 , y = 0 )
132+ root .update ()
133+ self .button .event_generate ('<Leave>' , x = 0 , y = 0 )
134+ root .update ()
135+
136+ time .sleep (0.15 )
137+ root .update ()
138+
139+ # Test #1 assertions.
140+ self .assertTrue (self .is_tipwindow_shown (tooltip1 ))
141+ self .assertGreater (len (tooltip1 .showtip .call_args_list ), 0 )
142+
143+ # Test #2 assertions.
144+ self .assertFalse (self .is_tipwindow_shown (tooltip2 ))
145+ self .assertEqual (tooltip2 .showtip .call_args_list , [])
117146
118147 def test_hidetip_on_mouse_leave (self ):
119148 tooltip = Hovertip (self .button , 'ToolTip text' , hover_delay = None )
120149 self .addCleanup (tooltip .hidetip )
121150 tooltip .showtip = add_call_counting (tooltip .showtip )
122- root_update ()
151+ root . update ()
123152 self .button .event_generate ('<Enter>' , x = 0 , y = 0 )
124- root_update ()
153+ root . update ()
125154 self .button .event_generate ('<Leave>' , x = 0 , y = 0 )
126- root_update ()
127- self .assertFalse (tooltip . tipwindow and tooltip . tipwindow . winfo_viewable ( ))
155+ root . update ()
156+ self .assertFalse (self . is_tipwindow_shown ( tooltip ))
128157 self .assertGreater (len (tooltip .showtip .call_args_list ), 0 )
129158
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-
144159
145160if __name__ == '__main__' :
146161 unittest .main (verbosity = 2 )
0 commit comments