1import unittest
2from test.test_support import requires
3
4import Tkinter as tk
5from Tkinter import Text as tkText
6from idlelib.idle_test.mock_tk import Text as mkText
7from idlelib.IdleHistory import History
8from idlelib.configHandler import idleConf
9
10line1 = 'a = 7'
11line2 = 'b = a'
12
13class StoreTest(unittest.TestCase):
14    '''Tests History.__init__ and History.store with mock Text'''
15
16    @classmethod
17    def setUpClass(cls):
18        cls.text = mkText()
19        cls.history = History(cls.text)
20
21    def tearDown(self):
22        self.text.delete('1.0', 'end')
23        self.history.history = []
24
25    def test_init(self):
26        self.assertIs(self.history.text, self.text)
27        self.assertEqual(self.history.history, [])
28        self.assertIsNone(self.history.prefix)
29        self.assertIsNone(self.history.pointer)
30        self.assertEqual(self.history.cyclic,
31                idleConf.GetOption("main", "History",  "cyclic", 1, "bool"))
32
33    def test_store_short(self):
34        self.history.store('a')
35        self.assertEqual(self.history.history, [])
36        self.history.store('  a  ')
37        self.assertEqual(self.history.history, [])
38
39    def test_store_dup(self):
40        self.history.store(line1)
41        self.assertEqual(self.history.history, [line1])
42        self.history.store(line2)
43        self.assertEqual(self.history.history, [line1, line2])
44        self.history.store(line1)
45        self.assertEqual(self.history.history, [line2, line1])
46
47    def test_store_reset(self):
48        self.history.prefix = line1
49        self.history.pointer = 0
50        self.history.store(line2)
51        self.assertIsNone(self.history.prefix)
52        self.assertIsNone(self.history.pointer)
53
54
55class TextWrapper:
56    def __init__(self, master):
57        self.text = tkText(master=master)
58        self._bell = False
59    def __getattr__(self, name):
60        return getattr(self.text, name)
61    def bell(self):
62        self._bell = True
63
64class FetchTest(unittest.TestCase):
65    '''Test History.fetch with wrapped tk.Text.
66    '''
67    @classmethod
68    def setUpClass(cls):
69        requires('gui')
70        cls.root = tk.Tk()
71        cls.root.withdraw()
72
73    def setUp(self):
74        self.text = text = TextWrapper(self.root)
75        text.insert('1.0', ">>> ")
76        text.mark_set('iomark', '1.4')
77        text.mark_gravity('iomark', 'left')
78        self.history = History(text)
79        self.history.history = [line1, line2]
80
81    @classmethod
82    def tearDownClass(cls):
83        cls.root.destroy()
84        del cls.root
85
86    def fetch_test(self, reverse, line, prefix, index, bell=False):
87        # Perform one fetch as invoked by Alt-N or Alt-P
88        # Test the result. The line test is the most important.
89        # The last two are diagnostic of fetch internals.
90        History = self.history
91        History.fetch(reverse)
92
93        Equal = self.assertEqual
94        Equal(self.text.get('iomark', 'end-1c'), line)
95        Equal(self.text._bell, bell)
96        if bell:
97            self.text._bell = False
98        Equal(History.prefix, prefix)
99        Equal(History.pointer, index)
100        Equal(self.text.compare("insert", '==', "end-1c"), 1)
101
102    def test_fetch_prev_cyclic(self):
103        prefix = ''
104        test = self.fetch_test
105        test(True, line2, prefix, 1)
106        test(True, line1, prefix, 0)
107        test(True, prefix, None, None, bell=True)
108
109    def test_fetch_next_cyclic(self):
110        prefix = ''
111        test  = self.fetch_test
112        test(False, line1, prefix, 0)
113        test(False, line2, prefix, 1)
114        test(False, prefix, None, None, bell=True)
115
116    # Prefix 'a' tests skip line2, which starts with 'b'
117    def test_fetch_prev_prefix(self):
118        prefix = 'a'
119        self.text.insert('iomark', prefix)
120        self.fetch_test(True, line1, prefix, 0)
121        self.fetch_test(True, prefix, None, None, bell=True)
122
123    def test_fetch_next_prefix(self):
124        prefix = 'a'
125        self.text.insert('iomark', prefix)
126        self.fetch_test(False, line1, prefix, 0)
127        self.fetch_test(False, prefix, None, None, bell=True)
128
129    def test_fetch_prev_noncyclic(self):
130        prefix = ''
131        self.history.cyclic = False
132        test = self.fetch_test
133        test(True, line2, prefix, 1)
134        test(True, line1, prefix, 0)
135        test(True, line1, prefix, 0, bell=True)
136
137    def test_fetch_next_noncyclic(self):
138        prefix = ''
139        self.history.cyclic = False
140        test  = self.fetch_test
141        test(False, prefix, None, None, bell=True)
142        test(True, line2, prefix, 1)
143        test(False, prefix, None, None, bell=True)
144        test(False, prefix, None, None, bell=True)
145
146    def test_fetch_cursor_move(self):
147        # Move cursor after fetch
148        self.history.fetch(reverse=True)  # initialization
149        self.text.mark_set('insert', 'iomark')
150        self.fetch_test(True, line2, None, None, bell=True)
151
152    def test_fetch_edit(self):
153        # Edit after fetch
154        self.history.fetch(reverse=True)  # initialization
155        self.text.delete('iomark', 'insert', )
156        self.text.insert('iomark', 'a =')
157        self.fetch_test(True, line1, 'a =', 0)  # prefix is reset
158
159    def test_history_prev_next(self):
160        # Minimally test functions bound to events
161        self.history.history_prev('dummy event')
162        self.assertEqual(self.history.pointer, 1)
163        self.history.history_next('dummy event')
164        self.assertEqual(self.history.pointer, None)
165
166
167if __name__ == '__main__':
168    unittest.main(verbosity=2, exit=2)
169