1"""Test textview, coverage 100%. 2 3Since all methods and functions create (or destroy) a ViewWindow, which 4is a widget containing a widget, etcetera, all tests must be gui tests. 5Using mock Text would not change this. Other mocks are used to retrieve 6information about calls. 7""" 8from idlelib import textview as tv 9from test.support import requires 10requires('gui') 11 12import os 13import unittest 14from tkinter import Tk, TclError, CHAR, NONE, WORD 15from tkinter.ttk import Button 16from idlelib.idle_test.mock_idle import Func 17from idlelib.idle_test.mock_tk import Mbox_func 18 19def setUpModule(): 20 global root 21 root = Tk() 22 root.withdraw() 23 24def tearDownModule(): 25 global root 26 root.update_idletasks() 27 root.destroy() 28 del root 29 30# If we call ViewWindow or wrapper functions with defaults 31# modal=True, _utest=False, test hangs on call to wait_window. 32# Have also gotten tk error 'can't invoke "event" command'. 33 34 35class VW(tv.ViewWindow): # Used in ViewWindowTest. 36 transient = Func() 37 grab_set = Func() 38 wait_window = Func() 39 40 41# Call wrapper class VW with mock wait_window. 42class ViewWindowTest(unittest.TestCase): 43 44 def setUp(self): 45 VW.transient.__init__() 46 VW.grab_set.__init__() 47 VW.wait_window.__init__() 48 49 def test_init_modal(self): 50 view = VW(root, 'Title', 'test text') 51 self.assertTrue(VW.transient.called) 52 self.assertTrue(VW.grab_set.called) 53 self.assertTrue(VW.wait_window.called) 54 view.ok() 55 56 def test_init_nonmodal(self): 57 view = VW(root, 'Title', 'test text', modal=False) 58 self.assertFalse(VW.transient.called) 59 self.assertFalse(VW.grab_set.called) 60 self.assertFalse(VW.wait_window.called) 61 view.ok() 62 63 def test_ok(self): 64 view = VW(root, 'Title', 'test text', modal=False) 65 view.destroy = Func() 66 view.ok() 67 self.assertTrue(view.destroy.called) 68 del view.destroy # Unmask real function. 69 view.destroy() 70 71 72class AutoHideScrollbarTest(unittest.TestCase): 73 # Method set is tested in ScrollableTextFrameTest 74 def test_forbidden_geometry(self): 75 scroll = tv.AutoHideScrollbar(root) 76 self.assertRaises(TclError, scroll.pack) 77 self.assertRaises(TclError, scroll.place) 78 79 80class ScrollableTextFrameTest(unittest.TestCase): 81 82 @classmethod 83 def setUpClass(cls): 84 cls.root = root = Tk() 85 root.withdraw() 86 87 @classmethod 88 def tearDownClass(cls): 89 cls.root.update_idletasks() 90 cls.root.destroy() 91 del cls.root 92 93 def make_frame(self, wrap=NONE, **kwargs): 94 frame = tv.ScrollableTextFrame(self.root, wrap=wrap, **kwargs) 95 def cleanup_frame(): 96 frame.update_idletasks() 97 frame.destroy() 98 self.addCleanup(cleanup_frame) 99 return frame 100 101 def test_line1(self): 102 frame = self.make_frame() 103 frame.text.insert('1.0', 'test text') 104 self.assertEqual(frame.text.get('1.0', '1.end'), 'test text') 105 106 def test_horiz_scrollbar(self): 107 # The horizontal scrollbar should be shown/hidden according to 108 # the 'wrap' setting: It should only be shown when 'wrap' is 109 # set to NONE. 110 111 # wrap = NONE -> with horizontal scrolling 112 frame = self.make_frame(wrap=NONE) 113 self.assertEqual(frame.text.cget('wrap'), NONE) 114 self.assertIsNotNone(frame.xscroll) 115 116 # wrap != NONE -> no horizontal scrolling 117 for wrap in [CHAR, WORD]: 118 with self.subTest(wrap=wrap): 119 frame = self.make_frame(wrap=wrap) 120 self.assertEqual(frame.text.cget('wrap'), wrap) 121 self.assertIsNone(frame.xscroll) 122 123 124class ViewFrameTest(unittest.TestCase): 125 126 @classmethod 127 def setUpClass(cls): 128 cls.root = root = Tk() 129 root.withdraw() 130 cls.frame = tv.ViewFrame(root, 'test text') 131 132 @classmethod 133 def tearDownClass(cls): 134 del cls.frame 135 cls.root.update_idletasks() 136 cls.root.destroy() 137 del cls.root 138 139 def test_line1(self): 140 get = self.frame.text.get 141 self.assertEqual(get('1.0', '1.end'), 'test text') 142 143 144# Call ViewWindow with modal=False. 145class ViewFunctionTest(unittest.TestCase): 146 147 @classmethod 148 def setUpClass(cls): 149 cls.orig_error = tv.showerror 150 tv.showerror = Mbox_func() 151 152 @classmethod 153 def tearDownClass(cls): 154 tv.showerror = cls.orig_error 155 del cls.orig_error 156 157 def test_view_text(self): 158 view = tv.view_text(root, 'Title', 'test text', modal=False) 159 self.assertIsInstance(view, tv.ViewWindow) 160 self.assertIsInstance(view.viewframe, tv.ViewFrame) 161 view.viewframe.ok() 162 163 def test_view_file(self): 164 view = tv.view_file(root, 'Title', __file__, 'ascii', modal=False) 165 self.assertIsInstance(view, tv.ViewWindow) 166 self.assertIsInstance(view.viewframe, tv.ViewFrame) 167 get = view.viewframe.textframe.text.get 168 self.assertIn('Test', get('1.0', '1.end')) 169 view.ok() 170 171 def test_bad_file(self): 172 # Mock showerror will be used; view_file will return None. 173 view = tv.view_file(root, 'Title', 'abc.xyz', 'ascii', modal=False) 174 self.assertIsNone(view) 175 self.assertEqual(tv.showerror.title, 'File Load Error') 176 177 def test_bad_encoding(self): 178 p = os.path 179 fn = p.abspath(p.join(p.dirname(__file__), '..', 'CREDITS.txt')) 180 view = tv.view_file(root, 'Title', fn, 'ascii', modal=False) 181 self.assertIsNone(view) 182 self.assertEqual(tv.showerror.title, 'Unicode Decode Error') 183 184 def test_nowrap(self): 185 view = tv.view_text(root, 'Title', 'test', modal=False, wrap='none') 186 text_widget = view.viewframe.textframe.text 187 self.assertEqual(text_widget.cget('wrap'), 'none') 188 189 190# Call ViewWindow with _utest=True. 191class ButtonClickTest(unittest.TestCase): 192 193 def setUp(self): 194 self.view = None 195 self.called = False 196 197 def tearDown(self): 198 if self.view: 199 self.view.destroy() 200 201 def test_view_text_bind_with_button(self): 202 def _command(): 203 self.called = True 204 self.view = tv.view_text(root, 'TITLE_TEXT', 'COMMAND', _utest=True) 205 button = Button(root, text='BUTTON', command=_command) 206 button.invoke() 207 self.addCleanup(button.destroy) 208 209 self.assertEqual(self.called, True) 210 self.assertEqual(self.view.title(), 'TITLE_TEXT') 211 self.assertEqual(self.view.viewframe.textframe.text.get('1.0', '1.end'), 212 'COMMAND') 213 214 def test_view_file_bind_with_button(self): 215 def _command(): 216 self.called = True 217 self.view = tv.view_file(root, 'TITLE_FILE', __file__, 218 encoding='ascii', _utest=True) 219 button = Button(root, text='BUTTON', command=_command) 220 button.invoke() 221 self.addCleanup(button.destroy) 222 223 self.assertEqual(self.called, True) 224 self.assertEqual(self.view.title(), 'TITLE_FILE') 225 get = self.view.viewframe.textframe.text.get 226 with open(__file__) as f: 227 self.assertEqual(get('1.0', '1.end'), f.readline().strip()) 228 f.readline() 229 self.assertEqual(get('3.0', '3.end'), f.readline().strip()) 230 231 232if __name__ == '__main__': 233 unittest.main(verbosity=2) 234