Home | History | Annotate | Download | only in test_ttk
      1 import sys
      2 import unittest
      3 import Tkinter as tkinter
      4 import ttk
      5 from test.test_support import requires, run_unittest, swap_attr
      6 from test_ttk.support import AbstractTkTest, destroy_default_root
      7 
      8 requires('gui')
      9 
     10 class LabeledScaleTest(AbstractTkTest, unittest.TestCase):
     11 
     12     def tearDown(self):
     13         self.root.update_idletasks()
     14         super(LabeledScaleTest, self).tearDown()
     15 
     16     def test_widget_destroy(self):
     17         # automatically created variable
     18         x = ttk.LabeledScale(self.root)
     19         var = x._variable._name
     20         x.destroy()
     21         self.assertRaises(tkinter.TclError, x.tk.globalgetvar, var)
     22 
     23         # manually created variable
     24         myvar = tkinter.DoubleVar(self.root)
     25         name = myvar._name
     26         x = ttk.LabeledScale(self.root, variable=myvar)
     27         x.destroy()
     28         if self.wantobjects:
     29             self.assertEqual(x.tk.globalgetvar(name), myvar.get())
     30         else:
     31             self.assertEqual(float(x.tk.globalgetvar(name)), myvar.get())
     32         del myvar
     33         self.assertRaises(tkinter.TclError, x.tk.globalgetvar, name)
     34 
     35         # checking that the tracing callback is properly removed
     36         myvar = tkinter.IntVar(self.root)
     37         # LabeledScale will start tracing myvar
     38         x = ttk.LabeledScale(self.root, variable=myvar)
     39         x.destroy()
     40         # Unless the tracing callback was removed, creating a new
     41         # LabeledScale with the same var will cause an error now. This
     42         # happens because the variable will be set to (possibly) a new
     43         # value which causes the tracing callback to be called and then
     44         # it tries calling instance attributes not yet defined.
     45         ttk.LabeledScale(self.root, variable=myvar)
     46         if hasattr(sys, 'last_type'):
     47             self.assertNotEqual(sys.last_type, tkinter.TclError)
     48 
     49 
     50     def test_initialization_no_master(self):
     51         # no master passing
     52         with swap_attr(tkinter, '_default_root', None), \
     53              swap_attr(tkinter, '_support_default_root', True):
     54             try:
     55                 x = ttk.LabeledScale()
     56                 self.assertIsNotNone(tkinter._default_root)
     57                 self.assertEqual(x.master, tkinter._default_root)
     58                 self.assertEqual(x.tk, tkinter._default_root.tk)
     59                 x.destroy()
     60             finally:
     61                 destroy_default_root()
     62 
     63     def test_initialization(self):
     64         # master passing
     65         master = tkinter.Frame(self.root)
     66         x = ttk.LabeledScale(master)
     67         self.assertEqual(x.master, master)
     68         x.destroy()
     69 
     70         # variable initialization/passing
     71         passed_expected = (('0', 0), (0, 0), (10, 10),
     72             (-1, -1), (sys.maxint + 1, sys.maxint + 1))
     73         if self.wantobjects:
     74             passed_expected += ((2.5, 2),)
     75         for pair in passed_expected:
     76             x = ttk.LabeledScale(self.root, from_=pair[0])
     77             self.assertEqual(x.value, pair[1])
     78             x.destroy()
     79         x = ttk.LabeledScale(self.root, from_='2.5')
     80         self.assertRaises(ValueError, x._variable.get)
     81         x.destroy()
     82         x = ttk.LabeledScale(self.root, from_=None)
     83         self.assertRaises(ValueError, x._variable.get)
     84         x.destroy()
     85         # variable should have its default value set to the from_ value
     86         myvar = tkinter.DoubleVar(self.root, value=20)
     87         x = ttk.LabeledScale(self.root, variable=myvar)
     88         self.assertEqual(x.value, 0)
     89         x.destroy()
     90         # check that it is really using a DoubleVar
     91         x = ttk.LabeledScale(self.root, variable=myvar, from_=0.5)
     92         self.assertEqual(x.value, 0.5)
     93         self.assertEqual(x._variable._name, myvar._name)
     94         x.destroy()
     95 
     96         # widget positionment
     97         def check_positions(scale, scale_pos, label, label_pos):
     98             self.assertEqual(scale.pack_info()['side'], scale_pos)
     99             self.assertEqual(label.place_info()['anchor'], label_pos)
    100         x = ttk.LabeledScale(self.root, compound='top')
    101         check_positions(x.scale, 'bottom', x.label, 'n')
    102         x.destroy()
    103         x = ttk.LabeledScale(self.root, compound='bottom')
    104         check_positions(x.scale, 'top', x.label, 's')
    105         x.destroy()
    106         # invert default positions
    107         x = ttk.LabeledScale(self.root, compound='unknown')
    108         check_positions(x.scale, 'top', x.label, 's')
    109         x.destroy()
    110         x = ttk.LabeledScale(self.root) # take default positions
    111         check_positions(x.scale, 'bottom', x.label, 'n')
    112         x.destroy()
    113 
    114         # extra, and invalid, kwargs
    115         self.assertRaises(tkinter.TclError, ttk.LabeledScale, master, a='b')
    116 
    117 
    118     def test_horizontal_range(self):
    119         lscale = ttk.LabeledScale(self.root, from_=0, to=10)
    120         lscale.pack()
    121         lscale.wait_visibility()
    122         lscale.update()
    123 
    124         linfo_1 = lscale.label.place_info()
    125         prev_xcoord = lscale.scale.coords()[0]
    126         self.assertEqual(prev_xcoord, int(linfo_1['x']))
    127         # change range to: from -5 to 5. This should change the x coord of
    128         # the scale widget, since 0 is at the middle of the new
    129         # range.
    130         lscale.scale.configure(from_=-5, to=5)
    131         # The following update is needed since the test doesn't use mainloop,
    132         # at the same time this shouldn't affect test outcome
    133         lscale.update()
    134         curr_xcoord = lscale.scale.coords()[0]
    135         self.assertNotEqual(prev_xcoord, curr_xcoord)
    136         # the label widget should have been repositioned too
    137         linfo_2 = lscale.label.place_info()
    138         self.assertEqual(lscale.label['text'], 0 if self.wantobjects else '0')
    139         self.assertEqual(curr_xcoord, int(linfo_2['x']))
    140         # change the range back
    141         lscale.scale.configure(from_=0, to=10)
    142         self.assertNotEqual(prev_xcoord, curr_xcoord)
    143         self.assertEqual(prev_xcoord, int(linfo_1['x']))
    144 
    145         lscale.destroy()
    146 
    147 
    148     def test_variable_change(self):
    149         x = ttk.LabeledScale(self.root)
    150         x.pack()
    151         x.wait_visibility()
    152         x.update()
    153 
    154         curr_xcoord = x.scale.coords()[0]
    155         newval = x.value + 1
    156         x.value = newval
    157         # The following update is needed since the test doesn't use mainloop,
    158         # at the same time this shouldn't affect test outcome
    159         x.update()
    160         self.assertEqual(x.label['text'],
    161                          newval if self.wantobjects else str(newval))
    162         self.assertGreater(x.scale.coords()[0], curr_xcoord)
    163         self.assertEqual(x.scale.coords()[0],
    164             int(x.label.place_info()['x']))
    165 
    166         # value outside range
    167         if self.wantobjects:
    168             conv = lambda x: x
    169         else:
    170             conv = int
    171         x.value = conv(x.scale['to']) + 1 # no changes shouldn't happen
    172         x.update()
    173         self.assertEqual(conv(x.label['text']), newval)
    174         self.assertEqual(x.scale.coords()[0],
    175             int(x.label.place_info()['x']))
    176 
    177         x.destroy()
    178 
    179 
    180     def test_resize(self):
    181         x = ttk.LabeledScale(self.root)
    182         x.pack(expand=True, fill='both')
    183         x.wait_visibility()
    184         x.update()
    185 
    186         width, height = x.master.winfo_width(), x.master.winfo_height()
    187         width_new, height_new = width * 2, height * 2
    188 
    189         x.value = 3
    190         x.update()
    191         x.master.wm_geometry("%dx%d" % (width_new, height_new))
    192         self.assertEqual(int(x.label.place_info()['x']),
    193             x.scale.coords()[0])
    194 
    195         # Reset geometry
    196         x.master.wm_geometry("%dx%d" % (width, height))
    197         x.destroy()
    198 
    199 
    200 class OptionMenuTest(AbstractTkTest, unittest.TestCase):
    201 
    202     def setUp(self):
    203         super(OptionMenuTest, self).setUp()
    204         self.textvar = tkinter.StringVar(self.root)
    205 
    206     def tearDown(self):
    207         del self.textvar
    208         super(OptionMenuTest, self).tearDown()
    209 
    210 
    211     def test_widget_destroy(self):
    212         var = tkinter.StringVar(self.root)
    213         optmenu = ttk.OptionMenu(self.root, var)
    214         name = var._name
    215         optmenu.update_idletasks()
    216         optmenu.destroy()
    217         self.assertEqual(optmenu.tk.globalgetvar(name), var.get())
    218         del var
    219         self.assertRaises(tkinter.TclError, optmenu.tk.globalgetvar, name)
    220 
    221 
    222     def test_initialization(self):
    223         self.assertRaises(tkinter.TclError,
    224             ttk.OptionMenu, self.root, self.textvar, invalid='thing')
    225 
    226         optmenu = ttk.OptionMenu(self.root, self.textvar, 'b', 'a', 'b')
    227         self.assertEqual(optmenu._variable.get(), 'b')
    228 
    229         self.assertTrue(optmenu['menu'])
    230         self.assertTrue(optmenu['textvariable'])
    231 
    232         optmenu.destroy()
    233 
    234 
    235     def test_menu(self):
    236         items = ('a', 'b', 'c')
    237         default = 'a'
    238         optmenu = ttk.OptionMenu(self.root, self.textvar, default, *items)
    239         found_default = False
    240         for i in range(len(items)):
    241             value = optmenu['menu'].entrycget(i, 'value')
    242             self.assertEqual(value, items[i])
    243             if value == default:
    244                 found_default = True
    245         self.assertTrue(found_default)
    246         optmenu.destroy()
    247 
    248         # default shouldn't be in menu if it is not part of values
    249         default = 'd'
    250         optmenu = ttk.OptionMenu(self.root, self.textvar, default, *items)
    251         curr = None
    252         i = 0
    253         while True:
    254             last, curr = curr, optmenu['menu'].entryconfigure(i, 'value')
    255             if last == curr:
    256                 # no more menu entries
    257                 break
    258             self.assertNotEqual(curr, default)
    259             i += 1
    260         self.assertEqual(i, len(items))
    261 
    262         # check that variable is updated correctly
    263         optmenu.pack()
    264         optmenu.wait_visibility()
    265         optmenu['menu'].invoke(0)
    266         self.assertEqual(optmenu._variable.get(), items[0])
    267 
    268         # changing to an invalid index shouldn't change the variable
    269         self.assertRaises(tkinter.TclError, optmenu['menu'].invoke, -1)
    270         self.assertEqual(optmenu._variable.get(), items[0])
    271 
    272         optmenu.destroy()
    273 
    274         # specifying a callback
    275         success = []
    276         def cb_test(item):
    277             self.assertEqual(item, items[1])
    278             success.append(True)
    279         optmenu = ttk.OptionMenu(self.root, self.textvar, 'a', command=cb_test,
    280             *items)
    281         optmenu['menu'].invoke(1)
    282         if not success:
    283             self.fail("Menu callback not invoked")
    284 
    285         optmenu.destroy()
    286 
    287 
    288 tests_gui = (LabeledScaleTest, OptionMenuTest)
    289 
    290 if __name__ == "__main__":
    291     run_unittest(*tests_gui)
    292