17db96d56Sopenharmony_ci"Test editor, coverage 53%."
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_cifrom idlelib import editor
47db96d56Sopenharmony_ciimport unittest
57db96d56Sopenharmony_cifrom collections import namedtuple
67db96d56Sopenharmony_cifrom test.support import requires
77db96d56Sopenharmony_cifrom tkinter import Tk, Text
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ciEditor = editor.EditorWindow
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ciclass EditorWindowTest(unittest.TestCase):
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci    @classmethod
157db96d56Sopenharmony_ci    def setUpClass(cls):
167db96d56Sopenharmony_ci        requires('gui')
177db96d56Sopenharmony_ci        cls.root = Tk()
187db96d56Sopenharmony_ci        cls.root.withdraw()
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci    @classmethod
217db96d56Sopenharmony_ci    def tearDownClass(cls):
227db96d56Sopenharmony_ci        cls.root.update_idletasks()
237db96d56Sopenharmony_ci        for id in cls.root.tk.call('after', 'info'):
247db96d56Sopenharmony_ci            cls.root.after_cancel(id)
257db96d56Sopenharmony_ci        cls.root.destroy()
267db96d56Sopenharmony_ci        del cls.root
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci    def test_init(self):
297db96d56Sopenharmony_ci        e = Editor(root=self.root)
307db96d56Sopenharmony_ci        self.assertEqual(e.root, self.root)
317db96d56Sopenharmony_ci        e._close()
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ciclass GetLineIndentTest(unittest.TestCase):
357db96d56Sopenharmony_ci    def test_empty_lines(self):
367db96d56Sopenharmony_ci        for tabwidth in [1, 2, 4, 6, 8]:
377db96d56Sopenharmony_ci            for line in ['', '\n']:
387db96d56Sopenharmony_ci                with self.subTest(line=line, tabwidth=tabwidth):
397db96d56Sopenharmony_ci                    self.assertEqual(
407db96d56Sopenharmony_ci                        editor.get_line_indent(line, tabwidth=tabwidth),
417db96d56Sopenharmony_ci                        (0, 0),
427db96d56Sopenharmony_ci                    )
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci    def test_tabwidth_4(self):
457db96d56Sopenharmony_ci        #        (line, (raw, effective))
467db96d56Sopenharmony_ci        tests = (('no spaces', (0, 0)),
477db96d56Sopenharmony_ci                 # Internal space isn't counted.
487db96d56Sopenharmony_ci                 ('    space test', (4, 4)),
497db96d56Sopenharmony_ci                 ('\ttab test', (1, 4)),
507db96d56Sopenharmony_ci                 ('\t\tdouble tabs test', (2, 8)),
517db96d56Sopenharmony_ci                 # Different results when mixing tabs and spaces.
527db96d56Sopenharmony_ci                 ('    \tmixed test', (5, 8)),
537db96d56Sopenharmony_ci                 ('  \t  mixed test', (5, 6)),
547db96d56Sopenharmony_ci                 ('\t    mixed test', (5, 8)),
557db96d56Sopenharmony_ci                 # Spaces not divisible by tabwidth.
567db96d56Sopenharmony_ci                 ('  \tmixed test', (3, 4)),
577db96d56Sopenharmony_ci                 (' \t mixed test', (3, 5)),
587db96d56Sopenharmony_ci                 ('\t  mixed test', (3, 6)),
597db96d56Sopenharmony_ci                 # Only checks spaces and tabs.
607db96d56Sopenharmony_ci                 ('\nnewline test', (0, 0)))
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci        for line, expected in tests:
637db96d56Sopenharmony_ci            with self.subTest(line=line):
647db96d56Sopenharmony_ci                self.assertEqual(
657db96d56Sopenharmony_ci                    editor.get_line_indent(line, tabwidth=4),
667db96d56Sopenharmony_ci                    expected,
677db96d56Sopenharmony_ci                )
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci    def test_tabwidth_8(self):
707db96d56Sopenharmony_ci        #        (line, (raw, effective))
717db96d56Sopenharmony_ci        tests = (('no spaces', (0, 0)),
727db96d56Sopenharmony_ci                 # Internal space isn't counted.
737db96d56Sopenharmony_ci                 ('        space test', (8, 8)),
747db96d56Sopenharmony_ci                 ('\ttab test', (1, 8)),
757db96d56Sopenharmony_ci                 ('\t\tdouble tabs test', (2, 16)),
767db96d56Sopenharmony_ci                 # Different results when mixing tabs and spaces.
777db96d56Sopenharmony_ci                 ('        \tmixed test', (9, 16)),
787db96d56Sopenharmony_ci                 ('      \t  mixed test', (9, 10)),
797db96d56Sopenharmony_ci                 ('\t        mixed test', (9, 16)),
807db96d56Sopenharmony_ci                 # Spaces not divisible by tabwidth.
817db96d56Sopenharmony_ci                 ('  \tmixed test', (3, 8)),
827db96d56Sopenharmony_ci                 (' \t mixed test', (3, 9)),
837db96d56Sopenharmony_ci                 ('\t  mixed test', (3, 10)),
847db96d56Sopenharmony_ci                 # Only checks spaces and tabs.
857db96d56Sopenharmony_ci                 ('\nnewline test', (0, 0)))
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci        for line, expected in tests:
887db96d56Sopenharmony_ci            with self.subTest(line=line):
897db96d56Sopenharmony_ci                self.assertEqual(
907db96d56Sopenharmony_ci                    editor.get_line_indent(line, tabwidth=8),
917db96d56Sopenharmony_ci                    expected,
927db96d56Sopenharmony_ci                )
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_cidef insert(text, string):
967db96d56Sopenharmony_ci    text.delete('1.0', 'end')
977db96d56Sopenharmony_ci    text.insert('end', string)
987db96d56Sopenharmony_ci    text.update()  # Force update for colorizer to finish.
997db96d56Sopenharmony_ci
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ciclass IndentAndNewlineTest(unittest.TestCase):
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ci    @classmethod
1047db96d56Sopenharmony_ci    def setUpClass(cls):
1057db96d56Sopenharmony_ci        requires('gui')
1067db96d56Sopenharmony_ci        cls.root = Tk()
1077db96d56Sopenharmony_ci        cls.root.withdraw()
1087db96d56Sopenharmony_ci        cls.window = Editor(root=cls.root)
1097db96d56Sopenharmony_ci        cls.window.indentwidth = 2
1107db96d56Sopenharmony_ci        cls.window.tabwidth = 2
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_ci    @classmethod
1137db96d56Sopenharmony_ci    def tearDownClass(cls):
1147db96d56Sopenharmony_ci        cls.window._close()
1157db96d56Sopenharmony_ci        del cls.window
1167db96d56Sopenharmony_ci        cls.root.update_idletasks()
1177db96d56Sopenharmony_ci        for id in cls.root.tk.call('after', 'info'):
1187db96d56Sopenharmony_ci            cls.root.after_cancel(id)
1197db96d56Sopenharmony_ci        cls.root.destroy()
1207db96d56Sopenharmony_ci        del cls.root
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci    def test_indent_and_newline_event(self):
1237db96d56Sopenharmony_ci        eq = self.assertEqual
1247db96d56Sopenharmony_ci        w = self.window
1257db96d56Sopenharmony_ci        text = w.text
1267db96d56Sopenharmony_ci        get = text.get
1277db96d56Sopenharmony_ci        nl = w.newline_and_indent_event
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci        TestInfo = namedtuple('Tests', ['label', 'text', 'expected', 'mark'])
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci        tests = (TestInfo('Empty line inserts with no indent.',
1327db96d56Sopenharmony_ci                          '  \n  def __init__(self):',
1337db96d56Sopenharmony_ci                          '\n  \n  def __init__(self):\n',
1347db96d56Sopenharmony_ci                          '1.end'),
1357db96d56Sopenharmony_ci                 TestInfo('Inside bracket before space, deletes space.',
1367db96d56Sopenharmony_ci                          '  def f1(self, a, b):',
1377db96d56Sopenharmony_ci                          '  def f1(self,\n         a, b):\n',
1387db96d56Sopenharmony_ci                          '1.14'),
1397db96d56Sopenharmony_ci                 TestInfo('Inside bracket after space, deletes space.',
1407db96d56Sopenharmony_ci                          '  def f1(self, a, b):',
1417db96d56Sopenharmony_ci                          '  def f1(self,\n         a, b):\n',
1427db96d56Sopenharmony_ci                          '1.15'),
1437db96d56Sopenharmony_ci                 TestInfo('Inside string with one line - no indent.',
1447db96d56Sopenharmony_ci                          '  """Docstring."""',
1457db96d56Sopenharmony_ci                          '  """Docstring.\n"""\n',
1467db96d56Sopenharmony_ci                          '1.15'),
1477db96d56Sopenharmony_ci                 TestInfo('Inside string with more than one line.',
1487db96d56Sopenharmony_ci                          '  """Docstring.\n  Docstring Line 2"""',
1497db96d56Sopenharmony_ci                          '  """Docstring.\n  Docstring Line 2\n  """\n',
1507db96d56Sopenharmony_ci                          '2.18'),
1517db96d56Sopenharmony_ci                 TestInfo('Backslash with one line.',
1527db96d56Sopenharmony_ci                          'a =\\',
1537db96d56Sopenharmony_ci                          'a =\\\n  \n',
1547db96d56Sopenharmony_ci                          '1.end'),
1557db96d56Sopenharmony_ci                 TestInfo('Backslash with more than one line.',
1567db96d56Sopenharmony_ci                          'a =\\\n          multiline\\',
1577db96d56Sopenharmony_ci                          'a =\\\n          multiline\\\n          \n',
1587db96d56Sopenharmony_ci                          '2.end'),
1597db96d56Sopenharmony_ci                 TestInfo('Block opener - indents +1 level.',
1607db96d56Sopenharmony_ci                          '  def f1(self):\n    pass',
1617db96d56Sopenharmony_ci                          '  def f1(self):\n    \n    pass\n',
1627db96d56Sopenharmony_ci                          '1.end'),
1637db96d56Sopenharmony_ci                 TestInfo('Block closer - dedents -1 level.',
1647db96d56Sopenharmony_ci                          '  def f1(self):\n    pass',
1657db96d56Sopenharmony_ci                          '  def f1(self):\n    pass\n  \n',
1667db96d56Sopenharmony_ci                          '2.end'),
1677db96d56Sopenharmony_ci                 )
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci        for test in tests:
1707db96d56Sopenharmony_ci            with self.subTest(label=test.label):
1717db96d56Sopenharmony_ci                insert(text, test.text)
1727db96d56Sopenharmony_ci                text.mark_set('insert', test.mark)
1737db96d56Sopenharmony_ci                nl(event=None)
1747db96d56Sopenharmony_ci                eq(get('1.0', 'end'), test.expected)
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ci        # Selected text.
1777db96d56Sopenharmony_ci        insert(text, '  def f1(self, a, b):\n    return a + b')
1787db96d56Sopenharmony_ci        text.tag_add('sel', '1.17', '1.end')
1797db96d56Sopenharmony_ci        nl(None)
1807db96d56Sopenharmony_ci        # Deletes selected text before adding new line.
1817db96d56Sopenharmony_ci        eq(get('1.0', 'end'), '  def f1(self, a,\n         \n    return a + b\n')
1827db96d56Sopenharmony_ci
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ciclass IndentSearcherTest(unittest.TestCase):
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci    @classmethod
1877db96d56Sopenharmony_ci    def setUpClass(cls):
1887db96d56Sopenharmony_ci        requires('gui')
1897db96d56Sopenharmony_ci        cls.root = Tk()
1907db96d56Sopenharmony_ci        cls.root.withdraw()
1917db96d56Sopenharmony_ci        cls.text = Text(cls.root)
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci    @classmethod
1947db96d56Sopenharmony_ci    def tearDownClass(cls):
1957db96d56Sopenharmony_ci        cls.root.destroy()
1967db96d56Sopenharmony_ci        del cls.root
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ci    def test_searcher(self):
1997db96d56Sopenharmony_ci        text = self.text
2007db96d56Sopenharmony_ci        searcher = (self.text)
2017db96d56Sopenharmony_ci        test_info = (# text, (block, indent))
2027db96d56Sopenharmony_ci                     ("", (None, None)),
2037db96d56Sopenharmony_ci                     ("[1,", (None, None)),  # TokenError
2047db96d56Sopenharmony_ci                     ("if 1:\n", ('if 1:\n', None)),
2057db96d56Sopenharmony_ci                     ("if 1:\n  2\n  3\n", ('if 1:\n', '  2\n')),
2067db96d56Sopenharmony_ci                     )
2077db96d56Sopenharmony_ci        for code, expected_pair in test_info:
2087db96d56Sopenharmony_ci            with self.subTest(code=code):
2097db96d56Sopenharmony_ci                insert(text, code)
2107db96d56Sopenharmony_ci                actual_pair = editor.IndentSearcher(text).run()
2117db96d56Sopenharmony_ci                self.assertEqual(actual_pair, expected_pair)
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci
2147db96d56Sopenharmony_ciclass RMenuTest(unittest.TestCase):
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci    @classmethod
2177db96d56Sopenharmony_ci    def setUpClass(cls):
2187db96d56Sopenharmony_ci        requires('gui')
2197db96d56Sopenharmony_ci        cls.root = Tk()
2207db96d56Sopenharmony_ci        cls.root.withdraw()
2217db96d56Sopenharmony_ci        cls.window = Editor(root=cls.root)
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ci    @classmethod
2247db96d56Sopenharmony_ci    def tearDownClass(cls):
2257db96d56Sopenharmony_ci        cls.window._close()
2267db96d56Sopenharmony_ci        del cls.window
2277db96d56Sopenharmony_ci        cls.root.update_idletasks()
2287db96d56Sopenharmony_ci        for id in cls.root.tk.call('after', 'info'):
2297db96d56Sopenharmony_ci            cls.root.after_cancel(id)
2307db96d56Sopenharmony_ci        cls.root.destroy()
2317db96d56Sopenharmony_ci        del cls.root
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci    class DummyRMenu:
2347db96d56Sopenharmony_ci        def tk_popup(x, y): pass
2357db96d56Sopenharmony_ci
2367db96d56Sopenharmony_ci    def test_rclick(self):
2377db96d56Sopenharmony_ci        pass
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ciif __name__ == '__main__':
2417db96d56Sopenharmony_ci    unittest.main(verbosity=2)
242