@@ -1458,6 +1458,192 @@ def test_entryconfigure_variable(self):
14581458 m1 .entryconfigure (1 , variable = v2 )
14591459 self .assertEqual (str (m1 .entrycget (1 , 'variable' )), str (v2 ))
14601460
1461+ def test_add (self ):
1462+ m = self .create (tearoff = False )
1463+ m .add_command (label = 'Command' )
1464+ m .add_checkbutton (label = 'Checkbutton' )
1465+ m .add_radiobutton (label = 'Radiobutton' )
1466+ m .add_separator ()
1467+ m .add_cascade (label = 'Cascade' , menu = tkinter .Menu (m , tearoff = False ))
1468+ self .assertEqual (m .index ('end' ), 4 )
1469+ self .assertEqual ([m .type (i ) for i in range (5 )],
1470+ ['command' , 'checkbutton' , 'radiobutton' ,
1471+ 'separator' , 'cascade' ])
1472+ self .assertEqual (m .entrycget (0 , 'label' ), 'Command' )
1473+ self .assertRaisesRegex (TclError , 'bad menu entry type "spam"' ,
1474+ m .add , 'spam' )
1475+
1476+ def test_insert (self ):
1477+ m = self .create (tearoff = False )
1478+ m .add_command (label = 'A' )
1479+ m .add_command (label = 'C' )
1480+ m .insert_command (1 , label = 'B' )
1481+ m .insert_separator (0 )
1482+ m .insert_checkbutton ('end' , label = 'D' )
1483+ m .insert_radiobutton (0 , label = 'top' )
1484+ m .insert_cascade (2 , label = 'sub' ,
1485+ menu = tkinter .Menu (m , tearoff = False ))
1486+ self .assertEqual (
1487+ [m .type (i ) for i in range (m .index ('end' ) + 1 )],
1488+ ['radiobutton' , 'separator' , 'cascade' , 'command' ,
1489+ 'command' , 'command' , 'checkbutton' ])
1490+ self .assertEqual (
1491+ [m .entrycget (i , 'label' ) for i in (3 , 4 , 5 )],
1492+ ['A' , 'B' , 'C' ])
1493+ self .assertRaisesRegex (TclError , 'bad menu entry type "spam"' ,
1494+ m .insert , 0 , 'spam' )
1495+ self .assertRaisesRegex (TclError , 'bad menu entry index "spam"' ,
1496+ m .insert_command , 'spam' , label = 'z' )
1497+
1498+ def test_delete (self ):
1499+ m = self .create (tearoff = False )
1500+ commands = []
1501+ for label in 'ABCDE' :
1502+ m .add_command (label = label ,
1503+ command = lambda label = label : commands .append (label ))
1504+ # The Tcl command for a deleted item is cleaned up.
1505+ funcid = str (m .entrycget (2 , 'command' ))
1506+ self .assertEqual (
1507+ m .tk .splitlist (m .tk .call ('info' , 'commands' , funcid )), (funcid ,))
1508+
1509+ m .delete (2 ) # Delete a single item ('C').
1510+ self .assertEqual ([m .entrycget (i , 'label' ) for i in range (4 )],
1511+ ['A' , 'B' , 'D' , 'E' ])
1512+ self .assertEqual (
1513+ m .tk .splitlist (m .tk .call ('info' , 'commands' , funcid )), ())
1514+
1515+ m .delete (1 , 2 ) # Delete a range ('B' and 'D').
1516+ self .assertEqual ([m .entrycget (i , 'label' ) for i in range (2 )],
1517+ ['A' , 'E' ])
1518+ self .assertRaises (TypeError , m .delete )
1519+
1520+ def test_index (self ):
1521+ m = self .create (tearoff = False )
1522+ self .assertIsNone (m .index ('end' ))
1523+ m .add_command (label = 'First' )
1524+ m .add_command (label = 'Second' )
1525+ self .assertEqual (m .index ('end' ), 1 )
1526+ self .assertEqual (m .index ('last' ), 1 )
1527+ self .assertEqual (m .index ('Second' ), 1 )
1528+ self .assertEqual (m .index (0 ), 0 )
1529+ # 'active' and 'none' map to None when no item is active.
1530+ self .assertIsNone (m .index ('active' ))
1531+ self .assertIsNone (m .index ('none' ))
1532+ self .assertRaisesRegex (TclError , 'bad menu entry index "spam"' ,
1533+ m .index , 'spam' )
1534+
1535+ def test_invoke (self ):
1536+ m = self .create (tearoff = False )
1537+ commands = []
1538+ m .add_command (label = 'Command' ,
1539+ command = lambda : commands .append ('invoked' ))
1540+ var = tkinter .IntVar (self .root )
1541+ m .add_checkbutton (label = 'Check' , variable = var ,
1542+ onvalue = 1 , offvalue = 0 )
1543+ rvar = tkinter .StringVar (self .root )
1544+ m .add_radiobutton (label = 'Radio' , variable = rvar , value = 'on' )
1545+
1546+ m .invoke (0 )
1547+ self .assertEqual (commands , ['invoked' ])
1548+ m .invoke (1 )
1549+ self .assertEqual (var .get (), 1 )
1550+ m .invoke (1 )
1551+ self .assertEqual (var .get (), 0 )
1552+ m .invoke (2 )
1553+ self .assertEqual (rvar .get (), 'on' )
1554+ self .assertRaisesRegex (TclError , 'bad menu entry index "spam"' ,
1555+ m .invoke , 'spam' )
1556+
1557+ def test_xposition_yposition (self ):
1558+ m = self .create (tearoff = False )
1559+ m .add_command (label = 'First' )
1560+ m .add_command (label = 'Second' )
1561+ m .update_idletasks ()
1562+ self .assertIsInstance (m .xposition (0 ), int )
1563+ y0 = m .yposition (0 )
1564+ y1 = m .yposition (1 )
1565+ self .assertIsInstance (y0 , int )
1566+ self .assertLess (y0 , y1 )
1567+ # An out-of-range index gives the position past the last item.
1568+ self .assertEqual (m .xposition ('end' ), m .xposition (1 ))
1569+ self .assertRaisesRegex (TclError , 'bad menu entry index "spam"' ,
1570+ m .xposition , 'spam' )
1571+ self .assertRaisesRegex (TclError , 'bad menu entry index "spam"' ,
1572+ m .yposition , 'spam' )
1573+
1574+ def test_post_unpost (self ):
1575+ m = self .create (tearoff = False )
1576+ if m ._windowingsystem != 'x11' :
1577+ # Posting a menu is modal on Windows and uses a native, unmapped
1578+ # menu on Aqua, so it cannot be tested synchronously there.
1579+ self .skipTest ('menu posting is not testable on this platform' )
1580+ m .add_command (label = 'First' )
1581+ m .add_command (label = 'Second' )
1582+ self .assertFalse (m .winfo_ismapped ())
1583+
1584+ m .post (0 , 0 )
1585+ m .update ()
1586+ self .assertTrue (m .winfo_ismapped ())
1587+ m .unpost ()
1588+ m .update ()
1589+ self .assertFalse (m .winfo_ismapped ())
1590+
1591+ m .tk_popup (0 , 0 )
1592+ m .update ()
1593+ self .assertTrue (m .winfo_ismapped ())
1594+ m .unpost ()
1595+ m .update ()
1596+ self .assertFalse (m .winfo_ismapped ())
1597+
1598+ def check_entry_option (self , m , index , option , value , expected = None ):
1599+ if expected is None :
1600+ expected = value
1601+ m .entryconfigure (index , ** {option : value })
1602+ self .assertEqual (str (m .entrycget (index , option )), str (expected ))
1603+ self .assertEqual (str (m .entryconfigure (index , option )[4 ]), str (expected ))
1604+
1605+ def test_entry_options (self ):
1606+ m = self .create (tearoff = False )
1607+ m .add_command (label = 'Command' )
1608+ self .check_entry_option (m , 0 , 'accelerator' , 'Ctrl+O' )
1609+ self .check_entry_option (m , 0 , 'underline' , 2 )
1610+ self .check_entry_option (m , 0 , 'state' , 'disabled' )
1611+ self .check_entry_option (m , 0 , 'background' , 'red' )
1612+ self .check_entry_option (m , 0 , 'foreground' , 'blue' )
1613+ self .check_entry_option (m , 0 , 'columnbreak' , 1 )
1614+ self .check_entry_option (m , 0 , 'hidemargin' , 1 )
1615+
1616+ m .add_checkbutton (label = 'Checkbutton' )
1617+ self .check_entry_option (m , 1 , 'onvalue' , 'Y' )
1618+ self .check_entry_option (m , 1 , 'offvalue' , 'N' )
1619+ self .check_entry_option (m , 1 , 'indicatoron' , 0 )
1620+
1621+ m .add_radiobutton (label = 'Radiobutton' )
1622+ self .check_entry_option (m , 2 , 'value' , 'V' )
1623+ self .check_entry_option (m , 2 , 'selectcolor' , 'green' )
1624+
1625+ def test_entry_options_invalid (self ):
1626+ m = self .create (tearoff = False )
1627+ m .add_command (label = 'Command' )
1628+ self .assertRaisesRegex (TclError , 'unknown option "-spam"' ,
1629+ m .entrycget , 0 , 'spam' )
1630+ self .assertRaisesRegex (TclError , 'unknown option "-spam"' ,
1631+ m .entryconfigure , 0 , spam = 'x' )
1632+ self .assertRaisesRegex (TclError , 'bad state "spam"' ,
1633+ m .entryconfigure , 0 , state = 'spam' )
1634+ # Tk < 9 reports "expected integer but got ...", while Tk 9, where
1635+ # underline accepts an index, reports "bad index ...".
1636+ self .assertRaisesRegex (TclError ,
1637+ r'(expected integer but got|bad index) "spam"' ,
1638+ m .entryconfigure , 0 , underline = 'spam' )
1639+ self .assertRaisesRegex (TclError , 'unknown color name "spam"' ,
1640+ m .entryconfigure , 0 , background = 'spam' )
1641+ self .assertRaisesRegex (TclError , 'expected boolean value but got "spam"' ,
1642+ m .entryconfigure , 0 , columnbreak = 'spam' )
1643+ # onvalue applies only to checkbutton and radiobutton entries.
1644+ self .assertRaisesRegex (TclError , 'unknown option "-onvalue"' ,
1645+ m .entrycget , 0 , 'onvalue' )
1646+
14611647
14621648@add_standard_options (PixelSizeTests , StandardOptionsTests )
14631649class MessageTest (AbstractWidgetTest , unittest .TestCase ):
0 commit comments