Home | History | Annotate | Download | only in test_tkinter
      1 import unittest
      2 import tkinter
      3 from tkinter import TclError
      4 import os
      5 import sys
      6 from test.support import requires
      7 
      8 from tkinter.test.support import (tcl_version, requires_tcl,
      9                                   get_tk_patchlevel, widget_eq)
     10 from tkinter.test.widget_tests import (
     11     add_standard_options, noconv, pixels_round,
     12     AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests,
     13     setUpModule)
     14 
     15 requires('gui')
     16 
     17 
     18 def float_round(x):
     19     return float(round(x))
     20 
     21 
     22 class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
     23     _conv_pad_pixels = noconv
     24 
     25     def test_class(self):
     26         widget = self.create()
     27         self.assertEqual(widget['class'],
     28                          widget.__class__.__name__.title())
     29         self.checkInvalidParam(widget, 'class', 'Foo',
     30                 errmsg="can't modify -class option after widget is created")
     31         widget2 = self.create(class_='Foo')
     32         self.assertEqual(widget2['class'], 'Foo')
     33 
     34     def test_colormap(self):
     35         widget = self.create()
     36         self.assertEqual(widget['colormap'], '')
     37         self.checkInvalidParam(widget, 'colormap', 'new',
     38                 errmsg="can't modify -colormap option after widget is created")
     39         widget2 = self.create(colormap='new')
     40         self.assertEqual(widget2['colormap'], 'new')
     41 
     42     def test_container(self):
     43         widget = self.create()
     44         self.assertEqual(widget['container'], 0 if self.wantobjects else '0')
     45         self.checkInvalidParam(widget, 'container', 1,
     46                 errmsg="can't modify -container option after widget is created")
     47         widget2 = self.create(container=True)
     48         self.assertEqual(widget2['container'], 1 if self.wantobjects else '1')
     49 
     50     def test_visual(self):
     51         widget = self.create()
     52         self.assertEqual(widget['visual'], '')
     53         self.checkInvalidParam(widget, 'visual', 'default',
     54                 errmsg="can't modify -visual option after widget is created")
     55         widget2 = self.create(visual='default')
     56         self.assertEqual(widget2['visual'], 'default')
     57 
     58 
     59 @add_standard_options(StandardOptionsTests)
     60 class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
     61     OPTIONS = (
     62         'background', 'borderwidth',
     63         'class', 'colormap', 'container', 'cursor', 'height',
     64         'highlightbackground', 'highlightcolor', 'highlightthickness',
     65         'menu', 'padx', 'pady', 'relief', 'screen',
     66         'takefocus', 'use', 'visual', 'width',
     67     )
     68 
     69     def create(self, **kwargs):
     70         return tkinter.Toplevel(self.root, **kwargs)
     71 
     72     def test_menu(self):
     73         widget = self.create()
     74         menu = tkinter.Menu(self.root)
     75         self.checkParam(widget, 'menu', menu, eq=widget_eq)
     76         self.checkParam(widget, 'menu', '')
     77 
     78     def test_screen(self):
     79         widget = self.create()
     80         self.assertEqual(widget['screen'], '')
     81         try:
     82             display = os.environ['DISPLAY']
     83         except KeyError:
     84             self.skipTest('No $DISPLAY set.')
     85         self.checkInvalidParam(widget, 'screen', display,
     86                 errmsg="can't modify -screen option after widget is created")
     87         widget2 = self.create(screen=display)
     88         self.assertEqual(widget2['screen'], display)
     89 
     90     def test_use(self):
     91         widget = self.create()
     92         self.assertEqual(widget['use'], '')
     93         parent = self.create(container=True)
     94         wid = hex(parent.winfo_id())
     95         with self.subTest(wid=wid):
     96             widget2 = self.create(use=wid)
     97             self.assertEqual(widget2['use'], wid)
     98 
     99 
    100 @add_standard_options(StandardOptionsTests)
    101 class FrameTest(AbstractToplevelTest, unittest.TestCase):
    102     OPTIONS = (
    103         'background', 'borderwidth',
    104         'class', 'colormap', 'container', 'cursor', 'height',
    105         'highlightbackground', 'highlightcolor', 'highlightthickness',
    106         'padx', 'pady', 'relief', 'takefocus', 'visual', 'width',
    107     )
    108 
    109     def create(self, **kwargs):
    110         return tkinter.Frame(self.root, **kwargs)
    111 
    112 
    113 @add_standard_options(StandardOptionsTests)
    114 class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
    115     OPTIONS = (
    116         'background', 'borderwidth',
    117         'class', 'colormap', 'container', 'cursor',
    118         'font', 'foreground', 'height',
    119         'highlightbackground', 'highlightcolor', 'highlightthickness',
    120         'labelanchor', 'labelwidget', 'padx', 'pady', 'relief',
    121         'takefocus', 'text', 'visual', 'width',
    122     )
    123 
    124     def create(self, **kwargs):
    125         return tkinter.LabelFrame(self.root, **kwargs)
    126 
    127     def test_labelanchor(self):
    128         widget = self.create()
    129         self.checkEnumParam(widget, 'labelanchor',
    130                             'e', 'en', 'es', 'n', 'ne', 'nw',
    131                             's', 'se', 'sw', 'w', 'wn', 'ws')
    132         self.checkInvalidParam(widget, 'labelanchor', 'center')
    133 
    134     def test_labelwidget(self):
    135         widget = self.create()
    136         label = tkinter.Label(self.root, text='Mupp', name='foo')
    137         self.checkParam(widget, 'labelwidget', label, expected='.foo')
    138         label.destroy()
    139 
    140 
    141 class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests):
    142     _conv_pixels = noconv
    143 
    144     def test_highlightthickness(self):
    145         widget = self.create()
    146         self.checkPixelsParam(widget, 'highlightthickness',
    147                               0, 1.3, 2.6, 6, -2, '10p')
    148 
    149 
    150 @add_standard_options(StandardOptionsTests)
    151 class LabelTest(AbstractLabelTest, unittest.TestCase):
    152     OPTIONS = (
    153         'activebackground', 'activeforeground', 'anchor',
    154         'background', 'bitmap', 'borderwidth', 'compound', 'cursor',
    155         'disabledforeground', 'font', 'foreground', 'height',
    156         'highlightbackground', 'highlightcolor', 'highlightthickness',
    157         'image', 'justify', 'padx', 'pady', 'relief', 'state',
    158         'takefocus', 'text', 'textvariable',
    159         'underline', 'width', 'wraplength',
    160     )
    161 
    162     def create(self, **kwargs):
    163         return tkinter.Label(self.root, **kwargs)
    164 
    165 
    166 @add_standard_options(StandardOptionsTests)
    167 class ButtonTest(AbstractLabelTest, unittest.TestCase):
    168     OPTIONS = (
    169         'activebackground', 'activeforeground', 'anchor',
    170         'background', 'bitmap', 'borderwidth',
    171         'command', 'compound', 'cursor', 'default',
    172         'disabledforeground', 'font', 'foreground', 'height',
    173         'highlightbackground', 'highlightcolor', 'highlightthickness',
    174         'image', 'justify', 'overrelief', 'padx', 'pady', 'relief',
    175         'repeatdelay', 'repeatinterval',
    176         'state', 'takefocus', 'text', 'textvariable',
    177         'underline', 'width', 'wraplength')
    178 
    179     def create(self, **kwargs):
    180         return tkinter.Button(self.root, **kwargs)
    181 
    182     def test_default(self):
    183         widget = self.create()
    184         self.checkEnumParam(widget, 'default', 'active', 'disabled', 'normal')
    185 
    186 
    187 @add_standard_options(StandardOptionsTests)
    188 class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
    189     OPTIONS = (
    190         'activebackground', 'activeforeground', 'anchor',
    191         'background', 'bitmap', 'borderwidth',
    192         'command', 'compound', 'cursor',
    193         'disabledforeground', 'font', 'foreground', 'height',
    194         'highlightbackground', 'highlightcolor', 'highlightthickness',
    195         'image', 'indicatoron', 'justify',
    196         'offrelief', 'offvalue', 'onvalue', 'overrelief',
    197         'padx', 'pady', 'relief', 'selectcolor', 'selectimage', 'state',
    198         'takefocus', 'text', 'textvariable',
    199         'tristateimage', 'tristatevalue',
    200         'underline', 'variable', 'width', 'wraplength',
    201     )
    202 
    203     def create(self, **kwargs):
    204         return tkinter.Checkbutton(self.root, **kwargs)
    205 
    206 
    207     def test_offvalue(self):
    208         widget = self.create()
    209         self.checkParams(widget, 'offvalue', 1, 2.3, '', 'any string')
    210 
    211     def test_onvalue(self):
    212         widget = self.create()
    213         self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string')
    214 
    215 
    216 @add_standard_options(StandardOptionsTests)
    217 class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
    218     OPTIONS = (
    219         'activebackground', 'activeforeground', 'anchor',
    220         'background', 'bitmap', 'borderwidth',
    221         'command', 'compound', 'cursor',
    222         'disabledforeground', 'font', 'foreground', 'height',
    223         'highlightbackground', 'highlightcolor', 'highlightthickness',
    224         'image', 'indicatoron', 'justify', 'offrelief', 'overrelief',
    225         'padx', 'pady', 'relief', 'selectcolor', 'selectimage', 'state',
    226         'takefocus', 'text', 'textvariable',
    227         'tristateimage', 'tristatevalue',
    228         'underline', 'value', 'variable', 'width', 'wraplength',
    229     )
    230 
    231     def create(self, **kwargs):
    232         return tkinter.Radiobutton(self.root, **kwargs)
    233 
    234     def test_value(self):
    235         widget = self.create()
    236         self.checkParams(widget, 'value', 1, 2.3, '', 'any string')
    237 
    238 
    239 @add_standard_options(StandardOptionsTests)
    240 class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
    241     OPTIONS = (
    242         'activebackground', 'activeforeground', 'anchor',
    243         'background', 'bitmap', 'borderwidth',
    244         'compound', 'cursor', 'direction',
    245         'disabledforeground', 'font', 'foreground', 'height',
    246         'highlightbackground', 'highlightcolor', 'highlightthickness',
    247         'image', 'indicatoron', 'justify', 'menu',
    248         'padx', 'pady', 'relief', 'state',
    249         'takefocus', 'text', 'textvariable',
    250         'underline', 'width', 'wraplength',
    251     )
    252     _conv_pixels = staticmethod(pixels_round)
    253 
    254     def create(self, **kwargs):
    255         return tkinter.Menubutton(self.root, **kwargs)
    256 
    257     def test_direction(self):
    258         widget = self.create()
    259         self.checkEnumParam(widget, 'direction',
    260                 'above', 'below', 'flush', 'left', 'right')
    261 
    262     def test_height(self):
    263         widget = self.create()
    264         self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=str)
    265 
    266     test_highlightthickness = StandardOptionsTests.test_highlightthickness
    267 
    268     @unittest.skipIf(sys.platform == 'darwin',
    269                      'crashes with Cocoa Tk (issue19733)')
    270     def test_image(self):
    271         widget = self.create()
    272         image = tkinter.PhotoImage(master=self.root, name='image1')
    273         self.checkParam(widget, 'image', image, conv=str)
    274         errmsg = 'image "spam" doesn\'t exist'
    275         with self.assertRaises(tkinter.TclError) as cm:
    276             widget['image'] = 'spam'
    277         if errmsg is not None:
    278             self.assertEqual(str(cm.exception), errmsg)
    279         with self.assertRaises(tkinter.TclError) as cm:
    280             widget.configure({'image': 'spam'})
    281         if errmsg is not None:
    282             self.assertEqual(str(cm.exception), errmsg)
    283 
    284     def test_menu(self):
    285         widget = self.create()
    286         menu = tkinter.Menu(widget, name='menu')
    287         self.checkParam(widget, 'menu', menu, eq=widget_eq)
    288         menu.destroy()
    289 
    290     def test_padx(self):
    291         widget = self.create()
    292         self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m')
    293         self.checkParam(widget, 'padx', -2, expected=0)
    294 
    295     def test_pady(self):
    296         widget = self.create()
    297         self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m')
    298         self.checkParam(widget, 'pady', -2, expected=0)
    299 
    300     def test_width(self):
    301         widget = self.create()
    302         self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=str)
    303 
    304 
    305 class OptionMenuTest(MenubuttonTest, unittest.TestCase):
    306 
    307     def create(self, default='b', values=('a', 'b', 'c'), **kwargs):
    308         return tkinter.OptionMenu(self.root, None, default, *values, **kwargs)
    309 
    310 
    311 @add_standard_options(IntegerSizeTests, StandardOptionsTests)
    312 class EntryTest(AbstractWidgetTest, unittest.TestCase):
    313     OPTIONS = (
    314         'background', 'borderwidth', 'cursor',
    315         'disabledbackground', 'disabledforeground',
    316         'exportselection', 'font', 'foreground',
    317         'highlightbackground', 'highlightcolor', 'highlightthickness',
    318         'insertbackground', 'insertborderwidth',
    319         'insertofftime', 'insertontime', 'insertwidth',
    320         'invalidcommand', 'justify', 'readonlybackground', 'relief',
    321         'selectbackground', 'selectborderwidth', 'selectforeground',
    322         'show', 'state', 'takefocus', 'textvariable',
    323         'validate', 'validatecommand', 'width', 'xscrollcommand',
    324     )
    325 
    326     def create(self, **kwargs):
    327         return tkinter.Entry(self.root, **kwargs)
    328 
    329     def test_disabledbackground(self):
    330         widget = self.create()
    331         self.checkColorParam(widget, 'disabledbackground')
    332 
    333     def test_insertborderwidth(self):
    334         widget = self.create(insertwidth=100)
    335         self.checkPixelsParam(widget, 'insertborderwidth',
    336                               0, 1.3, 2.6, 6, -2, '10p')
    337         # insertborderwidth is bounded above by a half of insertwidth.
    338         self.checkParam(widget, 'insertborderwidth', 60, expected=100//2)
    339 
    340     def test_insertwidth(self):
    341         widget = self.create()
    342         self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p')
    343         self.checkParam(widget, 'insertwidth', 0.1, expected=2)
    344         self.checkParam(widget, 'insertwidth', -2, expected=2)
    345         if pixels_round(0.9) <= 0:
    346             self.checkParam(widget, 'insertwidth', 0.9, expected=2)
    347         else:
    348             self.checkParam(widget, 'insertwidth', 0.9, expected=1)
    349 
    350     def test_invalidcommand(self):
    351         widget = self.create()
    352         self.checkCommandParam(widget, 'invalidcommand')
    353         self.checkCommandParam(widget, 'invcmd')
    354 
    355     def test_readonlybackground(self):
    356         widget = self.create()
    357         self.checkColorParam(widget, 'readonlybackground')
    358 
    359     def test_show(self):
    360         widget = self.create()
    361         self.checkParam(widget, 'show', '*')
    362         self.checkParam(widget, 'show', '')
    363         self.checkParam(widget, 'show', ' ')
    364 
    365     def test_state(self):
    366         widget = self.create()
    367         self.checkEnumParam(widget, 'state',
    368                             'disabled', 'normal', 'readonly')
    369 
    370     def test_validate(self):
    371         widget = self.create()
    372         self.checkEnumParam(widget, 'validate',
    373                 'all', 'key', 'focus', 'focusin', 'focusout', 'none')
    374 
    375     def test_validatecommand(self):
    376         widget = self.create()
    377         self.checkCommandParam(widget, 'validatecommand')
    378         self.checkCommandParam(widget, 'vcmd')
    379 
    380 
    381 @add_standard_options(StandardOptionsTests)
    382 class SpinboxTest(EntryTest, unittest.TestCase):
    383     OPTIONS = (
    384         'activebackground', 'background', 'borderwidth',
    385         'buttonbackground', 'buttoncursor', 'buttondownrelief', 'buttonuprelief',
    386         'command', 'cursor', 'disabledbackground', 'disabledforeground',
    387         'exportselection', 'font', 'foreground', 'format', 'from',
    388         'highlightbackground', 'highlightcolor', 'highlightthickness',
    389         'increment',
    390         'insertbackground', 'insertborderwidth',
    391         'insertofftime', 'insertontime', 'insertwidth',
    392         'invalidcommand', 'justify', 'relief', 'readonlybackground',
    393         'repeatdelay', 'repeatinterval',
    394         'selectbackground', 'selectborderwidth', 'selectforeground',
    395         'state', 'takefocus', 'textvariable', 'to',
    396         'validate', 'validatecommand', 'values',
    397         'width', 'wrap', 'xscrollcommand',
    398     )
    399 
    400     def create(self, **kwargs):
    401         return tkinter.Spinbox(self.root, **kwargs)
    402 
    403     test_show = None
    404 
    405     def test_buttonbackground(self):
    406         widget = self.create()
    407         self.checkColorParam(widget, 'buttonbackground')
    408 
    409     def test_buttoncursor(self):
    410         widget = self.create()
    411         self.checkCursorParam(widget, 'buttoncursor')
    412 
    413     def test_buttondownrelief(self):
    414         widget = self.create()
    415         self.checkReliefParam(widget, 'buttondownrelief')
    416 
    417     def test_buttonuprelief(self):
    418         widget = self.create()
    419         self.checkReliefParam(widget, 'buttonuprelief')
    420 
    421     def test_format(self):
    422         widget = self.create()
    423         self.checkParam(widget, 'format', '%2f')
    424         self.checkParam(widget, 'format', '%2.2f')
    425         self.checkParam(widget, 'format', '%.2f')
    426         self.checkParam(widget, 'format', '%2.f')
    427         self.checkInvalidParam(widget, 'format', '%2e-1f')
    428         self.checkInvalidParam(widget, 'format', '2.2')
    429         self.checkInvalidParam(widget, 'format', '%2.-2f')
    430         self.checkParam(widget, 'format', '%-2.02f')
    431         self.checkParam(widget, 'format', '% 2.02f')
    432         self.checkParam(widget, 'format', '% -2.200f')
    433         self.checkParam(widget, 'format', '%09.200f')
    434         self.checkInvalidParam(widget, 'format', '%d')
    435 
    436     def test_from(self):
    437         widget = self.create()
    438         self.checkParam(widget, 'to', 100.0)
    439         self.checkFloatParam(widget, 'from', -10, 10.2, 11.7)
    440         self.checkInvalidParam(widget, 'from', 200,
    441                 errmsg='-to value must be greater than -from value')
    442 
    443     def test_increment(self):
    444         widget = self.create()
    445         self.checkFloatParam(widget, 'increment', -1, 1, 10.2, 12.8, 0)
    446 
    447     def test_to(self):
    448         widget = self.create()
    449         self.checkParam(widget, 'from', -100.0)
    450         self.checkFloatParam(widget, 'to', -10, 10.2, 11.7)
    451         self.checkInvalidParam(widget, 'to', -200,
    452                 errmsg='-to value must be greater than -from value')
    453 
    454     def test_values(self):
    455         # XXX
    456         widget = self.create()
    457         self.assertEqual(widget['values'], '')
    458         self.checkParam(widget, 'values', 'mon tue wed thur')
    459         self.checkParam(widget, 'values', ('mon', 'tue', 'wed', 'thur'),
    460                         expected='mon tue wed thur')
    461         self.checkParam(widget, 'values', (42, 3.14, '', 'any string'),
    462                         expected='42 3.14 {} {any string}')
    463         self.checkParam(widget, 'values', '')
    464 
    465     def test_wrap(self):
    466         widget = self.create()
    467         self.checkBooleanParam(widget, 'wrap')
    468 
    469     def test_bbox(self):
    470         widget = self.create()
    471         self.assertIsBoundingBox(widget.bbox(0))
    472         self.assertRaises(tkinter.TclError, widget.bbox, 'noindex')
    473         self.assertRaises(tkinter.TclError, widget.bbox, None)
    474         self.assertRaises(TypeError, widget.bbox)
    475         self.assertRaises(TypeError, widget.bbox, 0, 1)
    476 
    477 
    478 @add_standard_options(StandardOptionsTests)
    479 class TextTest(AbstractWidgetTest, unittest.TestCase):
    480     OPTIONS = (
    481         'autoseparators', 'background', 'blockcursor', 'borderwidth',
    482         'cursor', 'endline', 'exportselection',
    483         'font', 'foreground', 'height',
    484         'highlightbackground', 'highlightcolor', 'highlightthickness',
    485         'inactiveselectbackground', 'insertbackground', 'insertborderwidth',
    486         'insertofftime', 'insertontime', 'insertunfocussed', 'insertwidth',
    487         'maxundo', 'padx', 'pady', 'relief',
    488         'selectbackground', 'selectborderwidth', 'selectforeground',
    489         'setgrid', 'spacing1', 'spacing2', 'spacing3', 'startline', 'state',
    490         'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap',
    491         'xscrollcommand', 'yscrollcommand',
    492     )
    493     if tcl_version < (8, 5):
    494         _stringify = True
    495 
    496     def create(self, **kwargs):
    497         return tkinter.Text(self.root, **kwargs)
    498 
    499     def test_autoseparators(self):
    500         widget = self.create()
    501         self.checkBooleanParam(widget, 'autoseparators')
    502 
    503     @requires_tcl(8, 5)
    504     def test_blockcursor(self):
    505         widget = self.create()
    506         self.checkBooleanParam(widget, 'blockcursor')
    507 
    508     @requires_tcl(8, 5)
    509     def test_endline(self):
    510         widget = self.create()
    511         text = '\n'.join('Line %d' for i in range(100))
    512         widget.insert('end', text)
    513         self.checkParam(widget, 'endline', 200, expected='')
    514         self.checkParam(widget, 'endline', -10, expected='')
    515         self.checkInvalidParam(widget, 'endline', 'spam',
    516                 errmsg='expected integer but got "spam"')
    517         self.checkParam(widget, 'endline', 50)
    518         self.checkParam(widget, 'startline', 15)
    519         self.checkInvalidParam(widget, 'endline', 10,
    520                 errmsg='-startline must be less than or equal to -endline')
    521 
    522     def test_height(self):
    523         widget = self.create()
    524         self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c')
    525         self.checkParam(widget, 'height', -100, expected=1)
    526         self.checkParam(widget, 'height', 0, expected=1)
    527 
    528     def test_maxundo(self):
    529         widget = self.create()
    530         self.checkIntegerParam(widget, 'maxundo', 0, 5, -1)
    531 
    532     @requires_tcl(8, 5)
    533     def test_inactiveselectbackground(self):
    534         widget = self.create()
    535         self.checkColorParam(widget, 'inactiveselectbackground')
    536 
    537     @requires_tcl(8, 6)
    538     def test_insertunfocussed(self):
    539         widget = self.create()
    540         self.checkEnumParam(widget, 'insertunfocussed',
    541                             'hollow', 'none', 'solid')
    542 
    543     def test_selectborderwidth(self):
    544         widget = self.create()
    545         self.checkPixelsParam(widget, 'selectborderwidth',
    546                               1.3, 2.6, -2, '10p', conv=noconv,
    547                               keep_orig=tcl_version >= (8, 5))
    548 
    549     def test_spacing1(self):
    550         widget = self.create()
    551         self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, '0.5c')
    552         self.checkParam(widget, 'spacing1', -5, expected=0)
    553 
    554     def test_spacing2(self):
    555         widget = self.create()
    556         self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, '0.1c')
    557         self.checkParam(widget, 'spacing2', -1, expected=0)
    558 
    559     def test_spacing3(self):
    560         widget = self.create()
    561         self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, '0.5c')
    562         self.checkParam(widget, 'spacing3', -10, expected=0)
    563 
    564     @requires_tcl(8, 5)
    565     def test_startline(self):
    566         widget = self.create()
    567         text = '\n'.join('Line %d' for i in range(100))
    568         widget.insert('end', text)
    569         self.checkParam(widget, 'startline', 200, expected='')
    570         self.checkParam(widget, 'startline', -10, expected='')
    571         self.checkInvalidParam(widget, 'startline', 'spam',
    572                 errmsg='expected integer but got "spam"')
    573         self.checkParam(widget, 'startline', 10)
    574         self.checkParam(widget, 'endline', 50)
    575         self.checkInvalidParam(widget, 'startline', 70,
    576                 errmsg='-startline must be less than or equal to -endline')
    577 
    578     def test_state(self):
    579         widget = self.create()
    580         if tcl_version < (8, 5):
    581             self.checkParams(widget, 'state', 'disabled', 'normal')
    582         else:
    583             self.checkEnumParam(widget, 'state', 'disabled', 'normal')
    584 
    585     def test_tabs(self):
    586         widget = self.create()
    587         if get_tk_patchlevel() < (8, 5, 11):
    588             self.checkParam(widget, 'tabs', (10.2, 20.7, '1i', '2i'),
    589                             expected=('10.2', '20.7', '1i', '2i'))
    590         else:
    591             self.checkParam(widget, 'tabs', (10.2, 20.7, '1i', '2i'))
    592         self.checkParam(widget, 'tabs', '10.2 20.7 1i 2i',
    593                         expected=('10.2', '20.7', '1i', '2i'))
    594         self.checkParam(widget, 'tabs', '2c left 4c 6c center',
    595                         expected=('2c', 'left', '4c', '6c', 'center'))
    596         self.checkInvalidParam(widget, 'tabs', 'spam',
    597                                errmsg='bad screen distance "spam"',
    598                                keep_orig=tcl_version >= (8, 5))
    599 
    600     @requires_tcl(8, 5)
    601     def test_tabstyle(self):
    602         widget = self.create()
    603         self.checkEnumParam(widget, 'tabstyle', 'tabular', 'wordprocessor')
    604 
    605     def test_undo(self):
    606         widget = self.create()
    607         self.checkBooleanParam(widget, 'undo')
    608 
    609     def test_width(self):
    610         widget = self.create()
    611         self.checkIntegerParam(widget, 'width', 402)
    612         self.checkParam(widget, 'width', -402, expected=1)
    613         self.checkParam(widget, 'width', 0, expected=1)
    614 
    615     def test_wrap(self):
    616         widget = self.create()
    617         if tcl_version < (8, 5):
    618             self.checkParams(widget, 'wrap', 'char', 'none', 'word')
    619         else:
    620             self.checkEnumParam(widget, 'wrap', 'char', 'none', 'word')
    621 
    622     def test_bbox(self):
    623         widget = self.create()
    624         self.assertIsBoundingBox(widget.bbox('1.1'))
    625         self.assertIsNone(widget.bbox('end'))
    626         self.assertRaises(tkinter.TclError, widget.bbox, 'noindex')
    627         self.assertRaises(tkinter.TclError, widget.bbox, None)
    628         self.assertRaises(TypeError, widget.bbox)
    629         self.assertRaises(TypeError, widget.bbox, '1.1', 'end')
    630 
    631 
    632 @add_standard_options(PixelSizeTests, StandardOptionsTests)
    633 class CanvasTest(AbstractWidgetTest, unittest.TestCase):
    634     OPTIONS = (
    635         'background', 'borderwidth',
    636         'closeenough', 'confine', 'cursor', 'height',
    637         'highlightbackground', 'highlightcolor', 'highlightthickness',
    638         'insertbackground', 'insertborderwidth',
    639         'insertofftime', 'insertontime', 'insertwidth',
    640         'offset', 'relief', 'scrollregion',
    641         'selectbackground', 'selectborderwidth', 'selectforeground',
    642         'state', 'takefocus',
    643         'xscrollcommand', 'xscrollincrement',
    644         'yscrollcommand', 'yscrollincrement', 'width',
    645     )
    646 
    647     _conv_pixels = round
    648     _stringify = True
    649 
    650     def create(self, **kwargs):
    651         return tkinter.Canvas(self.root, **kwargs)
    652 
    653     def test_closeenough(self):
    654         widget = self.create()
    655         self.checkFloatParam(widget, 'closeenough', 24, 2.4, 3.6, -3,
    656                              conv=float)
    657 
    658     def test_confine(self):
    659         widget = self.create()
    660         self.checkBooleanParam(widget, 'confine')
    661 
    662     def test_offset(self):
    663         widget = self.create()
    664         self.assertEqual(widget['offset'], '0,0')
    665         self.checkParams(widget, 'offset',
    666                 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center')
    667         self.checkParam(widget, 'offset', '10,20')
    668         self.checkParam(widget, 'offset', '#5,6')
    669         self.checkInvalidParam(widget, 'offset', 'spam')
    670 
    671     def test_scrollregion(self):
    672         widget = self.create()
    673         self.checkParam(widget, 'scrollregion', '0 0 200 150')
    674         self.checkParam(widget, 'scrollregion', (0, 0, 200, 150),
    675                         expected='0 0 200 150')
    676         self.checkParam(widget, 'scrollregion', '')
    677         self.checkInvalidParam(widget, 'scrollregion', 'spam',
    678                                errmsg='bad scrollRegion "spam"')
    679         self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200, 'spam'))
    680         self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200))
    681         self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200, 150, 0))
    682 
    683     def test_state(self):
    684         widget = self.create()
    685         self.checkEnumParam(widget, 'state', 'disabled', 'normal',
    686                 errmsg='bad state value "{}": must be normal or disabled')
    687 
    688     def test_xscrollincrement(self):
    689         widget = self.create()
    690         self.checkPixelsParam(widget, 'xscrollincrement',
    691                               40, 0, 41.2, 43.6, -40, '0.5i')
    692 
    693     def test_yscrollincrement(self):
    694         widget = self.create()
    695         self.checkPixelsParam(widget, 'yscrollincrement',
    696                               10, 0, 11.2, 13.6, -10, '0.1i')
    697 
    698 
    699 @add_standard_options(IntegerSizeTests, StandardOptionsTests)
    700 class ListboxTest(AbstractWidgetTest, unittest.TestCase):
    701     OPTIONS = (
    702         'activestyle', 'background', 'borderwidth', 'cursor',
    703         'disabledforeground', 'exportselection',
    704         'font', 'foreground', 'height',
    705         'highlightbackground', 'highlightcolor', 'highlightthickness',
    706         'listvariable', 'relief',
    707         'selectbackground', 'selectborderwidth', 'selectforeground',
    708         'selectmode', 'setgrid', 'state',
    709         'takefocus', 'width', 'xscrollcommand', 'yscrollcommand',
    710     )
    711 
    712     def create(self, **kwargs):
    713         return tkinter.Listbox(self.root, **kwargs)
    714 
    715     def test_activestyle(self):
    716         widget = self.create()
    717         self.checkEnumParam(widget, 'activestyle',
    718                             'dotbox', 'none', 'underline')
    719 
    720     def test_listvariable(self):
    721         widget = self.create()
    722         var = tkinter.DoubleVar(self.root)
    723         self.checkVariableParam(widget, 'listvariable', var)
    724 
    725     def test_selectmode(self):
    726         widget = self.create()
    727         self.checkParam(widget, 'selectmode', 'single')
    728         self.checkParam(widget, 'selectmode', 'browse')
    729         self.checkParam(widget, 'selectmode', 'multiple')
    730         self.checkParam(widget, 'selectmode', 'extended')
    731 
    732     def test_state(self):
    733         widget = self.create()
    734         self.checkEnumParam(widget, 'state', 'disabled', 'normal')
    735 
    736     def test_itemconfigure(self):
    737         widget = self.create()
    738         with self.assertRaisesRegex(TclError, 'item number "0" out of range'):
    739             widget.itemconfigure(0)
    740         colors = 'red orange yellow green blue white violet'.split()
    741         widget.insert('end', *colors)
    742         for i, color in enumerate(colors):
    743             widget.itemconfigure(i, background=color)
    744         with self.assertRaises(TypeError):
    745             widget.itemconfigure()
    746         with self.assertRaisesRegex(TclError, 'bad listbox index "red"'):
    747             widget.itemconfigure('red')
    748         self.assertEqual(widget.itemconfigure(0, 'background'),
    749                          ('background', 'background', 'Background', '', 'red'))
    750         self.assertEqual(widget.itemconfigure('end', 'background'),
    751                          ('background', 'background', 'Background', '', 'violet'))
    752         self.assertEqual(widget.itemconfigure('@0,0', 'background'),
    753                          ('background', 'background', 'Background', '', 'red'))
    754 
    755         d = widget.itemconfigure(0)
    756         self.assertIsInstance(d, dict)
    757         for k, v in d.items():
    758             self.assertIn(len(v), (2, 5))
    759             if len(v) == 5:
    760                 self.assertEqual(v, widget.itemconfigure(0, k))
    761                 self.assertEqual(v[4], widget.itemcget(0, k))
    762 
    763     def check_itemconfigure(self, name, value):
    764         widget = self.create()
    765         widget.insert('end', 'a', 'b', 'c', 'd')
    766         widget.itemconfigure(0, **{name: value})
    767         self.assertEqual(widget.itemconfigure(0, name)[4], value)
    768         self.assertEqual(widget.itemcget(0, name), value)
    769         with self.assertRaisesRegex(TclError, 'unknown color name "spam"'):
    770             widget.itemconfigure(0, **{name: 'spam'})
    771 
    772     def test_itemconfigure_background(self):
    773         self.check_itemconfigure('background', '#ff0000')
    774 
    775     def test_itemconfigure_bg(self):
    776         self.check_itemconfigure('bg', '#ff0000')
    777 
    778     def test_itemconfigure_fg(self):
    779         self.check_itemconfigure('fg', '#110022')
    780 
    781     def test_itemconfigure_foreground(self):
    782         self.check_itemconfigure('foreground', '#110022')
    783 
    784     def test_itemconfigure_selectbackground(self):
    785         self.check_itemconfigure('selectbackground', '#110022')
    786 
    787     def test_itemconfigure_selectforeground(self):
    788         self.check_itemconfigure('selectforeground', '#654321')
    789 
    790     def test_box(self):
    791         lb = self.create()
    792         lb.insert(0, *('el%d' % i for i in range(8)))
    793         lb.pack()
    794         self.assertIsBoundingBox(lb.bbox(0))
    795         self.assertIsNone(lb.bbox(-1))
    796         self.assertIsNone(lb.bbox(10))
    797         self.assertRaises(TclError, lb.bbox, 'noindex')
    798         self.assertRaises(TclError, lb.bbox, None)
    799         self.assertRaises(TypeError, lb.bbox)
    800         self.assertRaises(TypeError, lb.bbox, 0, 1)
    801 
    802     def test_curselection(self):
    803         lb = self.create()
    804         lb.insert(0, *('el%d' % i for i in range(8)))
    805         lb.selection_clear(0, tkinter.END)
    806         lb.selection_set(2, 4)
    807         lb.selection_set(6)
    808         self.assertEqual(lb.curselection(), (2, 3, 4, 6))
    809         self.assertRaises(TypeError, lb.curselection, 0)
    810 
    811     def test_get(self):
    812         lb = self.create()
    813         lb.insert(0, *('el%d' % i for i in range(8)))
    814         self.assertEqual(lb.get(0), 'el0')
    815         self.assertEqual(lb.get(3), 'el3')
    816         self.assertEqual(lb.get('end'), 'el7')
    817         self.assertEqual(lb.get(8), '')
    818         self.assertEqual(lb.get(-1), '')
    819         self.assertEqual(lb.get(3, 5), ('el3', 'el4', 'el5'))
    820         self.assertEqual(lb.get(5, 'end'), ('el5', 'el6', 'el7'))
    821         self.assertEqual(lb.get(5, 0), ())
    822         self.assertEqual(lb.get(0, 0), ('el0',))
    823         self.assertRaises(TclError, lb.get, 'noindex')
    824         self.assertRaises(TclError, lb.get, None)
    825         self.assertRaises(TypeError, lb.get)
    826         self.assertRaises(TclError, lb.get, 'end', 'noindex')
    827         self.assertRaises(TypeError, lb.get, 1, 2, 3)
    828         self.assertRaises(TclError, lb.get, 2.4)
    829 
    830 
    831 @add_standard_options(PixelSizeTests, StandardOptionsTests)
    832 class ScaleTest(AbstractWidgetTest, unittest.TestCase):
    833     OPTIONS = (
    834         'activebackground', 'background', 'bigincrement', 'borderwidth',
    835         'command', 'cursor', 'digits', 'font', 'foreground', 'from',
    836         'highlightbackground', 'highlightcolor', 'highlightthickness',
    837         'label', 'length', 'orient', 'relief',
    838         'repeatdelay', 'repeatinterval',
    839         'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state',
    840         'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width',
    841     )
    842     default_orient = 'vertical'
    843 
    844     def create(self, **kwargs):
    845         return tkinter.Scale(self.root, **kwargs)
    846 
    847     def test_bigincrement(self):
    848         widget = self.create()
    849         self.checkFloatParam(widget, 'bigincrement', 12.4, 23.6, -5)
    850 
    851     def test_digits(self):
    852         widget = self.create()
    853         self.checkIntegerParam(widget, 'digits', 5, 0)
    854 
    855     def test_from(self):
    856         widget = self.create()
    857         self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round)
    858 
    859     def test_label(self):
    860         widget = self.create()
    861         self.checkParam(widget, 'label', 'any string')
    862         self.checkParam(widget, 'label', '')
    863 
    864     def test_length(self):
    865         widget = self.create()
    866         self.checkPixelsParam(widget, 'length', 130, 131.2, 135.6, '5i')
    867 
    868     def test_resolution(self):
    869         widget = self.create()
    870         self.checkFloatParam(widget, 'resolution', 4.2, 0, 6.7, -2)
    871 
    872     def test_showvalue(self):
    873         widget = self.create()
    874         self.checkBooleanParam(widget, 'showvalue')
    875 
    876     def test_sliderlength(self):
    877         widget = self.create()
    878         self.checkPixelsParam(widget, 'sliderlength',
    879                               10, 11.2, 15.6, -3, '3m')
    880 
    881     def test_sliderrelief(self):
    882         widget = self.create()
    883         self.checkReliefParam(widget, 'sliderrelief')
    884 
    885     def test_tickinterval(self):
    886         widget = self.create()
    887         self.checkFloatParam(widget, 'tickinterval', 1, 4.3, 7.6, 0,
    888                              conv=float_round)
    889         self.checkParam(widget, 'tickinterval', -2, expected=2,
    890                         conv=float_round)
    891 
    892     def test_to(self):
    893         widget = self.create()
    894         self.checkFloatParam(widget, 'to', 300, 14.9, 15.1, -10,
    895                              conv=float_round)
    896 
    897 
    898 @add_standard_options(PixelSizeTests, StandardOptionsTests)
    899 class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
    900     OPTIONS = (
    901         'activebackground', 'activerelief',
    902         'background', 'borderwidth',
    903         'command', 'cursor', 'elementborderwidth',
    904         'highlightbackground', 'highlightcolor', 'highlightthickness',
    905         'jump', 'orient', 'relief',
    906         'repeatdelay', 'repeatinterval',
    907         'takefocus', 'troughcolor', 'width',
    908     )
    909     _conv_pixels = round
    910     _stringify = True
    911     default_orient = 'vertical'
    912 
    913     def create(self, **kwargs):
    914         return tkinter.Scrollbar(self.root, **kwargs)
    915 
    916     def test_activerelief(self):
    917         widget = self.create()
    918         self.checkReliefParam(widget, 'activerelief')
    919 
    920     def test_elementborderwidth(self):
    921         widget = self.create()
    922         self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, -2, '1m')
    923 
    924     def test_orient(self):
    925         widget = self.create()
    926         self.checkEnumParam(widget, 'orient', 'vertical', 'horizontal',
    927                 errmsg='bad orientation "{}": must be vertical or horizontal')
    928 
    929     def test_activate(self):
    930         sb = self.create()
    931         for e in ('arrow1', 'slider', 'arrow2'):
    932             sb.activate(e)
    933             self.assertEqual(sb.activate(), e)
    934         sb.activate('')
    935         self.assertIsNone(sb.activate())
    936         self.assertRaises(TypeError, sb.activate, 'arrow1', 'arrow2')
    937 
    938     def test_set(self):
    939         sb = self.create()
    940         sb.set(0.2, 0.4)
    941         self.assertEqual(sb.get(), (0.2, 0.4))
    942         self.assertRaises(TclError, sb.set, 'abc', 'def')
    943         self.assertRaises(TclError, sb.set, 0.6, 'def')
    944         self.assertRaises(TclError, sb.set, 0.6, None)
    945         self.assertRaises(TypeError, sb.set, 0.6)
    946         self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8)
    947 
    948 
    949 @add_standard_options(StandardOptionsTests)
    950 class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
    951     OPTIONS = (
    952         'background', 'borderwidth', 'cursor',
    953         'handlepad', 'handlesize', 'height',
    954         'opaqueresize', 'orient', 'relief',
    955         'sashcursor', 'sashpad', 'sashrelief', 'sashwidth',
    956         'showhandle', 'width',
    957     )
    958     default_orient = 'horizontal'
    959 
    960     def create(self, **kwargs):
    961         return tkinter.PanedWindow(self.root, **kwargs)
    962 
    963     def test_handlepad(self):
    964         widget = self.create()
    965         self.checkPixelsParam(widget, 'handlepad', 5, 6.4, 7.6, -3, '1m')
    966 
    967     def test_handlesize(self):
    968         widget = self.create()
    969         self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m',
    970                               conv=noconv)
    971 
    972     def test_height(self):
    973         widget = self.create()
    974         self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i',
    975                               conv=noconv)
    976 
    977     def test_opaqueresize(self):
    978         widget = self.create()
    979         self.checkBooleanParam(widget, 'opaqueresize')
    980 
    981     def test_sashcursor(self):
    982         widget = self.create()
    983         self.checkCursorParam(widget, 'sashcursor')
    984 
    985     def test_sashpad(self):
    986         widget = self.create()
    987         self.checkPixelsParam(widget, 'sashpad', 8, 1.3, 2.6, -2, '2m')
    988 
    989     def test_sashrelief(self):
    990         widget = self.create()
    991         self.checkReliefParam(widget, 'sashrelief')
    992 
    993     def test_sashwidth(self):
    994         widget = self.create()
    995         self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m',
    996                               conv=noconv)
    997 
    998     def test_showhandle(self):
    999         widget = self.create()
   1000         self.checkBooleanParam(widget, 'showhandle')
   1001 
   1002     def test_width(self):
   1003         widget = self.create()
   1004         self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i',
   1005                               conv=noconv)
   1006 
   1007     def create2(self):
   1008         p = self.create()
   1009         b = tkinter.Button(p)
   1010         c = tkinter.Button(p)
   1011         p.add(b)
   1012         p.add(c)
   1013         return p, b, c
   1014 
   1015     def test_paneconfigure(self):
   1016         p, b, c = self.create2()
   1017         self.assertRaises(TypeError, p.paneconfigure)
   1018         d = p.paneconfigure(b)
   1019         self.assertIsInstance(d, dict)
   1020         for k, v in d.items():
   1021             self.assertEqual(len(v), 5)
   1022             self.assertEqual(v, p.paneconfigure(b, k))
   1023             self.assertEqual(v[4], p.panecget(b, k))
   1024 
   1025     def check_paneconfigure(self, p, b, name, value, expected, stringify=False):
   1026         conv = lambda x: x
   1027         if not self.wantobjects or stringify:
   1028             expected = str(expected)
   1029         if self.wantobjects and stringify:
   1030             conv = str
   1031         p.paneconfigure(b, **{name: value})
   1032         self.assertEqual(conv(p.paneconfigure(b, name)[4]), expected)
   1033         self.assertEqual(conv(p.panecget(b, name)), expected)
   1034 
   1035     def check_paneconfigure_bad(self, p, b, name, msg):
   1036         with self.assertRaisesRegex(TclError, msg):
   1037             p.paneconfigure(b, **{name: 'badValue'})
   1038 
   1039     def test_paneconfigure_after(self):
   1040         p, b, c = self.create2()
   1041         self.check_paneconfigure(p, b, 'after', c, str(c))
   1042         self.check_paneconfigure_bad(p, b, 'after',
   1043                                      'bad window path name "badValue"')
   1044 
   1045     def test_paneconfigure_before(self):
   1046         p, b, c = self.create2()
   1047         self.check_paneconfigure(p, b, 'before', c, str(c))
   1048         self.check_paneconfigure_bad(p, b, 'before',
   1049                                      'bad window path name "badValue"')
   1050 
   1051     def test_paneconfigure_height(self):
   1052         p, b, c = self.create2()
   1053         self.check_paneconfigure(p, b, 'height', 10, 10,
   1054                                  stringify=get_tk_patchlevel() < (8, 5, 11))
   1055         self.check_paneconfigure_bad(p, b, 'height',
   1056                                      'bad screen distance "badValue"')
   1057 
   1058     @requires_tcl(8, 5)
   1059     def test_paneconfigure_hide(self):
   1060         p, b, c = self.create2()
   1061         self.check_paneconfigure(p, b, 'hide', False, 0)
   1062         self.check_paneconfigure_bad(p, b, 'hide',
   1063                                      'expected boolean value but got "badValue"')
   1064 
   1065     def test_paneconfigure_minsize(self):
   1066         p, b, c = self.create2()
   1067         self.check_paneconfigure(p, b, 'minsize', 10, 10)
   1068         self.check_paneconfigure_bad(p, b, 'minsize',
   1069                                      'bad screen distance "badValue"')
   1070 
   1071     def test_paneconfigure_padx(self):
   1072         p, b, c = self.create2()
   1073         self.check_paneconfigure(p, b, 'padx', 1.3, 1)
   1074         self.check_paneconfigure_bad(p, b, 'padx',
   1075                                      'bad screen distance "badValue"')
   1076 
   1077     def test_paneconfigure_pady(self):
   1078         p, b, c = self.create2()
   1079         self.check_paneconfigure(p, b, 'pady', 1.3, 1)
   1080         self.check_paneconfigure_bad(p, b, 'pady',
   1081                                      'bad screen distance "badValue"')
   1082 
   1083     def test_paneconfigure_sticky(self):
   1084         p, b, c = self.create2()
   1085         self.check_paneconfigure(p, b, 'sticky', 'nsew', 'nesw')
   1086         self.check_paneconfigure_bad(p, b, 'sticky',
   1087                                      'bad stickyness value "badValue": must '
   1088                                      'be a string containing zero or more of '
   1089                                      'n, e, s, and w')
   1090 
   1091     @requires_tcl(8, 5)
   1092     def test_paneconfigure_stretch(self):
   1093         p, b, c = self.create2()
   1094         self.check_paneconfigure(p, b, 'stretch', 'alw', 'always')
   1095         self.check_paneconfigure_bad(p, b, 'stretch',
   1096                                      'bad stretch "badValue": must be '
   1097                                      'always, first, last, middle, or never')
   1098 
   1099     def test_paneconfigure_width(self):
   1100         p, b, c = self.create2()
   1101         self.check_paneconfigure(p, b, 'width', 10, 10,
   1102                                  stringify=get_tk_patchlevel() < (8, 5, 11))
   1103         self.check_paneconfigure_bad(p, b, 'width',
   1104                                      'bad screen distance "badValue"')
   1105 
   1106 
   1107 @add_standard_options(StandardOptionsTests)
   1108 class MenuTest(AbstractWidgetTest, unittest.TestCase):
   1109     OPTIONS = (
   1110         'activebackground', 'activeborderwidth', 'activeforeground',
   1111         'background', 'borderwidth', 'cursor',
   1112         'disabledforeground', 'font', 'foreground',
   1113         'postcommand', 'relief', 'selectcolor', 'takefocus',
   1114         'tearoff', 'tearoffcommand', 'title', 'type',
   1115     )
   1116     _conv_pixels = noconv
   1117 
   1118     def create(self, **kwargs):
   1119         return tkinter.Menu(self.root, **kwargs)
   1120 
   1121     def test_postcommand(self):
   1122         widget = self.create()
   1123         self.checkCommandParam(widget, 'postcommand')
   1124 
   1125     def test_tearoff(self):
   1126         widget = self.create()
   1127         self.checkBooleanParam(widget, 'tearoff')
   1128 
   1129     def test_tearoffcommand(self):
   1130         widget = self.create()
   1131         self.checkCommandParam(widget, 'tearoffcommand')
   1132 
   1133     def test_title(self):
   1134         widget = self.create()
   1135         self.checkParam(widget, 'title', 'any string')
   1136 
   1137     def test_type(self):
   1138         widget = self.create()
   1139         self.checkEnumParam(widget, 'type',
   1140                 'normal', 'tearoff', 'menubar')
   1141 
   1142     def test_entryconfigure(self):
   1143         m1 = self.create()
   1144         m1.add_command(label='test')
   1145         self.assertRaises(TypeError, m1.entryconfigure)
   1146         with self.assertRaisesRegex(TclError, 'bad menu entry index "foo"'):
   1147             m1.entryconfigure('foo')
   1148         d = m1.entryconfigure(1)
   1149         self.assertIsInstance(d, dict)
   1150         for k, v in d.items():
   1151             self.assertIsInstance(k, str)
   1152             self.assertIsInstance(v, tuple)
   1153             self.assertEqual(len(v), 5)
   1154             self.assertEqual(v[0], k)
   1155             self.assertEqual(m1.entrycget(1, k), v[4])
   1156         m1.destroy()
   1157 
   1158     def test_entryconfigure_label(self):
   1159         m1 = self.create()
   1160         m1.add_command(label='test')
   1161         self.assertEqual(m1.entrycget(1, 'label'), 'test')
   1162         m1.entryconfigure(1, label='changed')
   1163         self.assertEqual(m1.entrycget(1, 'label'), 'changed')
   1164 
   1165     def test_entryconfigure_variable(self):
   1166         m1 = self.create()
   1167         v1 = tkinter.BooleanVar(self.root)
   1168         v2 = tkinter.BooleanVar(self.root)
   1169         m1.add_checkbutton(variable=v1, onvalue=True, offvalue=False,
   1170                            label='Nonsense')
   1171         self.assertEqual(str(m1.entrycget(1, 'variable')), str(v1))
   1172         m1.entryconfigure(1, variable=v2)
   1173         self.assertEqual(str(m1.entrycget(1, 'variable')), str(v2))
   1174 
   1175 
   1176 @add_standard_options(PixelSizeTests, StandardOptionsTests)
   1177 class MessageTest(AbstractWidgetTest, unittest.TestCase):
   1178     OPTIONS = (
   1179         'anchor', 'aspect', 'background', 'borderwidth',
   1180         'cursor', 'font', 'foreground',
   1181         'highlightbackground', 'highlightcolor', 'highlightthickness',
   1182         'justify', 'padx', 'pady', 'relief',
   1183         'takefocus', 'text', 'textvariable', 'width',
   1184     )
   1185     _conv_pad_pixels = noconv
   1186 
   1187     def create(self, **kwargs):
   1188         return tkinter.Message(self.root, **kwargs)
   1189 
   1190     def test_aspect(self):
   1191         widget = self.create()
   1192         self.checkIntegerParam(widget, 'aspect', 250, 0, -300)
   1193 
   1194 
   1195 tests_gui = (
   1196         ButtonTest, CanvasTest, CheckbuttonTest, EntryTest,
   1197         FrameTest, LabelFrameTest,LabelTest, ListboxTest,
   1198         MenubuttonTest, MenuTest, MessageTest, OptionMenuTest,
   1199         PanedWindowTest, RadiobuttonTest, ScaleTest, ScrollbarTest,
   1200         SpinboxTest, TextTest, ToplevelTest,
   1201 )
   1202 
   1203 if __name__ == '__main__':
   1204     unittest.main()
   1205