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
177 changes: 176 additions & 1 deletion Lib/test/test_tkinter/test_simpledialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,143 @@
from test.support import requires, swap_attr
from test.test_tkinter.support import setUpModule # noqa: F401
from test.test_tkinter.support import AbstractDefaultRootTest, AbstractTkTest
from tkinter.simpledialog import (Dialog, askinteger,
from tkinter.simpledialog import (Dialog, SimpleDialog,
askinteger, askfloat, askstring,
_QueryInteger, _QueryFloat, _QueryString)

requires('gui')


class SimpleDialogTest(AbstractTkTest, unittest.TestCase):
# SimpleDialog's modal loop is in go(); its bindings are exercised here by
# generating events on the constructed dialog, without entering the loop.

def create(self, **kw):
kw.setdefault('text', 'Question?')
kw.setdefault('buttons', ['Yes', 'No'])
kw.setdefault('default', 0)
kw.setdefault('cancel', 1)
d = SimpleDialog(self.root, **kw)
self.addCleanup(lambda: d.root.winfo_exists() and d.root.destroy())
return d

def test_message(self):
# The text is shown in a message widget.
d = self.create(text='Hello?')
self.assertEqual(d.message.winfo_class(), 'Message')
self.assertEqual(str(d.message.cget('text')), 'Hello?')

def test_class_name(self):
# class_ sets the Tk class of the dialog window.
d = self.create(class_='MyDialog')
self.assertEqual(d.root.winfo_class(), 'MyDialog')

def test_button(self):
# Pressing a button records its index.
d = self.create(buttons=['Yes', 'No'])
d.frame.winfo_children()[1].invoke() # "No"
self.assertEqual(d.num, 1)

def test_default_button(self):
# The default button is drawn with a raised border.
d = self.create(buttons=['Yes', 'No'], default=0)
self.assertEqual(str(d.frame.winfo_children()[0].cget('relief')), 'ridge')

def test_return_activates_default(self):
# <Return> invokes the default button.
d = self.create() # default 0
d.root.focus_force()
d.root.update()
d.root.event_generate('<Return>')
d.root.update()
self.assertEqual(d.num, 0)

def test_return_no_default(self):
# With no default button, <Return> rings the bell and leaves the dialog
# open instead of activating a button.
d = self.create(default=None)
d.root.focus_force()
d.root.update()
bells = []
with swap_attr(d.root, 'bell', lambda *a, **k: bells.append(True)):
d.root.event_generate('<Return>')
d.root.update()
self.assertTrue(bells) # rang the bell
self.assertIsNone(d.num)
self.assertTrue(d.root.winfo_exists())

def test_wm_delete_cancels(self):
# Closing the window through the window manager records the cancel index.
d = self.create() # cancel 1
d.wm_delete_window()
self.assertEqual(d.num, 1)

def test_wm_delete_no_cancel(self):
# With no cancel index, closing the window through the window manager
# rings the bell and leaves the dialog open instead of recording an
# index.
d = self.create(default=None, cancel=None)
d.root.update()
bells = []
with swap_attr(d.root, 'bell', lambda *a, **k: bells.append(True)):
d.wm_delete_window()
d.root.update()
self.assertTrue(bells) # rang the bell
self.assertIsNone(d.num)
self.assertTrue(d.root.winfo_exists())

def test_go(self):
# go() runs the modal loop and returns the chosen button's index.
d = self.create()
d.root.after(1, lambda: d.done(0))
self.assertEqual(d.go(), 0)


class DialogTest(AbstractTkTest, unittest.TestCase):
# Dialog is a base class for custom dialogs; exercise it via _QueryInteger.

def open(self, **kw):
with swap_attr(Dialog, 'wait_window', staticmethod(lambda w: None)):
d = _QueryInteger('Title', 'Prompt', parent=self.root, **kw)
self.addCleanup(lambda: d.winfo_exists() and d.destroy())
return d

def buttons(self, d):
# Map the button box's buttons by their label.
return {str(b.cget('text')): b
for frame in d.winfo_children()
for b in frame.winfo_children()
if b.winfo_class() == 'Button'}

def test_background(self):
# The classic dialog keeps the default Toplevel background.
d = self.open()
ref = tkinter.Toplevel(self.root)
self.addCleanup(ref.destroy)
self.assertEqual(str(d.cget('background')), str(ref.cget('background')))

def test_buttons(self):
# The button box has OK (the default) and Cancel buttons.
buttons = self.buttons(self.open())
self.assertEqual(set(buttons), {'OK', 'Cancel'})
self.assertEqual(str(buttons['OK'].cget('default')), 'active')

def test_ok(self):
# The OK button validates the entry and stores the result.
d = self.open()
d.entry.insert(0, '42')
self.buttons(d)['OK'].invoke()
self.assertEqual(d.result, 42)
self.assertFalse(d.winfo_exists()) # The dialog closed.

def test_cancel(self):
# The Cancel button closes the dialog without a result.
d = self.open()
self.buttons(d)['Cancel'].invoke()
self.assertIsNone(d.result)
self.assertFalse(d.winfo_exists())


class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):

def test_askinteger(self):
Expand Down Expand Up @@ -53,6 +184,19 @@ def enter(self, d, value, key='<Return>'):
d.event_generate(key)
d.update()

def test_initialvalue(self):
# The entry is pre-filled with the initial value, which is accepted.
d = self.open(_QueryInteger, initialvalue=42)
self.assertEqual(d.entry.get(), '42')
d.event_generate('<Return>')
d.update()
self.assertEqual(d.result, 42)

def test_show(self):
# _QueryString hides the entered text when show is given.
d = self.open(_QueryString, show='*')
self.assertEqual(str(d.entry.cget('show')), '*')

def test_return_accepts(self):
for query, value, expected in [
(_QueryInteger, '42', 42),
Expand Down Expand Up @@ -93,6 +237,37 @@ def test_out_of_range(self):
self.assertTrue(d.winfo_exists())
self.assertEqual(len(warnings), 2)

def test_boundary_values_accepted(self):
# The min/max checks are inclusive: a value equal to a bound passes.
d = self.open(_QueryInteger, minvalue=10, maxvalue=20)
self.enter(d, '10') # Exactly the minimum.
self.assertEqual(d.result, 10)
self.assertFalse(d.winfo_exists())

d = self.open(_QueryInteger, minvalue=10, maxvalue=20)
self.enter(d, '20') # Exactly the maximum.
self.assertEqual(d.result, 20)
self.assertFalse(d.winfo_exists())

def run_ask(self, ask, value, **kw):
# Drive a modal ask* function: enter a value and accept it.
def accept(d):
d.entry.delete(0, 'end')
d.entry.insert(0, value)
d.ok()
with swap_attr(Dialog, 'wait_window', staticmethod(accept)):
return ask('Title', 'Prompt', parent=self.root, **kw)

def test_ask_functions(self):
self.assertEqual(self.run_ask(askinteger, '42'), 42)
self.assertEqual(self.run_ask(askfloat, '1.5'), 1.5)
self.assertEqual(self.run_ask(askstring, 'spam'), 'spam')

def test_ask_cancelled(self):
# A cancelled ask* returns None.
with swap_attr(Dialog, 'wait_window', staticmethod(lambda d: d.cancel())):
self.assertIsNone(askstring('Title', 'Prompt', parent=self.root))


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