147 lines
5.2 KiB
Python
147 lines
5.2 KiB
Python
|
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 root_update():
|
||
|
global root
|
||
|
root.update()
|
||
|
|
||
|
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 test_showtip(self):
|
||
|
tooltip = Hovertip(self.button, 'ToolTip text')
|
||
|
self.addCleanup(tooltip.hidetip)
|
||
|
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
tooltip.showtip()
|
||
|
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
|
||
|
def test_showtip_twice(self):
|
||
|
tooltip = Hovertip(self.button, 'ToolTip text')
|
||
|
self.addCleanup(tooltip.hidetip)
|
||
|
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
tooltip.showtip()
|
||
|
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
orig_tipwindow = tooltip.tipwindow
|
||
|
tooltip.showtip()
|
||
|
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
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(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
|
||
|
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(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
self.button.event_generate('<Enter>', x=0, y=0)
|
||
|
root_update()
|
||
|
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
|
||
|
|
||
|
def test_showtip_on_mouse_enter_hover_delay(self):
|
||
|
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50)
|
||
|
self.addCleanup(tooltip.hidetip)
|
||
|
tooltip.showtip = add_call_counting(tooltip.showtip)
|
||
|
root_update()
|
||
|
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
self.button.event_generate('<Enter>', x=0, y=0)
|
||
|
root_update()
|
||
|
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
time.sleep(0.1)
|
||
|
root_update()
|
||
|
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
|
||
|
|
||
|
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(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
|
||
|
|
||
|
def test_dont_show_on_mouse_leave_before_delay(self):
|
||
|
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50)
|
||
|
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()
|
||
|
time.sleep(0.1)
|
||
|
root_update()
|
||
|
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||
|
self.assertEqual(tooltip.showtip.call_args_list, [])
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
unittest.main(verbosity=2)
|