Skip to content

Commit

Permalink
Merge from 3.x: PR #4027
Browse files Browse the repository at this point in the history
Fixes #4010
  • Loading branch information
ccordoba12 committed Feb 25, 2017
2 parents 368df40 + fcc2deb commit 823df7b
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 34 deletions.
7 changes: 5 additions & 2 deletions spyder/widgets/findreplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ def __init__(self, parent, enable_replace=False):
replace_with = QLabel(_("Replace with:"))
self.replace_text = PatternComboBox(self, adjust_to_minimum=False,
tip=_('Replace string'))

self.replace_text.valid.connect(
lambda _: self.replace_find(focus_replace_text=True))
self.replace_button = create_toolbutton(self,
text=_('Replace/find'),
icon=ima.icon('DialogApplyButton'),
Expand Down Expand Up @@ -344,7 +345,7 @@ def find(self, changed=True, forward=True,
return found

@Slot()
def replace_find(self):
def replace_find(self, focus_replace_text=False):
"""Replace and find"""
if (self.editor is not None):
replace_text = to_text_string(self.replace_text.currentText())
Expand Down Expand Up @@ -419,3 +420,5 @@ def replace_find(self):
self.all_check.setCheckState(Qt.Unchecked)
if cursor is not None:
cursor.endEditBlock()
if focus_replace_text:
self.replace_text.setFocus()
Empty file.
File renamed without changes.
128 changes: 96 additions & 32 deletions spyder/widgets/tests/test_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,72 +8,136 @@
Tests for editor.py
"""

# Standard library imports
try:
from unittest.mock import Mock
except ImportError:
from mock import Mock # Python 2

# Third party imports
import pytest
from qtpy.QtCore import Qt

# Local imports
from spyder.utils.fixtures import setup_editor
from spyder.widgets.editor import EditorStack
from spyder.widgets.findreplace import FindReplace

# Qt Test Fixtures
#--------------------------------
@pytest.fixture
def base_editor_bot(qtbot):
editor_stack = EditorStack(None, [])
editor_stack.set_introspector(Mock())
editor_stack.set_find_widget(Mock())
editor_stack.set_io_actions(Mock(), Mock(), Mock(), Mock())
return editor_stack, qtbot

@pytest.fixture
def editor_bot(base_editor_bot):
"""
Set up EditorStack with CodeEditor containing some Python code.
The cursor is at the empty line below the code.
Returns tuple with EditorStack and CodeEditor.
"""
editor_stack, qtbot = base_editor_bot
text = ('a = 1\n'
'print(a)\n'
'\n'
'x = 2') # a newline is added at end
finfo = editor_stack.new('foo.py', 'utf-8', text)
qtbot.addWidget(editor_stack)
return editor_stack, finfo.editor, qtbot

@pytest.fixture
def editor_find_replace_bot(base_editor_bot):
editor_stack, qtbot = base_editor_bot
text = ('spam bacon\n'
'spam sausage\n'
'spam egg')
finfo = editor_stack.new('spam.py', 'utf-8', text)
find_replace = FindReplace(None, enable_replace=True)
editor_stack.set_find_widget(find_replace)
find_replace.set_editor(finfo.editor)
qtbot.addWidget(editor_stack)
return editor_stack, finfo.editor, find_replace, qtbot

def test_run_top_line(qtbot):
editorStack, editor = setup_editor(qtbot)
# Tests
#-------------------------------
def test_run_top_line(editor_bot):
editor_stack, editor, qtbot = editor_bot
editor.go_to_line(1) # line number is one based
editor.move_cursor(3)
with qtbot.waitSignal(editorStack.exec_in_extconsole) as blocker:
editorStack.run_selection()
with qtbot.waitSignal(editor_stack.exec_in_extconsole) as blocker:
editor_stack.run_selection()
assert blocker.signal_triggered
assert blocker.args[0] == 'a = 1'
# check cursor moves to start of next line; note line number is zero based
assert editor.get_cursor_line_column() == (1, 0)
assert editor.get_cursor_line_column() == (1, 0)

def test_run_last_nonempty_line(qtbot):
editorStack, editor = setup_editor(qtbot)
def test_run_last_nonempty_line(editor_bot):
editor_stack, editor, qtbot = editor_bot
editor.go_to_line(4)
with qtbot.waitSignal(editorStack.exec_in_extconsole) as blocker:
editorStack.run_selection()
with qtbot.waitSignal(editor_stack.exec_in_extconsole) as blocker:
editor_stack.run_selection()
assert blocker.signal_triggered
assert blocker.args[0] == 'x = 2'
assert editor.get_cursor_line_column() == (4, 0) # check cursor moves down

def test_run_empty_line_in_middle(qtbot):
editorStack, editor = setup_editor(qtbot)
def test_run_empty_line_in_middle(editor_bot):
editor_stack, editor, qtbot = editor_bot
editor.go_to_line(3)
with qtbot.assertNotEmitted(editorStack.exec_in_extconsole):
editorStack.run_selection()
with qtbot.assertNotEmitted(editor_stack.exec_in_extconsole):
editor_stack.run_selection()
assert editor.get_cursor_line_column() == (3, 0) # check cursor moves down

def test_run_last_line_when_empty(editor_bot):
editor_stack, editor, qtbot = editor_bot
with qtbot.assertNotEmitted(editor_stack.exec_in_extconsole):
editor_stack.run_selection()
# check cursor doesn't move
assert editor.get_cursor_line_column() == (4, 0)

def test_run_last_line_when_empty(qtbot):
editorStack, editor = setup_editor(qtbot)
with qtbot.assertNotEmitted(editorStack.exec_in_extconsole):
editorStack.run_selection()
assert editor.get_cursor_line_column() == (4, 0) # check cursor doesn't move

def test_run_last_line_when_nonempty(qtbot):
editorStack, editor = setup_editor(qtbot)
def test_run_last_line_when_nonempty(editor_bot):
editor_stack, editor, qtbot = editor_bot
editor.stdkey_backspace() # delete empty line at end
old_text = editor.toPlainText()
with qtbot.waitSignal(editorStack.exec_in_extconsole) as blocker:
editorStack.run_selection()
with qtbot.waitSignal(editor_stack.exec_in_extconsole) as blocker:
editor_stack.run_selection()
assert blocker.signal_triggered
assert blocker.args[0] == 'x = 2'
expected_new_text = old_text + editor.get_line_separator()
assert editor.toPlainText() == expected_new_text # check blank line got added
# check blank line got added
assert editor.toPlainText() == expected_new_text
assert editor.get_cursor_line_column() == (4, 0) # check cursor moves down

def test_find_replace_case_sensitive(qtbot):
editorStack, editor = setup_editor(qtbot)
editorStack.find_widget.case_button.setChecked(True)
editor_stack, editor = setup_editor(qtbot)
editor_stack.find_widget.case_button.setChecked(True)
text = ' test \nTEST \nTest \ntesT '
editor.set_text(text)
editorStack.find_widget.search_text.add_text('test')
editorStack.find_widget.replace_text.add_text('pass')
editorStack.find_widget.replace_find()
editorStack.find_widget.replace_find()
editorStack.find_widget.replace_find()
editorStack.find_widget.replace_find()
editor_stack.find_widget.search_text.add_text('test')
editor_stack.find_widget.replace_text.add_text('pass')
editor_stack.find_widget.replace_find()
editor_stack.find_widget.replace_find()
editor_stack.find_widget.replace_find()
editor_stack.find_widget.replace_find()
editor_text = editor.toPlainText()
assert editor_text == ' pass \nTEST \nTest \ntesT '

def test_replace_current_selected_line(editor_find_replace_bot):
editor_stack, editor, finder, qtbot = editor_find_replace_bot
expected_new_text = ('ham bacon\n'
'spam sausage\n'
'spam egg')
old_text = editor.toPlainText()
finder.show()
finder.show_replace()
qtbot.keyClicks(finder.search_text, 'spam')
qtbot.keyClicks(finder.replace_text, 'ham')
qtbot.keyPress(finder.replace_text, Qt.Key_Return)
assert editor.toPlainText()[0:-1] == expected_new_text


if __name__ == "__main__":
pytest.main()

0 comments on commit 823df7b

Please sign in to comment.