Issue18130: Test class idlelib.configSectionNameDialog.GetCfgSectionNameDialog.

Fix bug in existing human test and add instructions; fix two bugs in tested
code; remove redundancies, add spaces, and change two internal method names.
Add mock_tk with mocks for tkinter.Variable subclasses and tkinter.messagebox.
Use mocks in test_config_name to unittest methods that are otherwise gui-free.
This commit is contained in:
Terry Jan Reedy 2013-06-05 14:22:26 -04:00
parent a534fc4b3b
commit 247bd5ea30
3 changed files with 198 additions and 51 deletions

View file

@ -1,97 +1,106 @@
"""
Dialog that allows user to specify a new config file section name.
Used to get new highlight theme and keybinding set names.
The 'return value' for the dialog, used two placed in configDialog.py,
is the .result attribute set in the Ok and Cancel methods.
"""
from tkinter import *
import tkinter.messagebox as tkMessageBox
class GetCfgSectionNameDialog(Toplevel):
def __init__(self,parent,title,message,usedNames):
def __init__(self, parent, title, message, used_names):
"""
message - string, informational message to display
usedNames - list, list of names already in use for validity check
used_names - string collection, names already in use for validity check
"""
Toplevel.__init__(self, parent)
self.configure(borderwidth=5)
self.resizable(height=FALSE,width=FALSE)
self.resizable(height=FALSE, width=FALSE)
self.title(title)
self.transient(parent)
self.grab_set()
self.protocol("WM_DELETE_WINDOW", self.Cancel)
self.parent = parent
self.message=message
self.usedNames=usedNames
self.result=''
self.CreateWidgets()
self.withdraw() #hide while setting geometry
self.message = message
self.used_names = used_names
self.create_widgets()
self.withdraw() #hide while setting geometry
self.update_idletasks()
#needs to be done here so that the winfo_reqwidth is valid
self.messageInfo.config(width=self.frameMain.winfo_reqwidth())
self.geometry("+%d+%d" %
((parent.winfo_rootx()+((parent.winfo_width()/2)
-(self.winfo_reqwidth()/2)),
parent.winfo_rooty()+((parent.winfo_height()/2)
-(self.winfo_reqheight()/2)) )) ) #centre dialog over parent
self.deiconify() #geometry set, unhide
self.geometry(
"+%d+%d" % (
parent.winfo_rootx() +
(parent.winfo_width()/2 - self.winfo_reqwidth()/2),
parent.winfo_rooty() +
(parent.winfo_height()/2 - self.winfo_reqheight()/2)
) ) #centre dialog over parent
self.deiconify() #geometry set, unhide
self.wait_window()
def CreateWidgets(self):
self.name=StringVar(self)
self.fontSize=StringVar(self)
self.frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
self.frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
self.messageInfo=Message(self.frameMain,anchor=W,justify=LEFT,padx=5,pady=5,
text=self.message)#,aspect=200)
entryName=Entry(self.frameMain,textvariable=self.name,width=30)
def create_widgets(self):
self.name = StringVar(self.parent)
self.fontSize = StringVar(self.parent)
self.frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
self.messageInfo = Message(self.frameMain, anchor=W, justify=LEFT,
padx=5, pady=5, text=self.message) #,aspect=200)
entryName = Entry(self.frameMain, textvariable=self.name, width=30)
entryName.focus_set()
self.messageInfo.pack(padx=5,pady=5)#,expand=TRUE,fill=BOTH)
entryName.pack(padx=5,pady=5)
frameButtons=Frame(self)
frameButtons.pack(side=BOTTOM,fill=X)
self.buttonOk = Button(frameButtons,text='Ok',
width=8,command=self.Ok)
self.buttonOk.grid(row=0,column=0,padx=5,pady=5)
self.buttonCancel = Button(frameButtons,text='Cancel',
width=8,command=self.Cancel)
self.buttonCancel.grid(row=0,column=1,padx=5,pady=5)
self.messageInfo.pack(padx=5, pady=5) #, expand=TRUE, fill=BOTH)
entryName.pack(padx=5, pady=5)
def NameOk(self):
#simple validity check for a sensible
#ConfigParser file section name
nameOk=1
name=self.name.get()
name.strip()
frameButtons = Frame(self, pady=2)
frameButtons.pack(side=BOTTOM)
self.buttonOk = Button(frameButtons, text='Ok',
width=8, command=self.Ok)
self.buttonOk.pack(side=LEFT, padx=5)
self.buttonCancel = Button(frameButtons, text='Cancel',
width=8, command=self.Cancel)
self.buttonCancel.pack(side=RIGHT, padx=5)
def name_ok(self):
''' After stripping entered name, check that it is a sensible
ConfigParser file section name. Return it if it is, '' if not.
'''
name = self.name.get().strip()
if not name: #no name specified
tkMessageBox.showerror(title='Name Error',
message='No name specified.', parent=self)
nameOk=0
elif len(name)>30: #name too long
tkMessageBox.showerror(title='Name Error',
message='Name too long. It should be no more than '+
'30 characters.', parent=self)
nameOk=0
elif name in self.usedNames:
name = ''
elif name in self.used_names:
tkMessageBox.showerror(title='Name Error',
message='This name is already in use.', parent=self)
nameOk=0
return nameOk
name = ''
return name
def Ok(self, event=None):
if self.NameOk():
self.result=self.name.get().strip()
name = self.name_ok()
if name:
self.result = name
self.destroy()
def Cancel(self, event=None):
self.result=''
self.result = ''
self.destroy()
if __name__ == '__main__':
#test the dialog
root=Tk()
import unittest
unittest.main('idlelib.idle_test.test_config_name', verbosity=2, exit=False)
# also human test the dialog
root = Tk()
def run():
keySeq=''
dlg=GetCfgSectionNameDialog(root,'Get Name',
'The information here should need to be word wrapped. Test.')
"After the text entered with [Ok] is stripped, <nothing>, "
"'abc', or more that 30 chars are errors. "
"Close with a valid entry (printed), [Cancel], or [X]",
{'abc'})
print(dlg.result)
Button(root,text='Dialog',command=run).pack()
Message(root, text='').pack() # will be needed for oher dialog tests
Button(root, text='Click to begin dialog test', command=run).pack()
root.mainloop()