2016-11-07 18:15:01 -04:00
|
|
|
"""Test idlelib.configdialog.
|
2014-07-15 00:07:32 -03:00
|
|
|
|
2016-11-07 18:15:01 -04:00
|
|
|
Half the class creates dialog, half works with user customizations.
|
2017-08-14 22:21:43 -03:00
|
|
|
Coverage: 81%.
|
2016-11-07 18:15:01 -04:00
|
|
|
"""
|
2017-07-26 21:54:40 -03:00
|
|
|
from idlelib import configdialog
|
2014-07-15 00:07:32 -03:00
|
|
|
from test.support import requires
|
2016-06-04 16:54:44 -03:00
|
|
|
requires('gui')
|
|
|
|
import unittest
|
2017-07-26 20:09:58 -03:00
|
|
|
from unittest import mock
|
2017-07-13 21:35:48 -03:00
|
|
|
from idlelib.idle_test.mock_idle import Func
|
2017-08-07 15:22:44 -03:00
|
|
|
from tkinter import Tk, Frame, StringVar, IntVar, BooleanVar, DISABLED, NORMAL
|
2017-07-26 21:54:40 -03:00
|
|
|
from idlelib import config
|
2017-07-28 18:00:02 -03:00
|
|
|
from idlelib.configdialog import idleConf, changes, tracers
|
2014-07-15 00:07:32 -03:00
|
|
|
|
2016-11-07 18:15:01 -04:00
|
|
|
# Tests should not depend on fortuitous user configurations.
|
|
|
|
# They must not affect actual user .cfg files.
|
|
|
|
# Use solution from test_config: empty parsers with no filename.
|
|
|
|
usercfg = idleConf.userCfg
|
|
|
|
testcfg = {
|
|
|
|
'main': config.IdleUserConfParser(''),
|
|
|
|
'highlight': config.IdleUserConfParser(''),
|
|
|
|
'keys': config.IdleUserConfParser(''),
|
|
|
|
'extensions': config.IdleUserConfParser(''),
|
|
|
|
}
|
2014-07-15 00:07:32 -03:00
|
|
|
|
2017-06-26 18:46:26 -03:00
|
|
|
root = None
|
2017-07-13 21:35:48 -03:00
|
|
|
dialog = None
|
2017-07-07 17:00:57 -03:00
|
|
|
mainpage = changes['main']
|
|
|
|
highpage = changes['highlight']
|
|
|
|
keyspage = changes['keys']
|
2017-08-14 22:21:43 -03:00
|
|
|
extpage = changes['extensions']
|
2017-06-26 18:46:26 -03:00
|
|
|
|
2016-11-07 18:15:01 -04:00
|
|
|
def setUpModule():
|
2017-07-13 21:35:48 -03:00
|
|
|
global root, dialog
|
2016-11-07 18:15:01 -04:00
|
|
|
idleConf.userCfg = testcfg
|
|
|
|
root = Tk()
|
2017-07-13 21:35:48 -03:00
|
|
|
# root.withdraw() # Comment out, see issue 30870
|
2017-07-28 18:00:02 -03:00
|
|
|
dialog = configdialog.ConfigDialog(root, 'Test', _utest=True)
|
2016-11-07 18:15:01 -04:00
|
|
|
|
|
|
|
def tearDownModule():
|
2017-07-13 21:35:48 -03:00
|
|
|
global root, dialog
|
2017-07-06 23:19:13 -03:00
|
|
|
idleConf.userCfg = usercfg
|
2017-07-28 18:00:02 -03:00
|
|
|
tracers.detach()
|
2017-08-07 15:22:44 -03:00
|
|
|
tracers.clear()
|
|
|
|
changes.clear()
|
2017-07-13 21:35:48 -03:00
|
|
|
del dialog
|
2016-11-07 18:15:01 -04:00
|
|
|
root.update_idletasks()
|
|
|
|
root.destroy()
|
|
|
|
del root
|
|
|
|
|
|
|
|
|
2017-07-30 14:34:25 -03:00
|
|
|
class FontPageTest(unittest.TestCase):
|
2017-07-24 01:18:25 -03:00
|
|
|
"""Test that font widgets enable users to make font changes.
|
2017-07-13 21:35:48 -03:00
|
|
|
|
2017-07-24 01:18:25 -03:00
|
|
|
Test that widget actions set vars, that var changes add three
|
|
|
|
options to changes and call set_samples, and that set_samples
|
|
|
|
changes the font of both sample boxes.
|
|
|
|
"""
|
2017-07-13 21:35:48 -03:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
2017-07-30 14:34:25 -03:00
|
|
|
page = cls.page = dialog.fontpage
|
|
|
|
dialog.note.select(page)
|
|
|
|
page.set_samples = Func() # Mask instance method.
|
2017-07-13 21:35:48 -03:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
2017-07-30 14:34:25 -03:00
|
|
|
del cls.page.set_samples # Unmask instance method.
|
2017-07-13 21:35:48 -03:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
changes.clear()
|
|
|
|
|
2017-07-24 01:18:25 -03:00
|
|
|
def test_load_font_cfg(self):
|
|
|
|
# Leave widget load test to human visual check.
|
|
|
|
# TODO Improve checks when add IdleConf.get_font_values.
|
2017-07-30 14:34:25 -03:00
|
|
|
tracers.detach()
|
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
d.font_name.set('Fake')
|
|
|
|
d.font_size.set('1')
|
|
|
|
d.font_bold.set(True)
|
|
|
|
d.set_samples.called = 0
|
|
|
|
d.load_font_cfg()
|
|
|
|
self.assertNotEqual(d.font_name.get(), 'Fake')
|
|
|
|
self.assertNotEqual(d.font_size.get(), '1')
|
|
|
|
self.assertFalse(d.font_bold.get())
|
2017-07-30 14:34:25 -03:00
|
|
|
self.assertEqual(d.set_samples.called, 1)
|
|
|
|
tracers.attach()
|
2017-07-24 01:18:25 -03:00
|
|
|
|
|
|
|
def test_fontlist_key(self):
|
2017-07-13 21:35:48 -03:00
|
|
|
# Up and Down keys should select a new font.
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
|
|
|
if d.fontlist.size() < 2:
|
|
|
|
self.skipTest('need at least 2 fonts')
|
|
|
|
fontlist = d.fontlist
|
2017-07-13 21:35:48 -03:00
|
|
|
fontlist.activate(0)
|
2017-07-30 14:34:25 -03:00
|
|
|
font = d.fontlist.get('active')
|
2017-07-13 21:35:48 -03:00
|
|
|
|
|
|
|
# Test Down key.
|
|
|
|
fontlist.focus_force()
|
|
|
|
fontlist.update()
|
|
|
|
fontlist.event_generate('<Key-Down>')
|
|
|
|
fontlist.event_generate('<KeyRelease-Down>')
|
|
|
|
|
|
|
|
down_font = fontlist.get('active')
|
|
|
|
self.assertNotEqual(down_font, font)
|
2017-07-30 14:34:25 -03:00
|
|
|
self.assertIn(d.font_name.get(), down_font.lower())
|
2017-07-13 21:35:48 -03:00
|
|
|
|
|
|
|
# Test Up key.
|
|
|
|
fontlist.focus_force()
|
|
|
|
fontlist.update()
|
|
|
|
fontlist.event_generate('<Key-Up>')
|
|
|
|
fontlist.event_generate('<KeyRelease-Up>')
|
|
|
|
|
|
|
|
up_font = fontlist.get('active')
|
|
|
|
self.assertEqual(up_font, font)
|
2017-07-30 14:34:25 -03:00
|
|
|
self.assertIn(d.font_name.get(), up_font.lower())
|
2017-07-13 21:35:48 -03:00
|
|
|
|
2017-07-24 01:18:25 -03:00
|
|
|
def test_fontlist_mouse(self):
|
2017-07-13 21:35:48 -03:00
|
|
|
# Click on item should select that item.
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
|
|
|
if d.fontlist.size() < 2:
|
2017-08-14 22:21:43 -03:00
|
|
|
self.skipTest('need at least 2 fonts')
|
2017-07-30 14:34:25 -03:00
|
|
|
fontlist = d.fontlist
|
2017-07-13 21:35:48 -03:00
|
|
|
fontlist.activate(0)
|
|
|
|
|
|
|
|
# Select next item in listbox
|
|
|
|
fontlist.focus_force()
|
|
|
|
fontlist.see(1)
|
|
|
|
fontlist.update()
|
|
|
|
x, y, dx, dy = fontlist.bbox(1)
|
|
|
|
x += dx // 2
|
|
|
|
y += dy // 2
|
|
|
|
fontlist.event_generate('<Button-1>', x=x, y=y)
|
|
|
|
fontlist.event_generate('<ButtonRelease-1>', x=x, y=y)
|
|
|
|
|
|
|
|
font1 = fontlist.get(1)
|
|
|
|
select_font = fontlist.get('anchor')
|
|
|
|
self.assertEqual(select_font, font1)
|
2017-07-30 14:34:25 -03:00
|
|
|
self.assertIn(d.font_name.get(), font1.lower())
|
2017-07-24 01:18:25 -03:00
|
|
|
|
|
|
|
def test_sizelist(self):
|
|
|
|
# Click on number shouod select that number
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
d.sizelist.variable.set(40)
|
|
|
|
self.assertEqual(d.font_size.get(), '40')
|
|
|
|
|
|
|
|
def test_bold_toggle(self):
|
|
|
|
# Click on checkbutton should invert it.
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
d.font_bold.set(False)
|
|
|
|
d.bold_toggle.invoke()
|
|
|
|
self.assertTrue(d.font_bold.get())
|
|
|
|
d.bold_toggle.invoke()
|
|
|
|
self.assertFalse(d.font_bold.get())
|
|
|
|
|
|
|
|
def test_font_set(self):
|
|
|
|
# Test that setting a font Variable results in 3 provisional
|
|
|
|
# change entries and a call to set_samples. Use values sure to
|
|
|
|
# not be defaults.
|
|
|
|
|
|
|
|
default_font = idleConf.GetFont(root, 'main', 'EditorWindow')
|
|
|
|
default_size = str(default_font[1])
|
|
|
|
default_bold = default_font[2] == 'bold'
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
d.font_size.set(default_size)
|
|
|
|
d.font_bold.set(default_bold)
|
|
|
|
d.set_samples.called = 0
|
|
|
|
|
|
|
|
d.font_name.set('Test Font')
|
|
|
|
expected = {'EditorWindow': {'font': 'Test Font',
|
|
|
|
'font-size': default_size,
|
|
|
|
'font-bold': str(default_bold)}}
|
|
|
|
self.assertEqual(mainpage, expected)
|
|
|
|
self.assertEqual(d.set_samples.called, 1)
|
|
|
|
changes.clear()
|
|
|
|
|
|
|
|
d.font_size.set('20')
|
|
|
|
expected = {'EditorWindow': {'font': 'Test Font',
|
|
|
|
'font-size': '20',
|
|
|
|
'font-bold': str(default_bold)}}
|
|
|
|
self.assertEqual(mainpage, expected)
|
|
|
|
self.assertEqual(d.set_samples.called, 2)
|
|
|
|
changes.clear()
|
|
|
|
|
|
|
|
d.font_bold.set(not default_bold)
|
|
|
|
expected = {'EditorWindow': {'font': 'Test Font',
|
|
|
|
'font-size': '20',
|
|
|
|
'font-bold': str(not default_bold)}}
|
|
|
|
self.assertEqual(mainpage, expected)
|
|
|
|
self.assertEqual(d.set_samples.called, 3)
|
|
|
|
|
|
|
|
def test_set_samples(self):
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
del d.set_samples # Unmask method for test
|
|
|
|
d.font_sample, d.highlight_sample = {}, {}
|
|
|
|
d.font_name.set('test')
|
|
|
|
d.font_size.set('5')
|
|
|
|
d.font_bold.set(1)
|
|
|
|
expected = {'font': ('test', '5', 'bold')}
|
|
|
|
|
|
|
|
# Test set_samples.
|
|
|
|
d.set_samples()
|
|
|
|
self.assertTrue(d.font_sample == d.highlight_sample == expected)
|
|
|
|
|
|
|
|
del d.font_sample, d.highlight_sample
|
|
|
|
d.set_samples = Func() # Re-mask for other tests.
|
|
|
|
|
|
|
|
|
|
|
|
class IndentTest(unittest.TestCase):
|
|
|
|
|
2017-07-30 14:34:25 -03:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
cls.page = dialog.fontpage
|
|
|
|
|
2017-07-24 01:18:25 -03:00
|
|
|
def test_load_tab_cfg(self):
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
d.space_num.set(16)
|
|
|
|
d.load_tab_cfg()
|
|
|
|
self.assertEqual(d.space_num.get(), 4)
|
|
|
|
|
|
|
|
def test_indent_scale(self):
|
2017-07-30 14:34:25 -03:00
|
|
|
d = self.page
|
2017-07-24 01:18:25 -03:00
|
|
|
changes.clear()
|
2017-07-30 14:34:25 -03:00
|
|
|
d.indent_scale.set(20)
|
|
|
|
self.assertEqual(d.space_num.get(), 16)
|
2017-07-24 01:18:25 -03:00
|
|
|
self.assertEqual(mainpage, {'Indent': {'num-spaces': '16'}})
|
2017-07-13 21:35:48 -03:00
|
|
|
|
|
|
|
|
2016-11-07 18:15:01 -04:00
|
|
|
class HighlightTest(unittest.TestCase):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
changes.clear()
|
|
|
|
|
|
|
|
|
2017-08-14 22:21:43 -03:00
|
|
|
class KeyTest(unittest.TestCase):
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
d = dialog
|
|
|
|
dialog.note.select(d.keyspage)
|
|
|
|
d.set_keys_type = Func()
|
|
|
|
d.load_keys_list = Func()
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
|
|
|
d = dialog
|
|
|
|
del d.set_keys_type, d.load_keys_list
|
2016-11-07 18:15:01 -04:00
|
|
|
|
|
|
|
def setUp(self):
|
2017-08-14 22:21:43 -03:00
|
|
|
d = dialog
|
|
|
|
# The following is needed for test_load_key_cfg, _delete_custom_keys.
|
|
|
|
# This may indicate a defect in some test or function.
|
|
|
|
for section in idleConf.GetSectionList('user', 'keys'):
|
|
|
|
idleConf.userCfg['keys'].remove_section(section)
|
|
|
|
changes.clear()
|
|
|
|
d.set_keys_type.called = 0
|
|
|
|
d.load_keys_list.called = 0
|
|
|
|
|
|
|
|
def test_load_key_cfg(self):
|
|
|
|
tracers.detach()
|
|
|
|
d = dialog
|
|
|
|
eq = self.assertEqual
|
|
|
|
|
|
|
|
# Use builtin keyset with no user keysets created.
|
|
|
|
idleConf.CurrentKeys = mock.Mock(return_value='IDLE Classic OSX')
|
|
|
|
d.load_key_cfg()
|
|
|
|
self.assertTrue(d.keyset_source.get())
|
|
|
|
# builtinlist sets variable builtin_name to the CurrentKeys default.
|
|
|
|
eq(d.builtin_name.get(), 'IDLE Classic OSX')
|
|
|
|
eq(d.custom_name.get(), '- no custom keys -')
|
|
|
|
eq(d.custom_keyset_on['state'], DISABLED)
|
|
|
|
eq(d.set_keys_type.called, 1)
|
|
|
|
eq(d.load_keys_list.called, 1)
|
|
|
|
eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
|
|
|
|
|
|
|
|
# Builtin keyset with non-empty user keyset list.
|
|
|
|
idleConf.SetOption('keys', 'test1', 'option', 'value')
|
|
|
|
idleConf.SetOption('keys', 'test2', 'option2', 'value2')
|
|
|
|
d.load_key_cfg()
|
|
|
|
eq(d.builtin_name.get(), 'IDLE Classic OSX')
|
|
|
|
eq(d.custom_name.get(), 'test1')
|
|
|
|
eq(d.set_keys_type.called, 2)
|
|
|
|
eq(d.load_keys_list.called, 2)
|
|
|
|
eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
|
|
|
|
|
|
|
|
# Use custom keyset.
|
|
|
|
idleConf.CurrentKeys = mock.Mock(return_value='test2')
|
|
|
|
idleConf.default_keys = mock.Mock(return_value='IDLE Modern Unix')
|
|
|
|
idleConf.SetOption('main', 'Keys', 'default', '0')
|
|
|
|
d.load_key_cfg()
|
|
|
|
self.assertFalse(d.keyset_source.get())
|
|
|
|
eq(d.builtin_name.get(), 'IDLE Modern Unix')
|
|
|
|
eq(d.custom_name.get(), 'test2')
|
|
|
|
eq(d.set_keys_type.called, 3)
|
|
|
|
eq(d.load_keys_list.called, 3)
|
|
|
|
eq(d.load_keys_list.args, ('test2', ))
|
|
|
|
|
|
|
|
del idleConf.CurrentKeys, idleConf.default_keys
|
|
|
|
tracers.attach()
|
|
|
|
|
|
|
|
def test_keyset_source(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
# Test these separately.
|
|
|
|
d.var_changed_builtin_name = Func()
|
|
|
|
d.var_changed_custom_name = Func()
|
|
|
|
# Builtin selected.
|
|
|
|
d.builtin_keyset_on.invoke()
|
|
|
|
eq(mainpage, {'Keys': {'default': 'True'}})
|
|
|
|
eq(d.var_changed_builtin_name.called, 1)
|
|
|
|
eq(d.var_changed_custom_name.called, 0)
|
2016-11-07 18:15:01 -04:00
|
|
|
changes.clear()
|
|
|
|
|
2017-08-14 22:21:43 -03:00
|
|
|
# Custom selected.
|
|
|
|
d.custom_keyset_on['state'] = NORMAL
|
|
|
|
d.custom_keyset_on.invoke()
|
|
|
|
self.assertEqual(mainpage, {'Keys': {'default': 'False'}})
|
|
|
|
eq(d.var_changed_builtin_name.called, 1)
|
|
|
|
eq(d.var_changed_custom_name.called, 1)
|
|
|
|
del d.var_changed_builtin_name, d.var_changed_custom_name
|
|
|
|
|
|
|
|
def test_builtin_name(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
idleConf.userCfg['main'].remove_section('Keys')
|
|
|
|
item_list = ['IDLE Classic Windows', 'IDLE Classic OSX',
|
|
|
|
'IDLE Modern UNIX']
|
|
|
|
|
|
|
|
# Not in old_keys, defaults name to first item.
|
|
|
|
d.builtinlist.SetMenu(item_list, 'IDLE Modern UNIX')
|
|
|
|
eq(mainpage, {'Keys': {'name': 'IDLE Classic Windows',
|
|
|
|
'name2': 'IDLE Modern UNIX'}})
|
|
|
|
eq(d.keys_message['text'], 'New key set, see Help')
|
|
|
|
eq(d.load_keys_list.called, 1)
|
|
|
|
eq(d.load_keys_list.args, ('IDLE Modern UNIX', ))
|
|
|
|
|
|
|
|
# Not in old keys - uses name2.
|
|
|
|
changes.clear()
|
|
|
|
idleConf.SetOption('main', 'Keys', 'name', 'IDLE Classic Unix')
|
|
|
|
d.builtinlist.SetMenu(item_list, 'IDLE Modern UNIX')
|
|
|
|
eq(mainpage, {'Keys': {'name2': 'IDLE Modern UNIX'}})
|
|
|
|
eq(d.keys_message['text'], 'New key set, see Help')
|
|
|
|
eq(d.load_keys_list.called, 2)
|
|
|
|
eq(d.load_keys_list.args, ('IDLE Modern UNIX', ))
|
|
|
|
|
|
|
|
# Builtin name in old_keys.
|
|
|
|
changes.clear()
|
|
|
|
d.builtinlist.SetMenu(item_list, 'IDLE Classic OSX')
|
|
|
|
eq(mainpage, {'Keys': {'name': 'IDLE Classic OSX', 'name2': ''}})
|
|
|
|
eq(d.keys_message['text'], '')
|
|
|
|
eq(d.load_keys_list.called, 3)
|
|
|
|
eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
|
|
|
|
|
|
|
|
def test_custom_name(self):
|
|
|
|
d = dialog
|
|
|
|
|
|
|
|
# If no selections, doesn't get added.
|
|
|
|
d.customlist.SetMenu([], '- no custom keys -')
|
|
|
|
self.assertNotIn('Keys', mainpage)
|
|
|
|
self.assertEqual(d.load_keys_list.called, 0)
|
|
|
|
|
|
|
|
# Custom name selected.
|
|
|
|
changes.clear()
|
|
|
|
d.customlist.SetMenu(['a', 'b', 'c'], 'c')
|
|
|
|
self.assertEqual(mainpage, {'Keys': {'name': 'c'}})
|
|
|
|
self.assertEqual(d.load_keys_list.called, 1)
|
|
|
|
|
|
|
|
def test_keybinding(self):
|
|
|
|
d = dialog
|
|
|
|
d.custom_name.set('my custom keys')
|
|
|
|
d.bindingslist.delete(0, 'end')
|
|
|
|
d.bindingslist.insert(0, 'copy')
|
|
|
|
d.bindingslist.insert(1, 'expand-word')
|
|
|
|
d.bindingslist.selection_set(0)
|
|
|
|
d.bindingslist.selection_anchor(0)
|
|
|
|
# Core binding - adds to keys.
|
|
|
|
d.keybinding.set('<Key-F11>')
|
|
|
|
self.assertEqual(keyspage,
|
|
|
|
{'my custom keys': {'copy': '<Key-F11>'}})
|
|
|
|
# Not a core binding - adds to extensions.
|
|
|
|
d.bindingslist.selection_set(1)
|
|
|
|
d.bindingslist.selection_anchor(1)
|
|
|
|
d.keybinding.set('<Key-F11>')
|
|
|
|
self.assertEqual(extpage,
|
|
|
|
{'AutoExpand_cfgBindings': {'expand-word': '<Key-F11>'}})
|
|
|
|
|
|
|
|
def test_set_keys_type(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
del d.set_keys_type
|
|
|
|
|
|
|
|
# Builtin keyset selected.
|
|
|
|
d.keyset_source.set(True)
|
|
|
|
d.set_keys_type()
|
|
|
|
eq(d.builtinlist['state'], NORMAL)
|
|
|
|
eq(d.customlist['state'], DISABLED)
|
|
|
|
eq(d.button_delete_custom_keys['state'], DISABLED)
|
|
|
|
|
|
|
|
# Custom keyset selected.
|
|
|
|
d.keyset_source.set(False)
|
|
|
|
d.set_keys_type()
|
|
|
|
eq(d.builtinlist['state'], DISABLED)
|
|
|
|
eq(d.custom_keyset_on['state'], NORMAL)
|
|
|
|
eq(d.customlist['state'], NORMAL)
|
|
|
|
eq(d.button_delete_custom_keys['state'], NORMAL)
|
|
|
|
d.set_keys_type = Func()
|
|
|
|
|
|
|
|
def test_get_new_keys(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
orig_getkeysdialog = configdialog.GetKeysDialog
|
|
|
|
gkd = configdialog.GetKeysDialog = Func(return_self=True)
|
|
|
|
gnkn = d.get_new_keys_name = Func()
|
|
|
|
|
|
|
|
d.button_new_keys['state'] = NORMAL
|
|
|
|
d.bindingslist.delete(0, 'end')
|
|
|
|
d.bindingslist.insert(0, 'copy - <Control-Shift-Key-C>')
|
|
|
|
d.bindingslist.selection_set(0)
|
|
|
|
d.bindingslist.selection_anchor(0)
|
|
|
|
d.keybinding.set('Key-a')
|
|
|
|
d.keyset_source.set(True) # Default keyset.
|
|
|
|
|
|
|
|
# Default keyset; no change to binding.
|
|
|
|
gkd.result = ''
|
|
|
|
d.button_new_keys.invoke()
|
|
|
|
eq(d.bindingslist.get('anchor'), 'copy - <Control-Shift-Key-C>')
|
|
|
|
# Keybinding isn't changed when there isn't a change entered.
|
|
|
|
eq(d.keybinding.get(), 'Key-a')
|
|
|
|
|
|
|
|
# Default keyset; binding changed.
|
|
|
|
gkd.result = '<Key-F11>'
|
|
|
|
# No keyset name selected therefore binding not saved.
|
|
|
|
gnkn.result = ''
|
|
|
|
d.button_new_keys.invoke()
|
|
|
|
eq(gnkn.called, 1)
|
|
|
|
eq(d.bindingslist.get('anchor'), 'copy - <Control-Shift-Key-C>')
|
|
|
|
# Keyset name selected.
|
|
|
|
gnkn.result = 'My New Key Set'
|
|
|
|
d.button_new_keys.invoke()
|
|
|
|
eq(d.custom_name.get(), gnkn.result)
|
|
|
|
eq(d.bindingslist.get('anchor'), 'copy - <Key-F11>')
|
|
|
|
eq(d.keybinding.get(), '<Key-F11>')
|
|
|
|
|
|
|
|
# User keyset; binding changed.
|
|
|
|
d.keyset_source.set(False) # Custom keyset.
|
|
|
|
gnkn.called = 0
|
|
|
|
gkd.result = '<Key-p>'
|
|
|
|
d.button_new_keys.invoke()
|
|
|
|
eq(gnkn.called, 0)
|
|
|
|
eq(d.bindingslist.get('anchor'), 'copy - <Key-p>')
|
|
|
|
eq(d.keybinding.get(), '<Key-p>')
|
|
|
|
|
|
|
|
del d.get_new_keys_name
|
|
|
|
configdialog.GetKeysDialog = orig_getkeysdialog
|
|
|
|
|
|
|
|
def test_get_new_keys_name(self):
|
|
|
|
orig_sectionname = configdialog.SectionName
|
|
|
|
sn = configdialog.SectionName = Func(return_self=True)
|
|
|
|
d = dialog
|
|
|
|
|
|
|
|
sn.result = 'New Keys'
|
|
|
|
self.assertEqual(d.get_new_keys_name(''), 'New Keys')
|
|
|
|
|
|
|
|
configdialog.SectionName = orig_sectionname
|
|
|
|
|
|
|
|
def test_save_as_new_key_set(self):
|
|
|
|
d = dialog
|
|
|
|
gnkn = d.get_new_keys_name = Func()
|
|
|
|
d.keyset_source.set(True)
|
|
|
|
|
|
|
|
# No name entered.
|
|
|
|
gnkn.result = ''
|
|
|
|
d.button_save_custom_keys.invoke()
|
|
|
|
|
|
|
|
# Name entered.
|
|
|
|
gnkn.result = 'my new key set'
|
|
|
|
gnkn.called = 0
|
|
|
|
self.assertNotIn(gnkn.result, idleConf.userCfg['keys'])
|
|
|
|
d.button_save_custom_keys.invoke()
|
|
|
|
self.assertIn(gnkn.result, idleConf.userCfg['keys'])
|
|
|
|
|
|
|
|
del d.get_new_keys_name
|
|
|
|
|
|
|
|
def test_on_bindingslist_select(self):
|
|
|
|
d = dialog
|
|
|
|
b = d.bindingslist
|
|
|
|
b.delete(0, 'end')
|
|
|
|
b.insert(0, 'copy')
|
|
|
|
b.insert(1, 'find')
|
|
|
|
b.activate(0)
|
|
|
|
|
|
|
|
b.focus_force()
|
|
|
|
b.see(1)
|
|
|
|
b.update()
|
|
|
|
x, y, dx, dy = b.bbox(1)
|
|
|
|
x += dx // 2
|
|
|
|
y += dy // 2
|
|
|
|
b.event_generate('<Enter>', x=0, y=0)
|
|
|
|
b.event_generate('<Motion>', x=x, y=y)
|
|
|
|
b.event_generate('<Button-1>', x=x, y=y)
|
|
|
|
b.event_generate('<ButtonRelease-1>', x=x, y=y)
|
|
|
|
self.assertEqual(b.get('anchor'), 'find')
|
|
|
|
self.assertEqual(d.button_new_keys['state'], NORMAL)
|
|
|
|
|
|
|
|
def test_create_new_key_set_and_save_new_key_set(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
|
|
|
|
# Use default as previously active keyset.
|
|
|
|
d.keyset_source.set(True)
|
|
|
|
d.builtin_name.set('IDLE Classic Windows')
|
|
|
|
first_new = 'my new custom key set'
|
|
|
|
second_new = 'my second custom keyset'
|
|
|
|
|
|
|
|
# No changes, so keysets are an exact copy.
|
|
|
|
self.assertNotIn(first_new, idleConf.userCfg)
|
|
|
|
d.create_new_key_set(first_new)
|
|
|
|
eq(idleConf.GetSectionList('user', 'keys'), [first_new])
|
|
|
|
eq(idleConf.GetKeySet('IDLE Classic Windows'),
|
|
|
|
idleConf.GetKeySet(first_new))
|
|
|
|
eq(d.custom_name.get(), first_new)
|
|
|
|
self.assertFalse(d.keyset_source.get()) # Use custom set.
|
|
|
|
eq(d.set_keys_type.called, 1)
|
|
|
|
|
|
|
|
# Test that changed keybindings are in new keyset.
|
|
|
|
changes.add_option('keys', first_new, 'copy', '<Key-F11>')
|
|
|
|
self.assertNotIn(second_new, idleConf.userCfg)
|
|
|
|
d.create_new_key_set(second_new)
|
|
|
|
eq(idleConf.GetSectionList('user', 'keys'), [first_new, second_new])
|
|
|
|
self.assertNotEqual(idleConf.GetKeySet(first_new),
|
|
|
|
idleConf.GetKeySet(second_new))
|
|
|
|
# Check that difference in keysets was in option `copy` from `changes`.
|
|
|
|
idleConf.SetOption('keys', first_new, 'copy', '<Key-F11>')
|
|
|
|
eq(idleConf.GetKeySet(first_new), idleConf.GetKeySet(second_new))
|
|
|
|
|
|
|
|
def test_load_keys_list(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
gks = idleConf.GetKeySet = Func()
|
|
|
|
del d.load_keys_list
|
|
|
|
b = d.bindingslist
|
|
|
|
|
|
|
|
b.delete(0, 'end')
|
|
|
|
b.insert(0, '<<find>>')
|
|
|
|
b.insert(1, '<<help>>')
|
|
|
|
gks.result = {'<<copy>>': ['<Control-Key-c>', '<Control-Key-C>'],
|
|
|
|
'<<force-open-completions>>': ['<Control-Key-space>'],
|
|
|
|
'<<spam>>': ['<Key-F11>']}
|
|
|
|
changes.add_option('keys', 'my keys', 'spam', '<Shift-Key-a>')
|
|
|
|
expected = ('copy - <Control-Key-c> <Control-Key-C>',
|
|
|
|
'force-open-completions - <Control-Key-space>',
|
|
|
|
'spam - <Shift-Key-a>')
|
|
|
|
|
|
|
|
# No current selection.
|
|
|
|
d.load_keys_list('my keys')
|
|
|
|
eq(b.get(0, 'end'), expected)
|
|
|
|
eq(b.get('anchor'), '')
|
|
|
|
eq(b.curselection(), ())
|
|
|
|
|
|
|
|
# Check selection.
|
|
|
|
b.selection_set(1)
|
|
|
|
b.selection_anchor(1)
|
|
|
|
d.load_keys_list('my keys')
|
|
|
|
eq(b.get(0, 'end'), expected)
|
|
|
|
eq(b.get('anchor'), 'force-open-completions - <Control-Key-space>')
|
|
|
|
eq(b.curselection(), (1, ))
|
|
|
|
|
|
|
|
# Change selection.
|
|
|
|
b.selection_set(2)
|
|
|
|
b.selection_anchor(2)
|
|
|
|
d.load_keys_list('my keys')
|
|
|
|
eq(b.get(0, 'end'), expected)
|
|
|
|
eq(b.get('anchor'), 'spam - <Shift-Key-a>')
|
|
|
|
eq(b.curselection(), (2, ))
|
|
|
|
d.load_keys_list = Func()
|
|
|
|
|
|
|
|
del idleConf.GetKeySet
|
|
|
|
|
|
|
|
def test_delete_custom_keys(self):
|
|
|
|
eq = self.assertEqual
|
|
|
|
d = dialog
|
|
|
|
d.button_delete_custom_keys['state'] = NORMAL
|
|
|
|
yesno = configdialog.tkMessageBox.askyesno = Func()
|
|
|
|
d.deactivate_current_config = Func()
|
|
|
|
d.activate_config_changes = Func()
|
|
|
|
|
|
|
|
keyset_name = 'spam key set'
|
|
|
|
idleConf.userCfg['keys'].SetOption(keyset_name, 'name', 'value')
|
|
|
|
keyspage[keyset_name] = {'option': 'True'}
|
|
|
|
|
|
|
|
# Force custom keyset.
|
|
|
|
d.keyset_source.set(False)
|
|
|
|
d.custom_name.set(keyset_name)
|
|
|
|
|
|
|
|
# Cancel deletion.
|
|
|
|
yesno.result = False
|
|
|
|
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(d.deactivate_current_config.called, 0)
|
|
|
|
eq(d.activate_config_changes.called, 0)
|
|
|
|
eq(d.set_keys_type.called, 0)
|
|
|
|
|
|
|
|
# Confirm deletion.
|
|
|
|
yesno.result = True
|
|
|
|
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(d.deactivate_current_config.called, 1)
|
|
|
|
eq(d.activate_config_changes.called, 1)
|
|
|
|
eq(d.set_keys_type.called, 1)
|
|
|
|
|
|
|
|
del d.activate_config_changes, d.deactivate_current_config
|
|
|
|
del configdialog.tkMessageBox.askyesno
|
|
|
|
|
2016-11-07 18:15:01 -04:00
|
|
|
|
2017-07-30 19:39:17 -03:00
|
|
|
class GenPageTest(unittest.TestCase):
|
2017-07-26 21:54:40 -03:00
|
|
|
"""Test that general tab widgets enable users to make changes.
|
|
|
|
|
|
|
|
Test that widget actions set vars, that var changes add
|
|
|
|
options to changes and that helplist works correctly.
|
|
|
|
"""
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
2017-07-30 19:39:17 -03:00
|
|
|
page = cls.page = dialog.genpage
|
|
|
|
dialog.note.select(page)
|
|
|
|
page.set = page.set_add_delete_state = Func()
|
|
|
|
page.upc = page.update_help_changes = Func()
|
2017-07-26 21:54:40 -03:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
2017-07-30 19:39:17 -03:00
|
|
|
page = cls.page
|
|
|
|
del page.set, page.set_add_delete_state
|
|
|
|
del page.upc, page.update_help_changes
|
|
|
|
page.helplist.delete(0, 'end')
|
|
|
|
page.user_helplist.clear()
|
2016-11-07 18:15:01 -04:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
changes.clear()
|
|
|
|
|
2017-07-26 21:54:40 -03:00
|
|
|
def test_load_general_cfg(self):
|
|
|
|
# Set to wrong values, load, check right values.
|
|
|
|
eq = self.assertEqual
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
d.startup_edit.set(1)
|
|
|
|
d.autosave.set(1)
|
|
|
|
d.win_width.set(1)
|
|
|
|
d.win_height.set(1)
|
|
|
|
d.helplist.insert('end', 'bad')
|
|
|
|
d.user_helplist = ['bad', 'worse']
|
|
|
|
idleConf.SetOption('main', 'HelpFiles', '1', 'name;file')
|
|
|
|
d.load_general_cfg()
|
|
|
|
eq(d.startup_edit.get(), 0)
|
|
|
|
eq(d.autosave.get(), 0)
|
|
|
|
eq(d.win_width.get(), '80')
|
|
|
|
eq(d.win_height.get(), '40')
|
|
|
|
eq(d.helplist.get(0, 'end'), ('name',))
|
|
|
|
eq(d.user_helplist, [('name', 'file', '1')])
|
|
|
|
|
2016-11-07 18:15:01 -04:00
|
|
|
def test_startup(self):
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
|
|
|
d.startup_editor_on.invoke()
|
2017-07-07 17:00:57 -03:00
|
|
|
self.assertEqual(mainpage,
|
|
|
|
{'General': {'editor-on-startup': '1'}})
|
2017-07-26 21:54:40 -03:00
|
|
|
changes.clear()
|
2017-07-30 19:39:17 -03:00
|
|
|
d.startup_shell_on.invoke()
|
2017-07-26 21:54:40 -03:00
|
|
|
self.assertEqual(mainpage,
|
|
|
|
{'General': {'editor-on-startup': '0'}})
|
2016-11-07 18:15:01 -04:00
|
|
|
|
|
|
|
def test_autosave(self):
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
|
|
|
d.save_auto_on.invoke()
|
2017-07-07 17:00:57 -03:00
|
|
|
self.assertEqual(mainpage, {'General': {'autosave': '1'}})
|
2017-07-30 19:39:17 -03:00
|
|
|
d.save_ask_on.invoke()
|
2017-07-26 21:54:40 -03:00
|
|
|
self.assertEqual(mainpage, {'General': {'autosave': '0'}})
|
2016-11-07 18:15:01 -04:00
|
|
|
|
|
|
|
def test_editor_size(self):
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
|
|
|
d.win_height_int.insert(0, '1')
|
2017-07-07 17:00:57 -03:00
|
|
|
self.assertEqual(mainpage, {'EditorWindow': {'height': '140'}})
|
2016-11-07 18:15:01 -04:00
|
|
|
changes.clear()
|
2017-07-30 19:39:17 -03:00
|
|
|
d.win_width_int.insert(0, '1')
|
2017-07-07 17:00:57 -03:00
|
|
|
self.assertEqual(mainpage, {'EditorWindow': {'width': '180'}})
|
2016-11-07 18:15:01 -04:00
|
|
|
|
2017-07-26 21:54:40 -03:00
|
|
|
def test_source_selected(self):
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
d.set = d.set_add_delete_state
|
|
|
|
d.upc = d.update_help_changes
|
|
|
|
helplist = d.helplist
|
2017-07-29 01:49:39 -03:00
|
|
|
dex = 'end'
|
|
|
|
helplist.insert(dex, 'source')
|
|
|
|
helplist.activate(dex)
|
2017-07-26 21:54:40 -03:00
|
|
|
|
|
|
|
helplist.focus_force()
|
2017-07-29 01:49:39 -03:00
|
|
|
helplist.see(dex)
|
2017-07-26 21:54:40 -03:00
|
|
|
helplist.update()
|
2017-07-29 01:49:39 -03:00
|
|
|
x, y, dx, dy = helplist.bbox(dex)
|
2017-07-26 21:54:40 -03:00
|
|
|
x += dx // 2
|
|
|
|
y += dy // 2
|
|
|
|
d.set.called = d.upc.called = 0
|
2017-07-29 01:49:39 -03:00
|
|
|
helplist.event_generate('<Enter>', x=0, y=0)
|
|
|
|
helplist.event_generate('<Motion>', x=x, y=y)
|
2017-07-26 21:54:40 -03:00
|
|
|
helplist.event_generate('<Button-1>', x=x, y=y)
|
|
|
|
helplist.event_generate('<ButtonRelease-1>', x=x, y=y)
|
2017-07-30 14:34:25 -03:00
|
|
|
self.assertEqual(helplist.get('anchor'), 'source')
|
|
|
|
self.assertTrue(d.set.called)
|
2017-07-26 21:54:40 -03:00
|
|
|
self.assertFalse(d.upc.called)
|
|
|
|
|
|
|
|
def test_set_add_delete_state(self):
|
|
|
|
# Call with 0 items, 1 unselected item, 1 selected item.
|
|
|
|
eq = self.assertEqual
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
del d.set_add_delete_state # Unmask method.
|
|
|
|
sad = d.set_add_delete_state
|
|
|
|
h = d.helplist
|
|
|
|
|
|
|
|
h.delete(0, 'end')
|
|
|
|
sad()
|
|
|
|
eq(d.button_helplist_edit['state'], DISABLED)
|
|
|
|
eq(d.button_helplist_remove['state'], DISABLED)
|
|
|
|
|
|
|
|
h.insert(0, 'source')
|
|
|
|
sad()
|
|
|
|
eq(d.button_helplist_edit['state'], DISABLED)
|
|
|
|
eq(d.button_helplist_remove['state'], DISABLED)
|
|
|
|
|
|
|
|
h.selection_set(0)
|
|
|
|
sad()
|
|
|
|
eq(d.button_helplist_edit['state'], NORMAL)
|
|
|
|
eq(d.button_helplist_remove['state'], NORMAL)
|
|
|
|
d.set_add_delete_state = Func() # Mask method.
|
|
|
|
|
|
|
|
def test_helplist_item_add(self):
|
|
|
|
# Call without and twice with HelpSource result.
|
|
|
|
# Double call enables check on order.
|
|
|
|
eq = self.assertEqual
|
|
|
|
orig_helpsource = configdialog.HelpSource
|
|
|
|
hs = configdialog.HelpSource = Func(return_self=True)
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
d.helplist.delete(0, 'end')
|
|
|
|
d.user_helplist.clear()
|
|
|
|
d.set.called = d.upc.called = 0
|
|
|
|
|
|
|
|
hs.result = ''
|
|
|
|
d.helplist_item_add()
|
|
|
|
self.assertTrue(list(d.helplist.get(0, 'end')) ==
|
|
|
|
d.user_helplist == [])
|
|
|
|
self.assertFalse(d.upc.called)
|
|
|
|
|
|
|
|
hs.result = ('name1', 'file1')
|
|
|
|
d.helplist_item_add()
|
|
|
|
hs.result = ('name2', 'file2')
|
|
|
|
d.helplist_item_add()
|
|
|
|
eq(d.helplist.get(0, 'end'), ('name1', 'name2'))
|
|
|
|
eq(d.user_helplist, [('name1', 'file1'), ('name2', 'file2')])
|
|
|
|
eq(d.upc.called, 2)
|
|
|
|
self.assertFalse(d.set.called)
|
|
|
|
|
|
|
|
configdialog.HelpSource = orig_helpsource
|
|
|
|
|
|
|
|
def test_helplist_item_edit(self):
|
|
|
|
# Call without and with HelpSource change.
|
|
|
|
eq = self.assertEqual
|
|
|
|
orig_helpsource = configdialog.HelpSource
|
|
|
|
hs = configdialog.HelpSource = Func(return_self=True)
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
d.helplist.delete(0, 'end')
|
|
|
|
d.helplist.insert(0, 'name1')
|
|
|
|
d.helplist.selection_set(0)
|
|
|
|
d.helplist.selection_anchor(0)
|
|
|
|
d.user_helplist.clear()
|
|
|
|
d.user_helplist.append(('name1', 'file1'))
|
|
|
|
d.set.called = d.upc.called = 0
|
|
|
|
|
|
|
|
hs.result = ''
|
|
|
|
d.helplist_item_edit()
|
|
|
|
hs.result = ('name1', 'file1')
|
|
|
|
d.helplist_item_edit()
|
|
|
|
eq(d.helplist.get(0, 'end'), ('name1',))
|
|
|
|
eq(d.user_helplist, [('name1', 'file1')])
|
|
|
|
self.assertFalse(d.upc.called)
|
|
|
|
|
|
|
|
hs.result = ('name2', 'file2')
|
|
|
|
d.helplist_item_edit()
|
|
|
|
eq(d.helplist.get(0, 'end'), ('name2',))
|
|
|
|
eq(d.user_helplist, [('name2', 'file2')])
|
|
|
|
self.assertTrue(d.upc.called == d.set.called == 1)
|
|
|
|
|
|
|
|
configdialog.HelpSource = orig_helpsource
|
|
|
|
|
|
|
|
def test_helplist_item_remove(self):
|
|
|
|
eq = self.assertEqual
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
d.helplist.delete(0, 'end')
|
|
|
|
d.helplist.insert(0, 'name1')
|
|
|
|
d.helplist.selection_set(0)
|
|
|
|
d.helplist.selection_anchor(0)
|
|
|
|
d.user_helplist.clear()
|
|
|
|
d.user_helplist.append(('name1', 'file1'))
|
|
|
|
d.set.called = d.upc.called = 0
|
|
|
|
|
|
|
|
d.helplist_item_remove()
|
|
|
|
eq(d.helplist.get(0, 'end'), ())
|
|
|
|
eq(d.user_helplist, [])
|
|
|
|
self.assertTrue(d.upc.called == d.set.called == 1)
|
|
|
|
|
|
|
|
def test_update_help_changes(self):
|
2017-07-30 19:39:17 -03:00
|
|
|
d = self.page
|
2017-07-26 21:54:40 -03:00
|
|
|
del d.update_help_changes
|
|
|
|
d.user_helplist.clear()
|
|
|
|
d.user_helplist.append(('name1', 'file1'))
|
|
|
|
d.user_helplist.append(('name2', 'file2'))
|
|
|
|
|
|
|
|
d.update_help_changes()
|
|
|
|
self.assertEqual(mainpage['HelpFiles'],
|
2017-07-30 19:39:17 -03:00
|
|
|
{'1': 'name1;file1', '2': 'name2;file2'})
|
2017-07-26 21:54:40 -03:00
|
|
|
d.update_help_changes = Func()
|
2014-07-15 00:07:32 -03:00
|
|
|
|
|
|
|
|
2017-07-28 18:00:02 -03:00
|
|
|
class VarTraceTest(unittest.TestCase):
|
2017-07-26 20:09:58 -03:00
|
|
|
|
2017-08-07 15:22:44 -03:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
cls.tracers = configdialog.VarTrace()
|
|
|
|
cls.iv = IntVar(root)
|
|
|
|
cls.bv = BooleanVar(root)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
|
|
|
del cls.tracers, cls.iv, cls.bv
|
|
|
|
|
2017-07-26 20:09:58 -03:00
|
|
|
def setUp(self):
|
2017-08-07 15:22:44 -03:00
|
|
|
self.tracers.clear()
|
2017-07-26 20:09:58 -03:00
|
|
|
self.called = 0
|
|
|
|
|
|
|
|
def var_changed_increment(self, *params):
|
|
|
|
self.called += 13
|
|
|
|
|
|
|
|
def var_changed_boolean(self, *params):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def test_init(self):
|
2017-08-07 15:22:44 -03:00
|
|
|
tr = self.tracers
|
|
|
|
tr.__init__()
|
|
|
|
self.assertEqual(tr.untraced, [])
|
|
|
|
self.assertEqual(tr.traced, [])
|
2017-07-28 18:00:02 -03:00
|
|
|
|
|
|
|
def test_clear(self):
|
2017-08-07 15:22:44 -03:00
|
|
|
tr = self.tracers
|
|
|
|
tr.untraced.append(0)
|
|
|
|
tr.traced.append(1)
|
|
|
|
tr.clear()
|
|
|
|
self.assertEqual(tr.untraced, [])
|
|
|
|
self.assertEqual(tr.traced, [])
|
2017-07-26 20:09:58 -03:00
|
|
|
|
|
|
|
def test_add(self):
|
2017-08-07 15:22:44 -03:00
|
|
|
tr = self.tracers
|
2017-07-26 20:09:58 -03:00
|
|
|
func = Func()
|
|
|
|
cb = tr.make_callback = mock.Mock(return_value=func)
|
|
|
|
|
2017-08-07 15:22:44 -03:00
|
|
|
iv = tr.add(self.iv, self.var_changed_increment)
|
|
|
|
self.assertIs(iv, self.iv)
|
|
|
|
bv = tr.add(self.bv, self.var_changed_boolean)
|
|
|
|
self.assertIs(bv, self.bv)
|
2017-07-26 20:09:58 -03:00
|
|
|
|
2017-08-07 15:22:44 -03:00
|
|
|
sv = StringVar(root)
|
|
|
|
sv2 = tr.add(sv, ('main', 'section', 'option'))
|
|
|
|
self.assertIs(sv2, sv)
|
2017-07-26 20:09:58 -03:00
|
|
|
cb.assert_called_once()
|
2017-08-07 15:22:44 -03:00
|
|
|
cb.assert_called_with(sv, ('main', 'section', 'option'))
|
2017-07-26 20:09:58 -03:00
|
|
|
|
2017-08-07 15:22:44 -03:00
|
|
|
expected = [(iv, self.var_changed_increment),
|
|
|
|
(bv, self.var_changed_boolean),
|
|
|
|
(sv, func)]
|
2017-07-26 20:09:58 -03:00
|
|
|
self.assertEqual(tr.traced, [])
|
|
|
|
self.assertEqual(tr.untraced, expected)
|
|
|
|
|
|
|
|
del tr.make_callback
|
|
|
|
|
|
|
|
def test_make_callback(self):
|
2017-08-07 15:22:44 -03:00
|
|
|
cb = self.tracers.make_callback(self.iv, ('main', 'section', 'option'))
|
2017-07-26 20:09:58 -03:00
|
|
|
self.assertTrue(callable(cb))
|
2017-08-07 15:22:44 -03:00
|
|
|
self.iv.set(42)
|
2017-07-26 20:09:58 -03:00
|
|
|
# Not attached, so set didn't invoke the callback.
|
|
|
|
self.assertNotIn('section', changes['main'])
|
|
|
|
# Invoke callback manually.
|
|
|
|
cb()
|
|
|
|
self.assertIn('section', changes['main'])
|
|
|
|
self.assertEqual(changes['main']['section']['option'], '42')
|
2017-08-07 15:22:44 -03:00
|
|
|
changes.clear()
|
2017-07-26 20:09:58 -03:00
|
|
|
|
|
|
|
def test_attach_detach(self):
|
2017-08-07 15:22:44 -03:00
|
|
|
tr = self.tracers
|
|
|
|
iv = tr.add(self.iv, self.var_changed_increment)
|
|
|
|
bv = tr.add(self.bv, self.var_changed_boolean)
|
|
|
|
expected = [(iv, self.var_changed_increment),
|
|
|
|
(bv, self.var_changed_boolean)]
|
2017-07-26 20:09:58 -03:00
|
|
|
|
|
|
|
# Attach callbacks and test call increment.
|
|
|
|
tr.attach()
|
|
|
|
self.assertEqual(tr.untraced, [])
|
|
|
|
self.assertCountEqual(tr.traced, expected)
|
2017-08-07 15:22:44 -03:00
|
|
|
iv.set(1)
|
|
|
|
self.assertEqual(iv.get(), 1)
|
2017-07-26 20:09:58 -03:00
|
|
|
self.assertEqual(self.called, 13)
|
|
|
|
|
|
|
|
# Check that only one callback is attached to a variable.
|
|
|
|
# If more than one callback were attached, then var_changed_increment
|
|
|
|
# would be called twice and the counter would be 2.
|
|
|
|
self.called = 0
|
|
|
|
tr.attach()
|
2017-08-07 15:22:44 -03:00
|
|
|
iv.set(1)
|
2017-07-26 20:09:58 -03:00
|
|
|
self.assertEqual(self.called, 13)
|
|
|
|
|
|
|
|
# Detach callbacks.
|
|
|
|
self.called = 0
|
|
|
|
tr.detach()
|
|
|
|
self.assertEqual(tr.traced, [])
|
|
|
|
self.assertCountEqual(tr.untraced, expected)
|
2017-08-07 15:22:44 -03:00
|
|
|
iv.set(1)
|
2017-07-26 20:09:58 -03:00
|
|
|
self.assertEqual(self.called, 0)
|
|
|
|
|
|
|
|
|
2014-07-15 00:07:32 -03:00
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main(verbosity=2)
|