1"""Unittest for UndoDelegator in idlelib.undo.py. 2 3Coverage about 80% (retest). 4""" 5from test.support import requires 6requires('gui') 7 8import unittest 9from unittest.mock import Mock 10from tkinter import Text, Tk 11from idlelib.undo import UndoDelegator 12from idlelib.percolator import Percolator 13 14 15class UndoDelegatorTest(unittest.TestCase): 16 17 @classmethod 18 def setUpClass(cls): 19 cls.root = Tk() 20 cls.text = Text(cls.root) 21 cls.percolator = Percolator(cls.text) 22 23 @classmethod 24 def tearDownClass(cls): 25 cls.percolator.redir.close() 26 del cls.percolator, cls.text 27 cls.root.destroy() 28 del cls.root 29 30 def setUp(self): 31 self.delegator = UndoDelegator() 32 self.delegator.bell = Mock() 33 self.percolator.insertfilter(self.delegator) 34 35 def tearDown(self): 36 self.percolator.removefilter(self.delegator) 37 self.text.delete('1.0', 'end') 38 self.delegator.resetcache() 39 40 def test_undo_event(self): 41 text = self.text 42 43 text.insert('insert', 'foobar') 44 text.insert('insert', 'h') 45 text.event_generate('<<undo>>') 46 self.assertEqual(text.get('1.0', 'end'), '\n') 47 48 text.insert('insert', 'foo') 49 text.insert('insert', 'bar') 50 text.delete('1.2', '1.4') 51 text.insert('insert', 'hello') 52 text.event_generate('<<undo>>') 53 self.assertEqual(text.get('1.0', '1.4'), 'foar') 54 text.event_generate('<<undo>>') 55 self.assertEqual(text.get('1.0', '1.6'), 'foobar') 56 text.event_generate('<<undo>>') 57 self.assertEqual(text.get('1.0', '1.3'), 'foo') 58 text.event_generate('<<undo>>') 59 self.delegator.undo_event('event') 60 self.assertTrue(self.delegator.bell.called) 61 62 def test_redo_event(self): 63 text = self.text 64 65 text.insert('insert', 'foo') 66 text.insert('insert', 'bar') 67 text.delete('1.0', '1.3') 68 text.event_generate('<<undo>>') 69 text.event_generate('<<redo>>') 70 self.assertEqual(text.get('1.0', '1.3'), 'bar') 71 text.event_generate('<<redo>>') 72 self.assertTrue(self.delegator.bell.called) 73 74 def test_dump_event(self): 75 """ 76 Dump_event cannot be tested directly without changing 77 environment variables. So, test statements in dump_event 78 indirectly 79 """ 80 text = self.text 81 d = self.delegator 82 83 text.insert('insert', 'foo') 84 text.insert('insert', 'bar') 85 text.delete('1.2', '1.4') 86 self.assertTupleEqual((d.pointer, d.can_merge), (3, True)) 87 text.event_generate('<<undo>>') 88 self.assertTupleEqual((d.pointer, d.can_merge), (2, False)) 89 90 def test_get_set_saved(self): 91 # test the getter method get_saved 92 # test the setter method set_saved 93 # indirectly test check_saved 94 d = self.delegator 95 96 self.assertTrue(d.get_saved()) 97 self.text.insert('insert', 'a') 98 self.assertFalse(d.get_saved()) 99 d.saved_change_hook = Mock() 100 101 d.set_saved(True) 102 self.assertEqual(d.pointer, d.saved) 103 self.assertTrue(d.saved_change_hook.called) 104 105 d.set_saved(False) 106 self.assertEqual(d.saved, -1) 107 self.assertTrue(d.saved_change_hook.called) 108 109 def test_undo_start_stop(self): 110 # test the undo_block_start and undo_block_stop methods 111 text = self.text 112 113 text.insert('insert', 'foo') 114 self.delegator.undo_block_start() 115 text.insert('insert', 'bar') 116 text.insert('insert', 'bar') 117 self.delegator.undo_block_stop() 118 self.assertEqual(text.get('1.0', '1.3'), 'foo') 119 120 # test another code path 121 self.delegator.undo_block_start() 122 text.insert('insert', 'bar') 123 self.delegator.undo_block_stop() 124 self.assertEqual(text.get('1.0', '1.3'), 'foo') 125 126 def test_addcmd(self): 127 text = self.text 128 # when number of undo operations exceeds max_undo 129 self.delegator.max_undo = max_undo = 10 130 for i in range(max_undo + 10): 131 text.insert('insert', 'foo') 132 self.assertLessEqual(len(self.delegator.undolist), max_undo) 133 134if __name__ == '__main__': 135 unittest.main(verbosity=2, exit=False) 136