| """Test parenmatch, coverage 91%. |
| |
| This must currently be a gui test because ParenMatch methods use |
| several text methods not defined on idlelib.idle_test.mock_tk.Text. |
| """ |
| from idlelib.parenmatch import ParenMatch |
| from test.support import requires |
| requires('gui') |
| |
| import unittest |
| from unittest.mock import Mock |
| from tkinter import Tk, Text |
| |
| |
| class DummyEditwin: |
| def __init__(self, text): |
| self.text = text |
| self.indentwidth = 8 |
| self.tabwidth = 8 |
| self.context_use_ps1 = True |
| |
| |
| class ParenMatchTest(unittest.TestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| cls.root = Tk() |
| cls.root.withdraw() |
| cls.text = Text(cls.root) |
| cls.editwin = DummyEditwin(cls.text) |
| cls.editwin.text_frame = Mock() |
| |
| @classmethod |
| def tearDownClass(cls): |
| del cls.text, cls.editwin |
| cls.root.update_idletasks() |
| cls.root.destroy() |
| del cls.root |
| |
| def tearDown(self): |
| self.text.delete('1.0', 'end') |
| |
| def get_parenmatch(self): |
| pm = ParenMatch(self.editwin) |
| pm.bell = lambda: None |
| return pm |
| |
| def test_paren_styles(self): |
| """ |
| Test ParenMatch with each style. |
| """ |
| text = self.text |
| pm = self.get_parenmatch() |
| for style, range1, range2 in ( |
| ('opener', ('1.10', '1.11'), ('1.10', '1.11')), |
| ('default',('1.10', '1.11'),('1.10', '1.11')), |
| ('parens', ('1.14', '1.15'), ('1.15', '1.16')), |
| ('expression', ('1.10', '1.15'), ('1.10', '1.16'))): |
| with self.subTest(style=style): |
| text.delete('1.0', 'end') |
| pm.STYLE = style |
| text.insert('insert', 'def foobar(a, b') |
| |
| pm.flash_paren_event('event') |
| self.assertIn('<<parenmatch-check-restore>>', text.event_info()) |
| if style == 'parens': |
| self.assertTupleEqual(text.tag_nextrange('paren', '1.0'), |
| ('1.10', '1.11')) |
| self.assertTupleEqual( |
| text.tag_prevrange('paren', 'end'), range1) |
| |
| text.insert('insert', ')') |
| pm.restore_event() |
| self.assertNotIn('<<parenmatch-check-restore>>', |
| text.event_info()) |
| self.assertEqual(text.tag_prevrange('paren', 'end'), ()) |
| |
| pm.paren_closed_event('event') |
| self.assertTupleEqual( |
| text.tag_prevrange('paren', 'end'), range2) |
| |
| def test_paren_corner(self): |
| """ |
| Test corner cases in flash_paren_event and paren_closed_event. |
| |
| These cases force conditional expression and alternate paths. |
| """ |
| text = self.text |
| pm = self.get_parenmatch() |
| |
| text.insert('insert', '# this is a commen)') |
| pm.paren_closed_event('event') |
| |
| text.insert('insert', '\ndef') |
| pm.flash_paren_event('event') |
| pm.paren_closed_event('event') |
| |
| text.insert('insert', ' a, *arg)') |
| pm.paren_closed_event('event') |
| |
| def test_handle_restore_timer(self): |
| pm = self.get_parenmatch() |
| pm.restore_event = Mock() |
| pm.handle_restore_timer(0) |
| self.assertTrue(pm.restore_event.called) |
| pm.restore_event.reset_mock() |
| pm.handle_restore_timer(1) |
| self.assertFalse(pm.restore_event.called) |
| |
| |
| if __name__ == '__main__': |
| unittest.main(verbosity=2) |