• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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