-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
test_findreplace.py
334 lines (274 loc) · 10.1 KB
/
test_findreplace.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
#
"""
Tests for pathmanager.py
"""
# Standard library imports
import os
# Test library imports
import pytest
from qtpy.QtCore import Qt
from qtpy.QtGui import QFont, QTextCursor
from qtpy.QtWidgets import QVBoxLayout, QWidget
# Local imports
from spyder.plugins.editor.widgets.codeeditor import CodeEditor
from spyder.widgets.findreplace import FindReplace
from spyder.utils.stylesheet import APP_STYLESHEET
@pytest.fixture
def findreplace_editor(qtbot, request):
"""Set up editor with FindReplace widget."""
# Widget to show together the two other below
widget = QWidget()
qtbot.addWidget(widget)
widget.setStyleSheet(str(APP_STYLESHEET))
# Widget's layout
layout = QVBoxLayout()
widget.setLayout(layout)
# Code editor
editor = CodeEditor(parent=widget)
editor.setup_editor(
color_scheme='spyder/dark',
font=QFont("Courier New", 10)
)
widget.editor = editor
layout.addWidget(editor)
# Find replace
findreplace = FindReplace(editor, enable_replace=True)
findreplace.set_editor(editor)
widget.findreplace = findreplace
layout.addWidget(findreplace)
# Resize widget and show
widget.resize(900, 360)
widget.show()
return widget
def test_findreplace_multiline_replacement(findreplace_editor, qtbot):
"""
Test find replace widget for multiline regex replacements
See: spyder-ide/spyder#2675
"""
expected = '\n\nhello world!\n\n'
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
editor.set_text('\n\nhello\n\n\nworld!\n\n')
findreplace.show_replace()
findreplace.re_button.setChecked(True)
edit = findreplace.search_text.lineEdit()
edit.clear()
edit.setText('\\n\\n\\n')
findreplace.replace_text.setCurrentText(' ')
qtbot.wait(1000)
findreplace.replace_find_all()
qtbot.wait(1000)
assert editor.toPlainText() == expected
def test_replace_selection(findreplace_editor, qtbot):
"""Test find replace final selection in the editor.
For further information see spyder-ide/spyder#12745
"""
expected = 'Spyder is greit!\nSpyder is greit!'
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
editor.set_text('Spyder as great!\nSpyder as great!')
editor.select_lines(0, 2)
findreplace.show_replace()
edit = findreplace.search_text.lineEdit()
edit.clear()
edit.setText('a')
findreplace.replace_text.setCurrentText('i')
findreplace.replace_find_selection()
qtbot.wait(1000)
assert editor.get_selected_text() == expected
assert len(editor.get_selected_text()) == len(expected)
def test_replace_all(findreplace_editor, qtbot):
"""
Test find replace final selection in the editor.
Regression test for spyder-ide/spyder#20403
"""
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
findreplace.show_replace()
findreplace.search_text.setCurrentText('a')
findreplace.replace_text.setCurrentText('x')
# Replace all
editor.set_text('a\naa')
expected = 'x\nxx'
qtbot.wait(500)
findreplace.replace_find_all()
qtbot.wait(500)
assert editor.toPlainText() == expected
# Replace all with whole word matching
editor.set_text('a\naa')
expected = 'x\naa'
qtbot.wait(500)
qtbot.mouseClick(findreplace.words_button, Qt.LeftButton)
findreplace.replace_find_all()
qtbot.wait(500)
qtbot.mouseClick(findreplace.words_button, Qt.LeftButton)
assert editor.toPlainText() == expected
findreplace.search_text.setCurrentText(r'a(\d+)a')
findreplace.replace_text.setCurrentText(r'b\1b')
# Replace all with regex
editor.set_text('a123a\nabca')
expected = 'b123b\nabca'
qtbot.wait(500)
qtbot.mouseClick(findreplace.re_button, Qt.LeftButton)
findreplace.replace_find_all()
qtbot.wait(500)
qtbot.mouseClick(findreplace.re_button, Qt.LeftButton)
assert editor.toPlainText() == expected
def test_messages_action(findreplace_editor, qtbot):
"""
Test that we set the right icons and tooltips on messages_action.
"""
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
editor.set_text('Spyder as great!')
# Assert messages_action is not visible by default
assert not findreplace.messages_action.isVisible()
# Search for missing text
edit = findreplace.search_text.lineEdit()
edit.clear()
qtbot.keyClicks(edit, 'foo')
assert not findreplace.number_matches_text.isVisible()
assert findreplace.messages_action.icon().cacheKey() == \
findreplace.no_matches_icon.cacheKey()
assert findreplace.messages_action.toolTip() == \
findreplace.TOOLTIP['no_matches']
# Assert messages_action is not visible when there's no text
edit.selectAll()
qtbot.keyClick(edit, Qt.Key_Delete)
assert not findreplace.messages_action.isVisible()
# Search with wrong regexp
msg = ': nothing to repeat at position 0'
edit.clear()
findreplace.re_button.setChecked(True)
qtbot.keyClicks(edit, '?')
assert not findreplace.number_matches_text.isVisible()
assert findreplace.messages_action.icon().cacheKey() == \
findreplace.error_icon.cacheKey()
assert findreplace.messages_action.toolTip() == \
findreplace.TOOLTIP['regexp_error'] + msg
# Search for available text
edit.clear()
qtbot.keyClicks(edit, 'great')
qtbot.wait(500)
assert not findreplace.messages_action.isVisible()
assert findreplace.number_matches_text.isVisible()
assert findreplace.number_matches_text.text() == '1 of 1'
def test_replace_text_button(findreplace_editor, qtbot):
"""
Test that replace_text_button is checked/unchecked under different
scenarios.
"""
findreplace = findreplace_editor.findreplace
findreplace.hide()
# Show replace row directly
findreplace.show(hide_replace=False)
qtbot.wait(500)
assert findreplace.replace_text_button.isChecked()
# Hide with the close button and show find row only
qtbot.mouseClick(findreplace.close_button, Qt.LeftButton)
findreplace.show(hide_replace=True)
qtbot.wait(500)
assert not findreplace.replace_text_button.isChecked()
# Show both find and replace rows and then only the find one
findreplace.show(hide_replace=False)
qtbot.wait(500)
findreplace.show(hide_replace=True)
assert not findreplace.replace_text_button.isChecked()
def test_update_matches(findreplace_editor, qtbot):
"""
Test that we update the total number of matches when the editor text has
changed.
"""
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
editor.set_text('foo\nfoo\n')
# Search for present text
edit = findreplace.search_text.lineEdit()
edit.clear()
edit.setFocus()
qtbot.keyClicks(edit, 'foo')
assert findreplace.number_matches_text.text() == '1 of 2'
# Add the same text and check matches were updated
editor.setFocus()
cursor = editor.textCursor()
cursor.movePosition(QTextCursor.End)
editor.setTextCursor(cursor)
qtbot.keyClicks(editor, 'foo')
qtbot.wait(500)
assert findreplace.number_matches_text.text() == '3 matches'
# Assert found results are highlighted in the editor
assert len(editor.found_results) == 3
# Check we don't update matches when the widget is hidden
findreplace.hide()
qtbot.wait(500)
qtbot.keyClick(editor, Qt.Key_Return)
qtbot.keyClicks(editor, 'foo')
qtbot.wait(500)
assert findreplace.number_matches_text.text() == '3 matches'
def test_clear_action(findreplace_editor, qtbot):
"""
Test that clear_action in the search_text line edit is working as expected.
"""
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
clear_action = findreplace.search_text.lineEdit().clear_action
editor.set_text('foo\nfoo\n')
# clear_action should not be visible when the widget is shown
assert not clear_action.isVisible()
# Search for some existing text and check clear_action is visible
edit = findreplace.search_text.lineEdit()
edit.setFocus()
qtbot.keyClicks(edit, 'foo')
assert clear_action.isVisible()
qtbot.wait(500)
# Trigger clear_action and assert it's hidden, along with
# number_matches_text
clear_action.triggered.emit()
assert not clear_action.isVisible()
assert not findreplace.number_matches_text.isVisible()
# Search for unexisting text
edit.clear()
edit.setFocus()
qtbot.keyClicks(edit, 'bar')
qtbot.wait(500)
assert findreplace.messages_action.isVisible()
# Trigger clear_action and assert messages_action is hidden
clear_action.triggered.emit()
qtbot.wait(500)
assert not findreplace.messages_action.isVisible()
def test_replace_all_backslash(findreplace_editor, qtbot):
"""
Test that we can replace all occurrences of a certain text with an
expression that contains backslashes.
This is a regression test for issue spyder-ide/spyder#21007
"""
editor = findreplace_editor.editor
findreplace = findreplace_editor.findreplace
# Replace all instances of | by \
editor.set_text("a | b | c")
edit = findreplace.search_text.lineEdit()
edit.setFocus()
qtbot.keyClicks(edit, '|')
findreplace.replace_text_button.setChecked(True)
findreplace.replace_text.setCurrentText('\\')
qtbot.wait(100)
findreplace.replace_find_all()
assert editor.toPlainText() == "a \\ b \\ c"
# Clear editor and edit
editor.selectAll()
qtbot.keyClick(edit, Qt.Key_Delete)
edit.clear()
# Replace all instances of \alpha by \beta
editor.set_text("\\Psi\n\\alpha\n\\beta\n\\alpha")
edit.setFocus()
qtbot.keyClicks(edit, "\\alpha")
findreplace.replace_text.setCurrentText('\\beta')
qtbot.wait(100)
findreplace.replace_find_all()
assert editor.toPlainText() == "\\Psi\n\\beta\n\\beta\n\\beta"
if __name__ == "__main__":
pytest.main([os.path.basename(__file__)])