Coverage for idle_test/test_editor.py: 53%
101 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-11 13:22 -0700
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-11 13:22 -0700
1"Test editor, coverage 35%."
3from idlelib import editor
4import unittest
5from collections import namedtuple
6from test.support import requires
7from tkinter import Tk
9Editor = editor.EditorWindow
12class EditorWindowTest(unittest.TestCase):
14 @classmethod
15 def setUpClass(cls):
16 requires('gui')
17 cls.root = Tk()
18 cls.root.withdraw()
20 @classmethod
21 def tearDownClass(cls):
22 cls.root.update_idletasks()
23 for id in cls.root.tk.call('after', 'info'):
24 cls.root.after_cancel(id)
25 cls.root.destroy()
26 del cls.root
28 def test_init(self):
29 e = Editor(root=self.root)
30 self.assertEqual(e.root, self.root)
31 e._close()
34class TestGetLineIndent(unittest.TestCase):
35 def test_empty_lines(self):
36 for tabwidth in [1, 2, 4, 6, 8]: 1b
37 for line in ['', '\n']: 1b
38 with self.subTest(line=line, tabwidth=tabwidth): 1b
39 self.assertEqual( 1b
40 editor.get_line_indent(line, tabwidth=tabwidth),
41 (0, 0),
42 )
44 def test_tabwidth_4(self):
45 # (line, (raw, effective))
46 tests = (('no spaces', (0, 0)), 1c
47 # Internal space isn't counted.
48 (' space test', (4, 4)),
49 ('\ttab test', (1, 4)),
50 ('\t\tdouble tabs test', (2, 8)),
51 # Different results when mixing tabs and spaces.
52 (' \tmixed test', (5, 8)),
53 (' \t mixed test', (5, 6)),
54 ('\t mixed test', (5, 8)),
55 # Spaces not divisible by tabwidth.
56 (' \tmixed test', (3, 4)),
57 (' \t mixed test', (3, 5)),
58 ('\t mixed test', (3, 6)),
59 # Only checks spaces and tabs.
60 ('\nnewline test', (0, 0)))
62 for line, expected in tests: 1c
63 with self.subTest(line=line): 1c
64 self.assertEqual( 1c
65 editor.get_line_indent(line, tabwidth=4),
66 expected,
67 )
69 def test_tabwidth_8(self):
70 # (line, (raw, effective))
71 tests = (('no spaces', (0, 0)), 1d
72 # Internal space isn't counted.
73 (' space test', (8, 8)),
74 ('\ttab test', (1, 8)),
75 ('\t\tdouble tabs test', (2, 16)),
76 # Different results when mixing tabs and spaces.
77 (' \tmixed test', (9, 16)),
78 (' \t mixed test', (9, 10)),
79 ('\t mixed test', (9, 16)),
80 # Spaces not divisible by tabwidth.
81 (' \tmixed test', (3, 8)),
82 (' \t mixed test', (3, 9)),
83 ('\t mixed test', (3, 10)),
84 # Only checks spaces and tabs.
85 ('\nnewline test', (0, 0)))
87 for line, expected in tests: 1d
88 with self.subTest(line=line): 1d
89 self.assertEqual( 1d
90 editor.get_line_indent(line, tabwidth=8),
91 expected,
92 )
95def insert(text, string):
96 text.delete('1.0', 'end')
97 text.insert('end', string)
98 text.update() # Force update for colorizer to finish.
101class IndentAndNewlineTest(unittest.TestCase):
103 @classmethod
104 def setUpClass(cls):
105 requires('gui')
106 cls.root = Tk()
107 cls.root.withdraw()
108 cls.window = Editor(root=cls.root)
109 cls.window.indentwidth = 2
110 cls.window.tabwidth = 2
112 @classmethod
113 def tearDownClass(cls):
114 cls.window._close()
115 del cls.window
116 cls.root.update_idletasks()
117 for id in cls.root.tk.call('after', 'info'):
118 cls.root.after_cancel(id)
119 cls.root.destroy()
120 del cls.root
122 def test_indent_and_newline_event(self):
123 eq = self.assertEqual
124 w = self.window
125 text = w.text
126 get = text.get
127 nl = w.newline_and_indent_event
129 TestInfo = namedtuple('Tests', ['label', 'text', 'expected', 'mark'])
131 tests = (TestInfo('Empty line inserts with no indent.',
132 ' \n def __init__(self):',
133 '\n \n def __init__(self):\n',
134 '1.end'),
135 TestInfo('Inside bracket before space, deletes space.',
136 ' def f1(self, a, b):',
137 ' def f1(self,\n a, b):\n',
138 '1.14'),
139 TestInfo('Inside bracket after space, deletes space.',
140 ' def f1(self, a, b):',
141 ' def f1(self,\n a, b):\n',
142 '1.15'),
143 TestInfo('Inside string with one line - no indent.',
144 ' """Docstring."""',
145 ' """Docstring.\n"""\n',
146 '1.15'),
147 TestInfo('Inside string with more than one line.',
148 ' """Docstring.\n Docstring Line 2"""',
149 ' """Docstring.\n Docstring Line 2\n """\n',
150 '2.18'),
151 TestInfo('Backslash with one line.',
152 'a =\\',
153 'a =\\\n \n',
154 '1.end'),
155 TestInfo('Backslash with more than one line.',
156 'a =\\\n multiline\\',
157 'a =\\\n multiline\\\n \n',
158 '2.end'),
159 TestInfo('Block opener - indents +1 level.',
160 ' def f1(self):\n pass',
161 ' def f1(self):\n \n pass\n',
162 '1.end'),
163 TestInfo('Block closer - dedents -1 level.',
164 ' def f1(self):\n pass',
165 ' def f1(self):\n pass\n \n',
166 '2.end'),
167 )
169 for test in tests:
170 with self.subTest(label=test.label):
171 insert(text, test.text)
172 text.mark_set('insert', test.mark)
173 nl(event=None)
174 eq(get('1.0', 'end'), test.expected)
176 # Selected text.
177 insert(text, ' def f1(self, a, b):\n return a + b')
178 text.tag_add('sel', '1.17', '1.end')
179 nl(None)
180 # Deletes selected text before adding new line.
181 eq(get('1.0', 'end'), ' def f1(self, a,\n \n return a + b\n')
184class RMenuTest(unittest.TestCase):
186 @classmethod
187 def setUpClass(cls):
188 requires('gui')
189 cls.root = Tk()
190 cls.root.withdraw()
191 cls.window = Editor(root=cls.root)
193 @classmethod
194 def tearDownClass(cls):
195 cls.window._close()
196 del cls.window
197 cls.root.update_idletasks()
198 for id in cls.root.tk.call('after', 'info'):
199 cls.root.after_cancel(id)
200 cls.root.destroy()
201 del cls.root
203 class DummyRMenu:
204 def tk_popup(x, y): pass 204 ↛ exitline 204 didn't return from function 'tk_popup'
206 def test_rclick(self):
207 pass
210if __name__ == '__main__': 210 ↛ 211line 210 didn't jump to line 211, because the condition on line 210 was never true
211 unittest.main(verbosity=2)