88import unittest
99from unittest import mock
1010from idlelib .idle_test .mock_idle import Func
11- from tkinter import Tk , StringVar , IntVar , BooleanVar , DISABLED , NORMAL
11+ from tkinter import ( Tk , StringVar , IntVar , BooleanVar , DISABLED , NORMAL )
1212from idlelib import config
1313from idlelib .configdialog import idleConf , changes , tracers
1414
3030keyspage = changes ['keys' ]
3131extpage = changes ['extensions' ]
3232
33+
3334def setUpModule ():
3435 global root , dialog
3536 idleConf .userCfg = testcfg
3637 root = Tk ()
3738 # root.withdraw() # Comment out, see issue 30870
3839 dialog = configdialog .ConfigDialog (root , 'Test' , _utest = True )
3940
41+
4042def tearDownModule ():
4143 global root , dialog
4244 idleConf .userCfg = usercfg
@@ -48,22 +50,56 @@ def tearDownModule():
4850 root = dialog = None
4951
5052
51- class DialogTest (unittest .TestCase ):
53+ class ConfigDialogTest (unittest .TestCase ):
54+
55+ def test_deactivate_current_config (self ):
56+ pass
57+
58+ def activate_config_changes (self ):
59+ pass
60+
5261
53- @mock .patch (__name__ + '.dialog.destroy' , new_callable = Func )
54- def test_cancel (self , destroy ):
62+ class ButtonTest (unittest .TestCase ):
63+
64+ def test_click_ok (self ):
65+ d = dialog
66+ apply = d .apply = mock .Mock ()
67+ destroy = d .destroy = mock .Mock ()
68+ d .buttons ['Ok' ].invoke ()
69+ apply .assert_called_once ()
70+ destroy .assert_called_once ()
71+ del d .destroy , d .apply
72+
73+ def test_click_apply (self ):
74+ d = dialog
75+ deactivate = d .deactivate_current_config = mock .Mock ()
76+ save_ext = d .save_all_changed_extensions = mock .Mock ()
77+ activate = d .activate_config_changes = mock .Mock ()
78+ d .buttons ['Apply' ].invoke ()
79+ deactivate .assert_called_once ()
80+ save_ext .assert_called_once ()
81+ activate .assert_called_once ()
82+ del d .save_all_changed_extensions
83+ del d .activate_config_changes , d .deactivate_current_config
84+
85+ def test_click_cancel (self ):
86+ d = dialog
87+ d .destroy = Func ()
5588 changes ['main' ]['something' ] = 1
56- dialog . cancel ()
89+ d . buttons [ 'Cancel' ]. invoke ()
5790 self .assertEqual (changes ['main' ], {})
58- self .assertEqual (destroy .called , 1 )
91+ self .assertEqual (d .destroy .called , 1 )
92+ del d .destroy
5993
60- @mock .patch ('idlelib.configdialog.view_text' , new_callable = Func )
61- def test_help (self , view ):
94+ def test_click_help (self ):
6295 dialog .note .select (dialog .keyspage )
63- dialog .help ()
64- s = view .kwds ['contents' ]
65- self .assertTrue (s .startswith ('When you click' ) and
66- s .endswith ('a different name.\n ' ))
96+ with mock .patch .object (configdialog , 'view_text' ,
97+ new_callable = Func ) as view :
98+ dialog .buttons ['Help' ].invoke ()
99+ title , contents = view .kwds ['title' ], view .kwds ['contents' ]
100+ self .assertEqual (title , 'Help for IDLE preferences' )
101+ self .assertTrue (contents .startswith ('When you click' ) and
102+ contents .endswith ('a different name.\n ' ))
67103
68104
69105class FontPageTest (unittest .TestCase ):
@@ -438,6 +474,48 @@ def click_it(start):
438474 eq (d .highlight_target .get (), elem [tag ])
439475 eq (d .set_highlight_target .called , count )
440476
477+ def test_highlight_sample_double_click (self ):
478+ # Test double click on highlight_sample.
479+ eq = self .assertEqual
480+ d = self .page
481+
482+ hs = d .highlight_sample
483+ hs .focus_force ()
484+ hs .see (1.0 )
485+ hs .update_idletasks ()
486+
487+ # Test binding from configdialog.
488+ hs .event_generate ('<Enter>' , x = 0 , y = 0 )
489+ hs .event_generate ('<Motion>' , x = 0 , y = 0 )
490+ # Double click is a sequence of two clicks in a row.
491+ for _ in range (2 ):
492+ hs .event_generate ('<ButtonPress-1>' , x = 0 , y = 0 )
493+ hs .event_generate ('<ButtonRelease-1>' , x = 0 , y = 0 )
494+
495+ eq (hs .tag_ranges ('sel' ), ())
496+
497+ def test_highlight_sample_b1_motion (self ):
498+ # Test button motion on highlight_sample.
499+ eq = self .assertEqual
500+ d = self .page
501+
502+ hs = d .highlight_sample
503+ hs .focus_force ()
504+ hs .see (1.0 )
505+ hs .update_idletasks ()
506+
507+ x , y , dx , dy , offset = hs .dlineinfo ('1.0' )
508+
509+ # Test binding from configdialog.
510+ hs .event_generate ('<Leave>' )
511+ hs .event_generate ('<Enter>' )
512+ hs .event_generate ('<Motion>' , x = x , y = y )
513+ hs .event_generate ('<ButtonPress-1>' , x = x , y = y )
514+ hs .event_generate ('<B1-Motion>' , x = dx , y = dy )
515+ hs .event_generate ('<ButtonRelease-1>' , x = dx , y = dy )
516+
517+ eq (hs .tag_ranges ('sel' ), ())
518+
441519 def test_set_theme_type (self ):
442520 eq = self .assertEqual
443521 d = self .page
@@ -666,16 +744,21 @@ def test_delete_custom(self):
666744 idleConf .userCfg ['highlight' ].SetOption (theme_name , 'name' , 'value' )
667745 highpage [theme_name ] = {'option' : 'True' }
668746
747+ theme_name2 = 'other theme'
748+ idleConf .userCfg ['highlight' ].SetOption (theme_name2 , 'name' , 'value' )
749+ highpage [theme_name2 ] = {'option' : 'False' }
750+
669751 # Force custom theme.
670- d .theme_source .set (False )
752+ d .custom_theme_on .state (('!disabled' ,))
753+ d .custom_theme_on .invoke ()
671754 d .custom_name .set (theme_name )
672755
673756 # Cancel deletion.
674757 yesno .result = False
675758 d .button_delete_custom .invoke ()
676759 eq (yesno .called , 1 )
677760 eq (highpage [theme_name ], {'option' : 'True' })
678- eq (idleConf .GetSectionList ('user' , 'highlight' ), ['spam theme' ])
761+ eq (idleConf .GetSectionList ('user' , 'highlight' ), [theme_name , theme_name2 ])
679762 eq (dialog .deactivate_current_config .called , 0 )
680763 eq (dialog .activate_config_changes .called , 0 )
681764 eq (d .set_theme_type .called , 0 )
@@ -685,13 +768,26 @@ def test_delete_custom(self):
685768 d .button_delete_custom .invoke ()
686769 eq (yesno .called , 2 )
687770 self .assertNotIn (theme_name , highpage )
688- eq (idleConf .GetSectionList ('user' , 'highlight' ), [])
689- eq (d .custom_theme_on .state (), ('disabled' , ))
690- eq (d .custom_name .get (), '- no custom themes -' )
771+ eq (idleConf .GetSectionList ('user' , 'highlight' ), [theme_name2 ])
772+ eq (d .custom_theme_on .state (), ())
773+ eq (d .custom_name .get (), theme_name2 )
691774 eq (dialog .deactivate_current_config .called , 1 )
692775 eq (dialog .activate_config_changes .called , 1 )
693776 eq (d .set_theme_type .called , 1 )
694777
778+ # Confirm deletion of second theme - empties list.
779+ d .custom_name .set (theme_name2 )
780+ yesno .result = True
781+ d .button_delete_custom .invoke ()
782+ eq (yesno .called , 3 )
783+ self .assertNotIn (theme_name , highpage )
784+ eq (idleConf .GetSectionList ('user' , 'highlight' ), [])
785+ eq (d .custom_theme_on .state (), ('disabled' ,))
786+ eq (d .custom_name .get (), '- no custom themes -' )
787+ eq (dialog .deactivate_current_config .called , 2 )
788+ eq (dialog .activate_config_changes .called , 2 )
789+ eq (d .set_theme_type .called , 2 )
790+
695791 del dialog .activate_config_changes , dialog .deactivate_current_config
696792 del d .askyesno
697793
@@ -1059,16 +1155,21 @@ def test_delete_custom_keys(self):
10591155 idleConf .userCfg ['keys' ].SetOption (keyset_name , 'name' , 'value' )
10601156 keyspage [keyset_name ] = {'option' : 'True' }
10611157
1158+ keyset_name2 = 'other key set'
1159+ idleConf .userCfg ['keys' ].SetOption (keyset_name2 , 'name' , 'value' )
1160+ keyspage [keyset_name2 ] = {'option' : 'False' }
1161+
10621162 # Force custom keyset.
1063- d .keyset_source .set (False )
1163+ d .custom_keyset_on .state (('!disabled' ,))
1164+ d .custom_keyset_on .invoke ()
10641165 d .custom_name .set (keyset_name )
10651166
10661167 # Cancel deletion.
10671168 yesno .result = False
10681169 d .button_delete_custom_keys .invoke ()
10691170 eq (yesno .called , 1 )
10701171 eq (keyspage [keyset_name ], {'option' : 'True' })
1071- eq (idleConf .GetSectionList ('user' , 'keys' ), ['spam key set' ])
1172+ eq (idleConf .GetSectionList ('user' , 'keys' ), [keyset_name , keyset_name2 ])
10721173 eq (dialog .deactivate_current_config .called , 0 )
10731174 eq (dialog .activate_config_changes .called , 0 )
10741175 eq (d .set_keys_type .called , 0 )
@@ -1078,13 +1179,26 @@ def test_delete_custom_keys(self):
10781179 d .button_delete_custom_keys .invoke ()
10791180 eq (yesno .called , 2 )
10801181 self .assertNotIn (keyset_name , keyspage )
1081- eq (idleConf .GetSectionList ('user' , 'keys' ), [])
1082- eq (d .custom_keyset_on .state (), ('disabled' , ))
1083- eq (d .custom_name .get (), '- no custom keys -' )
1182+ eq (idleConf .GetSectionList ('user' , 'keys' ), [keyset_name2 ])
1183+ eq (d .custom_keyset_on .state (), ())
1184+ eq (d .custom_name .get (), keyset_name2 )
10841185 eq (dialog .deactivate_current_config .called , 1 )
10851186 eq (dialog .activate_config_changes .called , 1 )
10861187 eq (d .set_keys_type .called , 1 )
10871188
1189+ # Confirm deletion of second keyset - empties list.
1190+ d .custom_name .set (keyset_name2 )
1191+ yesno .result = True
1192+ d .button_delete_custom_keys .invoke ()
1193+ eq (yesno .called , 3 )
1194+ self .assertNotIn (keyset_name , keyspage )
1195+ eq (idleConf .GetSectionList ('user' , 'keys' ), [])
1196+ eq (d .custom_keyset_on .state (), ('disabled' ,))
1197+ eq (d .custom_name .get (), '- no custom keys -' )
1198+ eq (dialog .deactivate_current_config .called , 2 )
1199+ eq (dialog .activate_config_changes .called , 2 )
1200+ eq (d .set_keys_type .called , 2 )
1201+
10881202 del dialog .activate_config_changes , dialog .deactivate_current_config
10891203 del d .askyesno
10901204
0 commit comments