diff options
Diffstat (limited to 'Lib/idlelib/idle_test/test_squeezer.py')
-rw-r--r-- | Lib/idlelib/idle_test/test_squeezer.py | 476 |
1 files changed, 0 insertions, 476 deletions
diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py deleted file mode 100644 index 1af2ce8..0000000 --- a/Lib/idlelib/idle_test/test_squeezer.py +++ /dev/null @@ -1,476 +0,0 @@ -"Test squeezer, coverage 95%" - -from collections import namedtuple -from textwrap import dedent -from tkinter import Text, Tk -import unittest -from unittest.mock import Mock, NonCallableMagicMock, patch, sentinel, ANY -from test.support import requires - -from idlelib.config import idleConf -from idlelib.squeezer import count_lines_with_wrapping, ExpandingButton, \ - Squeezer -from idlelib import macosx -from idlelib.textview import view_text -from idlelib.tooltip import Hovertip -from idlelib.pyshell import PyShell - - -SENTINEL_VALUE = sentinel.SENTINEL_VALUE - - -def get_test_tk_root(test_instance): - """Helper for tests: Create a root Tk object.""" - requires('gui') - root = Tk() - root.withdraw() - - def cleanup_root(): - root.update_idletasks() - root.destroy() - test_instance.addCleanup(cleanup_root) - - return root - - -class CountLinesTest(unittest.TestCase): - """Tests for the count_lines_with_wrapping function.""" - def check(self, expected, text, linewidth): - return self.assertEqual( - expected, - count_lines_with_wrapping(text, linewidth), - ) - - def test_count_empty(self): - """Test with an empty string.""" - self.assertEqual(count_lines_with_wrapping(""), 0) - - def test_count_begins_with_empty_line(self): - """Test with a string which begins with a newline.""" - self.assertEqual(count_lines_with_wrapping("\ntext"), 2) - - def test_count_ends_with_empty_line(self): - """Test with a string which ends with a newline.""" - self.assertEqual(count_lines_with_wrapping("text\n"), 1) - - def test_count_several_lines(self): - """Test with several lines of text.""" - self.assertEqual(count_lines_with_wrapping("1\n2\n3\n"), 3) - - def test_empty_lines(self): - self.check(expected=1, text='\n', linewidth=80) - self.check(expected=2, text='\n\n', linewidth=80) - self.check(expected=10, text='\n' * 10, linewidth=80) - - def test_long_line(self): - self.check(expected=3, text='a' * 200, linewidth=80) - self.check(expected=3, text='a' * 200 + '\n', linewidth=80) - - def test_several_lines_different_lengths(self): - text = dedent("""\ - 13 characters - 43 is the number of characters on this line - - 7 chars - 13 characters""") - self.check(expected=5, text=text, linewidth=80) - self.check(expected=5, text=text + '\n', linewidth=80) - self.check(expected=6, text=text, linewidth=40) - self.check(expected=7, text=text, linewidth=20) - self.check(expected=11, text=text, linewidth=10) - - -class SqueezerTest(unittest.TestCase): - """Tests for the Squeezer class.""" - def make_mock_editor_window(self, with_text_widget=False): - """Create a mock EditorWindow instance.""" - editwin = NonCallableMagicMock() - editwin.width = 80 - - if with_text_widget: - editwin.root = get_test_tk_root(self) - text_widget = self.make_text_widget(root=editwin.root) - editwin.text = editwin.per.bottom = text_widget - - return editwin - - def make_squeezer_instance(self, editor_window=None): - """Create an actual Squeezer instance with a mock EditorWindow.""" - if editor_window is None: - editor_window = self.make_mock_editor_window() - squeezer = Squeezer(editor_window) - return squeezer - - def make_text_widget(self, root=None): - if root is None: - root = get_test_tk_root(self) - text_widget = Text(root) - text_widget["font"] = ('Courier', 10) - text_widget.mark_set("iomark", "1.0") - return text_widget - - def set_idleconf_option_with_cleanup(self, configType, section, option, value): - prev_val = idleConf.GetOption(configType, section, option) - idleConf.SetOption(configType, section, option, value) - self.addCleanup(idleConf.SetOption, - configType, section, option, prev_val) - - def test_count_lines(self): - """Test Squeezer.count_lines() with various inputs.""" - editwin = self.make_mock_editor_window() - squeezer = self.make_squeezer_instance(editwin) - - for text_code, line_width, expected in [ - (r"'\n'", 80, 1), - (r"'\n' * 3", 80, 3), - (r"'a' * 40 + '\n'", 80, 1), - (r"'a' * 80 + '\n'", 80, 1), - (r"'a' * 200 + '\n'", 80, 3), - (r"'aa\t' * 20", 80, 2), - (r"'aa\t' * 21", 80, 3), - (r"'aa\t' * 20", 40, 4), - ]: - with self.subTest(text_code=text_code, - line_width=line_width, - expected=expected): - text = eval(text_code) - with patch.object(editwin, 'width', line_width): - self.assertEqual(squeezer.count_lines(text), expected) - - def test_init(self): - """Test the creation of Squeezer instances.""" - editwin = self.make_mock_editor_window() - squeezer = self.make_squeezer_instance(editwin) - self.assertIs(squeezer.editwin, editwin) - self.assertEqual(squeezer.expandingbuttons, []) - - def test_write_no_tags(self): - """Test Squeezer's overriding of the EditorWindow's write() method.""" - editwin = self.make_mock_editor_window() - for text in ['', 'TEXT', 'LONG TEXT' * 1000, 'MANY_LINES\n' * 100]: - editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE) - squeezer = self.make_squeezer_instance(editwin) - - self.assertEqual(squeezer.editwin.write(text, ()), SENTINEL_VALUE) - self.assertEqual(orig_write.call_count, 1) - orig_write.assert_called_with(text, ()) - self.assertEqual(len(squeezer.expandingbuttons), 0) - - def test_write_not_stdout(self): - """Test Squeezer's overriding of the EditorWindow's write() method.""" - for text in ['', 'TEXT', 'LONG TEXT' * 1000, 'MANY_LINES\n' * 100]: - editwin = self.make_mock_editor_window() - editwin.write.return_value = SENTINEL_VALUE - orig_write = editwin.write - squeezer = self.make_squeezer_instance(editwin) - - self.assertEqual(squeezer.editwin.write(text, "stderr"), - SENTINEL_VALUE) - self.assertEqual(orig_write.call_count, 1) - orig_write.assert_called_with(text, "stderr") - self.assertEqual(len(squeezer.expandingbuttons), 0) - - def test_write_stdout(self): - """Test Squeezer's overriding of the EditorWindow's write() method.""" - editwin = self.make_mock_editor_window() - - for text in ['', 'TEXT']: - editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE) - squeezer = self.make_squeezer_instance(editwin) - squeezer.auto_squeeze_min_lines = 50 - - self.assertEqual(squeezer.editwin.write(text, "stdout"), - SENTINEL_VALUE) - self.assertEqual(orig_write.call_count, 1) - orig_write.assert_called_with(text, "stdout") - self.assertEqual(len(squeezer.expandingbuttons), 0) - - for text in ['LONG TEXT' * 1000, 'MANY_LINES\n' * 100]: - editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE) - squeezer = self.make_squeezer_instance(editwin) - squeezer.auto_squeeze_min_lines = 50 - - self.assertEqual(squeezer.editwin.write(text, "stdout"), None) - self.assertEqual(orig_write.call_count, 0) - self.assertEqual(len(squeezer.expandingbuttons), 1) - - def test_auto_squeeze(self): - """Test that the auto-squeezing creates an ExpandingButton properly.""" - editwin = self.make_mock_editor_window(with_text_widget=True) - text_widget = editwin.text - squeezer = self.make_squeezer_instance(editwin) - squeezer.auto_squeeze_min_lines = 5 - squeezer.count_lines = Mock(return_value=6) - - editwin.write('TEXT\n'*6, "stdout") - self.assertEqual(text_widget.get('1.0', 'end'), '\n') - self.assertEqual(len(squeezer.expandingbuttons), 1) - - def test_squeeze_current_text_event(self): - """Test the squeeze_current_text event.""" - # Squeezing text should work for both stdout and stderr. - for tag_name in ["stdout", "stderr"]: - editwin = self.make_mock_editor_window(with_text_widget=True) - text_widget = editwin.text - squeezer = self.make_squeezer_instance(editwin) - squeezer.count_lines = Mock(return_value=6) - - # Prepare some text in the Text widget. - text_widget.insert("1.0", "SOME\nTEXT\n", tag_name) - text_widget.mark_set("insert", "1.0") - self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n') - - self.assertEqual(len(squeezer.expandingbuttons), 0) - - # Test squeezing the current text. - retval = squeezer.squeeze_current_text_event(event=Mock()) - self.assertEqual(retval, "break") - self.assertEqual(text_widget.get('1.0', 'end'), '\n\n') - self.assertEqual(len(squeezer.expandingbuttons), 1) - self.assertEqual(squeezer.expandingbuttons[0].s, 'SOME\nTEXT') - - # Test that expanding the squeezed text works and afterwards - # the Text widget contains the original text. - squeezer.expandingbuttons[0].expand(event=Mock()) - self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n') - self.assertEqual(len(squeezer.expandingbuttons), 0) - - def test_squeeze_current_text_event_no_allowed_tags(self): - """Test that the event doesn't squeeze text without a relevant tag.""" - editwin = self.make_mock_editor_window(with_text_widget=True) - text_widget = editwin.text - squeezer = self.make_squeezer_instance(editwin) - squeezer.count_lines = Mock(return_value=6) - - # Prepare some text in the Text widget. - text_widget.insert("1.0", "SOME\nTEXT\n", "TAG") - text_widget.mark_set("insert", "1.0") - self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n') - - self.assertEqual(len(squeezer.expandingbuttons), 0) - - # Test squeezing the current text. - retval = squeezer.squeeze_current_text_event(event=Mock()) - self.assertEqual(retval, "break") - self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n') - self.assertEqual(len(squeezer.expandingbuttons), 0) - - def test_squeeze_text_before_existing_squeezed_text(self): - """Test squeezing text before existing squeezed text.""" - editwin = self.make_mock_editor_window(with_text_widget=True) - text_widget = editwin.text - squeezer = self.make_squeezer_instance(editwin) - squeezer.count_lines = Mock(return_value=6) - - # Prepare some text in the Text widget and squeeze it. - text_widget.insert("1.0", "SOME\nTEXT\n", "stdout") - text_widget.mark_set("insert", "1.0") - squeezer.squeeze_current_text_event(event=Mock()) - self.assertEqual(len(squeezer.expandingbuttons), 1) - - # Test squeezing the current text. - text_widget.insert("1.0", "MORE\nSTUFF\n", "stdout") - text_widget.mark_set("insert", "1.0") - retval = squeezer.squeeze_current_text_event(event=Mock()) - self.assertEqual(retval, "break") - self.assertEqual(text_widget.get('1.0', 'end'), '\n\n\n') - self.assertEqual(len(squeezer.expandingbuttons), 2) - self.assertTrue(text_widget.compare( - squeezer.expandingbuttons[0], - '<', - squeezer.expandingbuttons[1], - )) - - def test_reload(self): - """Test the reload() class-method.""" - editwin = self.make_mock_editor_window(with_text_widget=True) - squeezer = self.make_squeezer_instance(editwin) - - orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines - - # Increase auto-squeeze-min-lines. - new_auto_squeeze_min_lines = orig_auto_squeeze_min_lines + 10 - self.set_idleconf_option_with_cleanup( - 'main', 'PyShell', 'auto-squeeze-min-lines', - str(new_auto_squeeze_min_lines)) - - Squeezer.reload() - self.assertEqual(squeezer.auto_squeeze_min_lines, - new_auto_squeeze_min_lines) - - def test_reload_no_squeezer_instances(self): - """Test that Squeezer.reload() runs without any instances existing.""" - Squeezer.reload() - - -class ExpandingButtonTest(unittest.TestCase): - """Tests for the ExpandingButton class.""" - # In these tests the squeezer instance is a mock, but actual tkinter - # Text and Button instances are created. - def make_mock_squeezer(self): - """Helper for tests: Create a mock Squeezer object.""" - root = get_test_tk_root(self) - squeezer = Mock() - squeezer.editwin.text = Text(root) - - # Set default values for the configuration settings. - squeezer.auto_squeeze_min_lines = 50 - return squeezer - - @patch('idlelib.squeezer.Hovertip', autospec=Hovertip) - def test_init(self, MockHovertip): - """Test the simplest creation of an ExpandingButton.""" - squeezer = self.make_mock_squeezer() - text_widget = squeezer.editwin.text - - expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer) - self.assertEqual(expandingbutton.s, 'TEXT') - - # Check that the underlying tkinter.Button is properly configured. - self.assertEqual(expandingbutton.master, text_widget) - self.assertTrue('50 lines' in expandingbutton.cget('text')) - - # Check that the text widget still contains no text. - self.assertEqual(text_widget.get('1.0', 'end'), '\n') - - # Check that the mouse events are bound. - self.assertIn('<Double-Button-1>', expandingbutton.bind()) - right_button_code = '<Button-%s>' % ('2' if macosx.isAquaTk() else '3') - self.assertIn(right_button_code, expandingbutton.bind()) - - # Check that ToolTip was called once, with appropriate values. - self.assertEqual(MockHovertip.call_count, 1) - MockHovertip.assert_called_with(expandingbutton, ANY, hover_delay=ANY) - - # Check that 'right-click' appears in the tooltip text. - tooltip_text = MockHovertip.call_args[0][1] - self.assertIn('right-click', tooltip_text.lower()) - - def test_expand(self): - """Test the expand event.""" - squeezer = self.make_mock_squeezer() - expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer) - - # Insert the button into the text widget - # (this is normally done by the Squeezer class). - text_widget = expandingbutton.text - text_widget.window_create("1.0", window=expandingbutton) - - # Set base_text to the text widget, so that changes are actually - # made to it (by ExpandingButton) and we can inspect these - # changes afterwards. - expandingbutton.base_text = expandingbutton.text - - # trigger the expand event - retval = expandingbutton.expand(event=Mock()) - self.assertEqual(retval, None) - - # Check that the text was inserted into the text widget. - self.assertEqual(text_widget.get('1.0', 'end'), 'TEXT\n') - - # Check that the 'TAGS' tag was set on the inserted text. - text_end_index = text_widget.index('end-1c') - self.assertEqual(text_widget.get('1.0', text_end_index), 'TEXT') - self.assertEqual(text_widget.tag_nextrange('TAGS', '1.0'), - ('1.0', text_end_index)) - - # Check that the button removed itself from squeezer.expandingbuttons. - self.assertEqual(squeezer.expandingbuttons.remove.call_count, 1) - squeezer.expandingbuttons.remove.assert_called_with(expandingbutton) - - def test_expand_dangerous_oupput(self): - """Test that expanding very long output asks user for confirmation.""" - squeezer = self.make_mock_squeezer() - text = 'a' * 10**5 - expandingbutton = ExpandingButton(text, 'TAGS', 50, squeezer) - expandingbutton.set_is_dangerous() - self.assertTrue(expandingbutton.is_dangerous) - - # Insert the button into the text widget - # (this is normally done by the Squeezer class). - text_widget = expandingbutton.text - text_widget.window_create("1.0", window=expandingbutton) - - # Set base_text to the text widget, so that changes are actually - # made to it (by ExpandingButton) and we can inspect these - # changes afterwards. - expandingbutton.base_text = expandingbutton.text - - # Patch the message box module to always return False. - with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox: - mock_msgbox.askokcancel.return_value = False - mock_msgbox.askyesno.return_value = False - # Trigger the expand event. - retval = expandingbutton.expand(event=Mock()) - - # Check that the event chain was broken and no text was inserted. - self.assertEqual(retval, 'break') - self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), '') - - # Patch the message box module to always return True. - with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox: - mock_msgbox.askokcancel.return_value = True - mock_msgbox.askyesno.return_value = True - # Trigger the expand event. - retval = expandingbutton.expand(event=Mock()) - - # Check that the event chain wasn't broken and the text was inserted. - self.assertEqual(retval, None) - self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), text) - - def test_copy(self): - """Test the copy event.""" - # Testing with the actual clipboard proved problematic, so this - # test replaces the clipboard manipulation functions with mocks - # and checks that they are called appropriately. - squeezer = self.make_mock_squeezer() - expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer) - expandingbutton.clipboard_clear = Mock() - expandingbutton.clipboard_append = Mock() - - # Trigger the copy event. - retval = expandingbutton.copy(event=Mock()) - self.assertEqual(retval, None) - - # Vheck that the expanding button called clipboard_clear() and - # clipboard_append('TEXT') once each. - self.assertEqual(expandingbutton.clipboard_clear.call_count, 1) - self.assertEqual(expandingbutton.clipboard_append.call_count, 1) - expandingbutton.clipboard_append.assert_called_with('TEXT') - - def test_view(self): - """Test the view event.""" - squeezer = self.make_mock_squeezer() - expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer) - expandingbutton.selection_own = Mock() - - with patch('idlelib.squeezer.view_text', autospec=view_text)\ - as mock_view_text: - # Trigger the view event. - expandingbutton.view(event=Mock()) - - # Check that the expanding button called view_text. - self.assertEqual(mock_view_text.call_count, 1) - - # Check that the proper text was passed. - self.assertEqual(mock_view_text.call_args[0][2], 'TEXT') - - def test_rmenu(self): - """Test the context menu.""" - squeezer = self.make_mock_squeezer() - expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer) - with patch('tkinter.Menu') as mock_Menu: - mock_menu = Mock() - mock_Menu.return_value = mock_menu - mock_event = Mock() - mock_event.x = 10 - mock_event.y = 10 - expandingbutton.context_menu_event(event=mock_event) - self.assertEqual(mock_menu.add_command.call_count, - len(expandingbutton.rmenu_specs)) - for label, *data in expandingbutton.rmenu_specs: - mock_menu.add_command.assert_any_call(label=label, command=ANY) - - -if __name__ == '__main__': - unittest.main(verbosity=2) |