bpo-30780: Add IDLE configdialog tests (GH-3592)
Expose dialog buttons to test code and complete their test coverage.
Complete test coverage for highlights and keys tabs.
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
(cherry picked from commit dd023ad161
)
Co-authored-by: Cheryl Sabella <cheryl.sabella@gmail.com>
This commit is contained in:
parent
414ab5de48
commit
5aefee6f98
|
@ -3,6 +3,9 @@ Released on 2019-12-16?
|
|||
======================================
|
||||
|
||||
|
||||
bpo-30780: Add remaining configdialog tests for buttons and
|
||||
highlights and keys tabs.
|
||||
|
||||
bpo-39388: Settings dialog Cancel button cancels pending changes.
|
||||
|
||||
bpo-39050: Settings dialog Help button again displays help text.
|
||||
|
|
|
@ -149,17 +149,19 @@ class ConfigDialog(Toplevel):
|
|||
else:
|
||||
padding_args = {'padding': (6, 3)}
|
||||
outer = Frame(self, padding=2)
|
||||
buttons = Frame(outer, padding=2)
|
||||
buttons_frame = Frame(outer, padding=2)
|
||||
self.buttons = {}
|
||||
for txt, cmd in (
|
||||
('Ok', self.ok),
|
||||
('Apply', self.apply),
|
||||
('Cancel', self.cancel),
|
||||
('Help', self.help)):
|
||||
Button(buttons, text=txt, command=cmd, takefocus=FALSE,
|
||||
**padding_args).pack(side=LEFT, padx=5)
|
||||
self.buttons[txt] = Button(buttons_frame, text=txt, command=cmd,
|
||||
takefocus=FALSE, **padding_args)
|
||||
self.buttons[txt].pack(side=LEFT, padx=5)
|
||||
# Add space above buttons.
|
||||
Frame(outer, height=2, borderwidth=0).pack(side=TOP)
|
||||
buttons.pack(side=BOTTOM)
|
||||
buttons_frame.pack(side=BOTTOM)
|
||||
return outer
|
||||
|
||||
def ok(self):
|
||||
|
@ -205,7 +207,6 @@ class ConfigDialog(Toplevel):
|
|||
|
||||
Attributes accessed:
|
||||
note
|
||||
|
||||
Methods:
|
||||
view_text: Method from textview module.
|
||||
"""
|
||||
|
@ -852,6 +853,7 @@ class HighPage(Frame):
|
|||
text.configure(
|
||||
font=('courier', 12, ''), cursor='hand2', width=1, height=1,
|
||||
takefocus=FALSE, highlightthickness=0, wrap=NONE)
|
||||
# Prevent perhaps invisible selection of word or slice.
|
||||
text.bind('<Double-Button-1>', lambda e: 'break')
|
||||
text.bind('<B1-Motion>', lambda e: 'break')
|
||||
string_tags=(
|
||||
|
@ -1284,8 +1286,7 @@ class HighPage(Frame):
|
|||
theme_name - string, the name of the new theme
|
||||
theme - dictionary containing the new theme
|
||||
"""
|
||||
if not idleConf.userCfg['highlight'].has_section(theme_name):
|
||||
idleConf.userCfg['highlight'].add_section(theme_name)
|
||||
idleConf.userCfg['highlight'].AddSection(theme_name)
|
||||
for element in theme:
|
||||
value = theme[element]
|
||||
idleConf.userCfg['highlight'].SetOption(theme_name, element, value)
|
||||
|
@ -1730,8 +1731,7 @@ class KeysPage(Frame):
|
|||
keyset_name - string, the name of the new key set
|
||||
keyset - dictionary containing the new keybindings
|
||||
"""
|
||||
if not idleConf.userCfg['keys'].has_section(keyset_name):
|
||||
idleConf.userCfg['keys'].add_section(keyset_name)
|
||||
idleConf.userCfg['keys'].AddSection(keyset_name)
|
||||
for event in keyset:
|
||||
value = keyset[event]
|
||||
idleConf.userCfg['keys'].SetOption(keyset_name, event, value)
|
||||
|
|
|
@ -8,7 +8,7 @@ requires('gui')
|
|||
import unittest
|
||||
from unittest import mock
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
from tkinter import Tk, StringVar, IntVar, BooleanVar, DISABLED, NORMAL
|
||||
from tkinter import (Tk, StringVar, IntVar, BooleanVar, DISABLED, NORMAL)
|
||||
from idlelib import config
|
||||
from idlelib.configdialog import idleConf, changes, tracers
|
||||
|
||||
|
@ -30,6 +30,7 @@ highpage = changes['highlight']
|
|||
keyspage = changes['keys']
|
||||
extpage = changes['extensions']
|
||||
|
||||
|
||||
def setUpModule():
|
||||
global root, dialog
|
||||
idleConf.userCfg = testcfg
|
||||
|
@ -37,6 +38,7 @@ def setUpModule():
|
|||
# root.withdraw() # Comment out, see issue 30870
|
||||
dialog = configdialog.ConfigDialog(root, 'Test', _utest=True)
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
global root, dialog
|
||||
idleConf.userCfg = usercfg
|
||||
|
@ -48,22 +50,56 @@ def tearDownModule():
|
|||
root = dialog = None
|
||||
|
||||
|
||||
class DialogTest(unittest.TestCase):
|
||||
class ConfigDialogTest(unittest.TestCase):
|
||||
|
||||
@mock.patch(__name__+'.dialog.destroy', new_callable=Func)
|
||||
def test_cancel(self, destroy):
|
||||
def test_deactivate_current_config(self):
|
||||
pass
|
||||
|
||||
def activate_config_changes(self):
|
||||
pass
|
||||
|
||||
|
||||
class ButtonTest(unittest.TestCase):
|
||||
|
||||
def test_click_ok(self):
|
||||
d = dialog
|
||||
apply = d.apply = mock.Mock()
|
||||
destroy = d.destroy = mock.Mock()
|
||||
d.buttons['Ok'].invoke()
|
||||
apply.assert_called_once()
|
||||
destroy.assert_called_once()
|
||||
del d.destroy, d.apply
|
||||
|
||||
def test_click_apply(self):
|
||||
d = dialog
|
||||
deactivate = d.deactivate_current_config = mock.Mock()
|
||||
save_ext = d.save_all_changed_extensions = mock.Mock()
|
||||
activate = d.activate_config_changes = mock.Mock()
|
||||
d.buttons['Apply'].invoke()
|
||||
deactivate.assert_called_once()
|
||||
save_ext.assert_called_once()
|
||||
activate.assert_called_once()
|
||||
del d.save_all_changed_extensions
|
||||
del d.activate_config_changes, d.deactivate_current_config
|
||||
|
||||
def test_click_cancel(self):
|
||||
d = dialog
|
||||
d.destroy = Func()
|
||||
changes['main']['something'] = 1
|
||||
dialog.cancel()
|
||||
d.buttons['Cancel'].invoke()
|
||||
self.assertEqual(changes['main'], {})
|
||||
self.assertEqual(destroy.called, 1)
|
||||
self.assertEqual(d.destroy.called, 1)
|
||||
del d.destroy
|
||||
|
||||
@mock.patch('idlelib.configdialog.view_text', new_callable=Func)
|
||||
def test_help(self, view):
|
||||
def test_click_help(self):
|
||||
dialog.note.select(dialog.keyspage)
|
||||
dialog.help()
|
||||
s = view.kwds['contents']
|
||||
self.assertTrue(s.startswith('When you click') and
|
||||
s.endswith('a different name.\n'))
|
||||
with mock.patch.object(configdialog, 'view_text',
|
||||
new_callable=Func) as view:
|
||||
dialog.buttons['Help'].invoke()
|
||||
title, contents = view.kwds['title'], view.kwds['contents']
|
||||
self.assertEqual(title, 'Help for IDLE preferences')
|
||||
self.assertTrue(contents.startswith('When you click') and
|
||||
contents.endswith('a different name.\n'))
|
||||
|
||||
|
||||
class FontPageTest(unittest.TestCase):
|
||||
|
@ -438,6 +474,48 @@ class HighPageTest(unittest.TestCase):
|
|||
eq(d.highlight_target.get(), elem[tag])
|
||||
eq(d.set_highlight_target.called, count)
|
||||
|
||||
def test_highlight_sample_double_click(self):
|
||||
# Test double click on highlight_sample.
|
||||
eq = self.assertEqual
|
||||
d = self.page
|
||||
|
||||
hs = d.highlight_sample
|
||||
hs.focus_force()
|
||||
hs.see(1.0)
|
||||
hs.update_idletasks()
|
||||
|
||||
# Test binding from configdialog.
|
||||
hs.event_generate('<Enter>', x=0, y=0)
|
||||
hs.event_generate('<Motion>', x=0, y=0)
|
||||
# Double click is a sequence of two clicks in a row.
|
||||
for _ in range(2):
|
||||
hs.event_generate('<ButtonPress-1>', x=0, y=0)
|
||||
hs.event_generate('<ButtonRelease-1>', x=0, y=0)
|
||||
|
||||
eq(hs.tag_ranges('sel'), ())
|
||||
|
||||
def test_highlight_sample_b1_motion(self):
|
||||
# Test button motion on highlight_sample.
|
||||
eq = self.assertEqual
|
||||
d = self.page
|
||||
|
||||
hs = d.highlight_sample
|
||||
hs.focus_force()
|
||||
hs.see(1.0)
|
||||
hs.update_idletasks()
|
||||
|
||||
x, y, dx, dy, offset = hs.dlineinfo('1.0')
|
||||
|
||||
# Test binding from configdialog.
|
||||
hs.event_generate('<Leave>')
|
||||
hs.event_generate('<Enter>')
|
||||
hs.event_generate('<Motion>', x=x, y=y)
|
||||
hs.event_generate('<ButtonPress-1>', x=x, y=y)
|
||||
hs.event_generate('<B1-Motion>', x=dx, y=dy)
|
||||
hs.event_generate('<ButtonRelease-1>', x=dx, y=dy)
|
||||
|
||||
eq(hs.tag_ranges('sel'), ())
|
||||
|
||||
def test_set_theme_type(self):
|
||||
eq = self.assertEqual
|
||||
d = self.page
|
||||
|
@ -666,8 +744,13 @@ class HighPageTest(unittest.TestCase):
|
|||
idleConf.userCfg['highlight'].SetOption(theme_name, 'name', 'value')
|
||||
highpage[theme_name] = {'option': 'True'}
|
||||
|
||||
theme_name2 = 'other theme'
|
||||
idleConf.userCfg['highlight'].SetOption(theme_name2, 'name', 'value')
|
||||
highpage[theme_name2] = {'option': 'False'}
|
||||
|
||||
# Force custom theme.
|
||||
d.theme_source.set(False)
|
||||
d.custom_theme_on.state(('!disabled',))
|
||||
d.custom_theme_on.invoke()
|
||||
d.custom_name.set(theme_name)
|
||||
|
||||
# Cancel deletion.
|
||||
|
@ -675,7 +758,7 @@ class HighPageTest(unittest.TestCase):
|
|||
d.button_delete_custom.invoke()
|
||||
eq(yesno.called, 1)
|
||||
eq(highpage[theme_name], {'option': 'True'})
|
||||
eq(idleConf.GetSectionList('user', 'highlight'), ['spam theme'])
|
||||
eq(idleConf.GetSectionList('user', 'highlight'), [theme_name, theme_name2])
|
||||
eq(dialog.deactivate_current_config.called, 0)
|
||||
eq(dialog.activate_config_changes.called, 0)
|
||||
eq(d.set_theme_type.called, 0)
|
||||
|
@ -685,13 +768,26 @@ class HighPageTest(unittest.TestCase):
|
|||
d.button_delete_custom.invoke()
|
||||
eq(yesno.called, 2)
|
||||
self.assertNotIn(theme_name, highpage)
|
||||
eq(idleConf.GetSectionList('user', 'highlight'), [])
|
||||
eq(d.custom_theme_on.state(), ('disabled',))
|
||||
eq(d.custom_name.get(), '- no custom themes -')
|
||||
eq(idleConf.GetSectionList('user', 'highlight'), [theme_name2])
|
||||
eq(d.custom_theme_on.state(), ())
|
||||
eq(d.custom_name.get(), theme_name2)
|
||||
eq(dialog.deactivate_current_config.called, 1)
|
||||
eq(dialog.activate_config_changes.called, 1)
|
||||
eq(d.set_theme_type.called, 1)
|
||||
|
||||
# Confirm deletion of second theme - empties list.
|
||||
d.custom_name.set(theme_name2)
|
||||
yesno.result = True
|
||||
d.button_delete_custom.invoke()
|
||||
eq(yesno.called, 3)
|
||||
self.assertNotIn(theme_name, highpage)
|
||||
eq(idleConf.GetSectionList('user', 'highlight'), [])
|
||||
eq(d.custom_theme_on.state(), ('disabled',))
|
||||
eq(d.custom_name.get(), '- no custom themes -')
|
||||
eq(dialog.deactivate_current_config.called, 2)
|
||||
eq(dialog.activate_config_changes.called, 2)
|
||||
eq(d.set_theme_type.called, 2)
|
||||
|
||||
del dialog.activate_config_changes, dialog.deactivate_current_config
|
||||
del d.askyesno
|
||||
|
||||
|
@ -1059,8 +1155,13 @@ class KeysPageTest(unittest.TestCase):
|
|||
idleConf.userCfg['keys'].SetOption(keyset_name, 'name', 'value')
|
||||
keyspage[keyset_name] = {'option': 'True'}
|
||||
|
||||
keyset_name2 = 'other key set'
|
||||
idleConf.userCfg['keys'].SetOption(keyset_name2, 'name', 'value')
|
||||
keyspage[keyset_name2] = {'option': 'False'}
|
||||
|
||||
# Force custom keyset.
|
||||
d.keyset_source.set(False)
|
||||
d.custom_keyset_on.state(('!disabled',))
|
||||
d.custom_keyset_on.invoke()
|
||||
d.custom_name.set(keyset_name)
|
||||
|
||||
# Cancel deletion.
|
||||
|
@ -1068,7 +1169,7 @@ class KeysPageTest(unittest.TestCase):
|
|||
d.button_delete_custom_keys.invoke()
|
||||
eq(yesno.called, 1)
|
||||
eq(keyspage[keyset_name], {'option': 'True'})
|
||||
eq(idleConf.GetSectionList('user', 'keys'), ['spam key set'])
|
||||
eq(idleConf.GetSectionList('user', 'keys'), [keyset_name, keyset_name2])
|
||||
eq(dialog.deactivate_current_config.called, 0)
|
||||
eq(dialog.activate_config_changes.called, 0)
|
||||
eq(d.set_keys_type.called, 0)
|
||||
|
@ -1078,13 +1179,26 @@ class KeysPageTest(unittest.TestCase):
|
|||
d.button_delete_custom_keys.invoke()
|
||||
eq(yesno.called, 2)
|
||||
self.assertNotIn(keyset_name, keyspage)
|
||||
eq(idleConf.GetSectionList('user', 'keys'), [])
|
||||
eq(d.custom_keyset_on.state(), ('disabled',))
|
||||
eq(d.custom_name.get(), '- no custom keys -')
|
||||
eq(idleConf.GetSectionList('user', 'keys'), [keyset_name2])
|
||||
eq(d.custom_keyset_on.state(), ())
|
||||
eq(d.custom_name.get(), keyset_name2)
|
||||
eq(dialog.deactivate_current_config.called, 1)
|
||||
eq(dialog.activate_config_changes.called, 1)
|
||||
eq(d.set_keys_type.called, 1)
|
||||
|
||||
# Confirm deletion of second keyset - empties list.
|
||||
d.custom_name.set(keyset_name2)
|
||||
yesno.result = True
|
||||
d.button_delete_custom_keys.invoke()
|
||||
eq(yesno.called, 3)
|
||||
self.assertNotIn(keyset_name, keyspage)
|
||||
eq(idleConf.GetSectionList('user', 'keys'), [])
|
||||
eq(d.custom_keyset_on.state(), ('disabled',))
|
||||
eq(d.custom_name.get(), '- no custom keys -')
|
||||
eq(dialog.deactivate_current_config.called, 2)
|
||||
eq(dialog.activate_config_changes.called, 2)
|
||||
eq(d.set_keys_type.called, 2)
|
||||
|
||||
del dialog.activate_config_changes, dialog.deactivate_current_config
|
||||
del d.askyesno
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add remaining configdialog tests for buttons and highlights and keys tabs.
|
Loading…
Reference in New Issue