1 """Test textview, coverage 100%.
2
3 Since all methods and functions create (or destroy) a ViewWindow, which
4 is a widget containing a widget, etcetera, all tests must be gui tests.
5 Using mock Text would not change this. Other mocks are used to retrieve
6 information about calls.
7 """
8 from idlelib import textview as tv
9 from test.support import requires
10 requires('gui')
11
12 import os
13 import unittest
14 from tkinter import Tk, TclError, CHAR, NONE, WORD
15 from tkinter.ttk import Button
16 from idlelib.idle_test.mock_idle import Func
17 from idlelib.idle_test.mock_tk import Mbox_func
18
19 def setUpModule():
20 global root
21 root = Tk()
22 root.withdraw()
23
24 def 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
35 class ESC[4;38;5;81mVW(ESC[4;38;5;149mtvESC[4;38;5;149m.ESC[4;38;5;149mViewWindow): # 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.
42 class ESC[4;38;5;81mViewWindowTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
72 class ESC[4;38;5;81mAutoHideScrollbarTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
80 class ESC[4;38;5;81mScrollableTextFrameTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
124 class ESC[4;38;5;81mViewFrameTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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.
145 class ESC[4;38;5;81mViewFunctionTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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.
191 class ESC[4;38;5;81mButtonClickTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
232 if __name__ == '__main__':
233 unittest.main(verbosity=2)