Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions Lib/test/test_tkinter/test_dnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ def setUp(self):
self.source = Source(self.log)
self.target = Target(self.canvas, self.log)

def tearDown(self):
# Make sure no drag-and-drop is left active between tests: the
# recursion guard is a name-mangled attribute on the root.
try:
del self.root._DndHandler__dnd
except AttributeError:
pass
super().tearDown()

def test_drag_and_drop(self):
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.assertIsNotNone(handler)
Expand Down Expand Up @@ -93,6 +102,70 @@ def test_no_recursive_start(self):
def test_high_button_number_ignored(self):
self.assertIsNone(dnd.dnd_start(self.source, FakeEvent(self.canvas, num=6)))

def test_restart_after_finish(self):
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
handler.cancel()
# Once a drag has finished a new one can start.
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.assertIsNotNone(handler)
handler.cancel()

def test_drag_cursor(self):
self.canvas['cursor'] = 'watch'
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
# The drag cursor is shown while dragging, the original restored after.
self.assertEqual(handler.save_cursor, 'watch')
self.assertEqual(str(self.canvas['cursor']), 'hand2')
handler.cancel()
self.assertEqual(str(self.canvas['cursor']), 'watch')

def test_bindings_added_and_removed(self):
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.assertIn('<Motion>', self.canvas.bind())
self.assertIn('<B1-ButtonRelease-1>', self.canvas.bind())
handler.cancel()
self.assertNotIn('<Motion>', self.canvas.bind())
self.assertNotIn('<B1-ButtonRelease-1>', self.canvas.bind())

def test_switch_target(self):
log1, log2 = [], []
w1, w2 = tkinter.Frame(self.root), tkinter.Frame(self.root)
target1, target2 = Target(w1, log1), Target(w2, log2)
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.canvas.winfo_containing = lambda x, y: w1
handler.on_motion(FakeEvent(self.canvas)) # Enter target1.
self.canvas.winfo_containing = lambda x, y: w2
handler.on_motion(FakeEvent(self.canvas)) # Leave target1, enter target2.
self.assertIs(handler.target, target2)
self.assertEqual(log1, ['accept', 'enter', 'leave'])
self.assertEqual(log2, ['accept', 'enter'])
handler.cancel()

def test_target_in_ancestor(self):
# The widget under the pointer has no dnd_accept, but an ancestor
# does: the search walks up the master chain to find it.
parent = tkinter.Frame(self.root)
target = Target(parent, self.log)
child = tkinter.Frame(parent)
self.canvas.winfo_containing = lambda x, y: child
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
handler.on_motion(FakeEvent(self.canvas))
self.assertIs(handler.target, target)
self.assertEqual(self.log, ['accept', 'enter'])
handler.cancel()

def test_accept_returning_none_continues(self):
# dnd_accept() returning None means "not me, keep looking up".
parent = tkinter.Frame(self.root)
target = Target(parent, self.log)
child = tkinter.Frame(parent)
child.dnd_accept = lambda source, event: None
self.canvas.winfo_containing = lambda x, y: child
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
handler.on_motion(FakeEvent(self.canvas))
self.assertIs(handler.target, target)
handler.cancel()


if __name__ == "__main__":
unittest.main()
Loading