Skip to content

Commit 49fdf1b

Browse files
Increase unit tests
1 parent de8c31c commit 49fdf1b

File tree

10 files changed

+200
-41
lines changed

10 files changed

+200
-41
lines changed

src/robotide/editor/contentassist.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from wx.lib.filebrowsebutton import FileBrowseButton
2020
from os.path import relpath, dirname, isdir
2121

22+
from .gridbase import GridEditor
2223
from .. import context, utils
2324
from ..context import IS_MAC, IS_WINDOWS, IS_WX_410_OR_HIGHER
2425
from ..namespace.suggesters import SuggestionSource
@@ -74,6 +75,8 @@ def __init__(self, suggestion_source, language='En', **kw):
7475
@staticmethod
7576
def _get_auto_suggestion_config():
7677
from robotide.context import APP
78+
if not APP:
79+
return True
7780
settings = APP.settings['Grid']
7881
return settings.get(_AUTO_SUGGESTION_CFG_KEY, False)
7982

@@ -540,7 +543,8 @@ def content_assist_for(self, value, row=None):
540543
self._choices = self._suggestions.get_for(value, row=row)
541544
if not self._choices:
542545
self._list.ClearAll()
543-
self._parent.hide()
546+
if not isinstance(self._parent, GridEditor):
547+
self._parent.hide()
544548
return False
545549
self._choices = list(set([c for c in self._choices if c is not None]))
546550
print(f"DEBUG: contentassist.py ContentAssistPopup content_assist_for CALL POPULATE Choices={self._choices}")

src/robotide/editor/texteditor.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,10 @@ def _apply_txt_changes_to_model(self):
609609
return True
610610

611611
def is_focused(self):
612-
return self.notebook.current_page_title == self.title
612+
try:
613+
return self.notebook.current_page_title == self.title
614+
except AttributeError:
615+
return self._editor.is_focused()
613616

614617

615618
class DummyController(WithStepsController):
@@ -1223,8 +1226,12 @@ def on_content_assist(self, event):
12231226
"""
12241227
self.store_position()
12251228
selected = self.source_editor.get_selected_or_near_text()
1226-
print(f"DEBUG: texteditor.py SourceEditor SELECTION selected = {selected} is type={type(selected)}")
1229+
# print(f"DEBUG: texteditor.py SourceEditor SELECTION selected = {selected} is type={type(selected)}")
12271230
self.set_editor_caret_position()
1231+
# Next is for the unit tests when the did not used open to get data:
1232+
if not self._suggestions:
1233+
self._controller_for_context = DummyController(self._data.wrapper_data, self._data.wrapper_data)
1234+
self._suggestions = SuggestionSource(self.plugin, self._controller_for_context)
12281235
self._suggestions.update_from_local(self.words_cache(self.source_editor.GetLineCount()), self.language)
12291236
sugs = set()
12301237
if selected:
@@ -1239,7 +1246,7 @@ def on_content_assist(self, event):
12391246
else:
12401247
found.append(s)
12411248
sugs.update(found)
1242-
print(f"DEBUG: texteditor.py SourceEditor on_content_assist FIRST SUGGESTION suggestions = {sugs}\n")
1249+
# print(f"DEBUG: texteditor.py SourceEditor on_content_assist FIRST SUGGESTION suggestions = {sugs}\n")
12431250
# DEBUG: Here, if sugs is still [], then we can get all words from line and repeat suggestions
12441251
# In another evolution, we can use database of words by frequency (considering future by project db)
12451252
sel = [s for s in selected] if selected else ['']
@@ -1249,7 +1256,7 @@ def on_content_assist(self, event):
12491256
# if sel[0] == '':
12501257
# The case when we call Ctl+Space in empty line o always add suggestions
12511258
# for start in sel:
1252-
print(f"DEBUG: texteditor.py SourceEditor on_content_assist selection = {sel}")
1259+
# print(f"DEBUG: texteditor.py SourceEditor on_content_assist selection = {sel}")
12531260
if sel[0] == '':
12541261
found = []
12551262
for s in self._suggestions.get_suggestions(''):
@@ -1277,15 +1284,15 @@ def on_content_assist(self, event):
12771284
else:
12781285
found.append(s)
12791286
sugs.update(found)
1280-
print(f"DEBUG: texteditor.py SourceEditor on_content_assist VARIABLES SEARCH selection = {sel}\n"
1281-
f"sugs={sugs}")
1287+
# print(f"DEBUG: texteditor.py SourceEditor on_content_assist VARIABLES SEARCH selection = {sel}\n"
1288+
# f"sugs={sugs}")
12821289
if len(sugs) > 0:
12831290
# sugs = [s for s in sugs if s != '']
12841291
if '' in sugs:
12851292
sugs.remove('')
12861293
suggestions=";".join(sorted(sugs))
1287-
print(f"DEBUG: texteditor.py SourceEditor on_content_assist BEFORE SHOW LIST suggestions = {suggestions}\n"
1288-
f" size={len(suggestions)} cache size={len(self._words_cache)}")
1294+
# print(f"DEBUG: texteditor.py SourceEditor on_content_assist BEFORE SHOW LIST suggestions = {suggestions}\n"
1295+
# f" size={len(suggestions)} cache size={len(self._words_cache)}")
12891296
if len(suggestions) > 0: # Consider using contentassist as in Grid Editor
12901297
self.source_editor.AutoCompSetDropRestOfWord(False)
12911298
self.source_editor.AutoCompSetFillUps('=')
@@ -1307,17 +1314,24 @@ def on_content_assist(self, event):
13071314
def open(self, data):
13081315
self.reset()
13091316
self._data = data
1310-
if self._data._doc_language is not None and len(self._data._doc_language) > 0:
1317+
if hasattr(self._data, '_doc_language') and self._data._doc_language is not None and len(self._data._doc_language) > 0:
13111318
self.language = self._data._doc_language
1319+
elif hasattr(self._data, '_language') and self._data._language is not None and len(self._data._language) > 0:
1320+
self.language = self._data._language
13121321
else:
13131322
self.language = ['en']
13141323
# print(f"DEBUG: texteditor.py SourceEditor open ENTER language={self.language}")
13151324
try:
1316-
if isinstance(self._data.wrapper_data, ResourceFileController):
1317-
self._controller_for_context = DummyController(self._data.wrapper_data, self._data.wrapper_data)
1318-
self._suggestions = SuggestionSource(self.plugin, self._controller_for_context)
1325+
if hasattr(self._data, 'wrapper_data'):
1326+
if isinstance(self._data.wrapper_data, ResourceFileController):
1327+
self._controller_for_context = DummyController(self._data.wrapper_data, self._data.wrapper_data)
1328+
else:
1329+
self._controller_for_context = self._data.wrapper_data.tests[0]
1330+
elif isinstance(self._data, ResourceFileController):
1331+
self._controller_for_context = self._data
13191332
else:
1320-
self._suggestions = SuggestionSource(self.plugin, self._data.wrapper_data.tests[0])
1333+
self._controller_for_context = self._data.tests[0]
1334+
self._suggestions = SuggestionSource(self.plugin, self._controller_for_context)
13211335
except IndexError: # It is a new project, no content yet
13221336
self._controller_for_context = DummyController(self._data.wrapper_data, self._data.wrapper_data)
13231337
self._suggestions = SuggestionSource(self.plugin, self._controller_for_context)
@@ -1330,7 +1344,8 @@ def open(self, data):
13301344
self._create_editor_text_control(text=self._stored_text, language=self.language)
13311345
else:
13321346
self.source_editor.set_language(self.language)
1333-
self.source_editor.set_text(self._data.content)
1347+
if hasattr(self._data, 'content'): # Special case for unit test
1348+
self.source_editor.set_text(self._data.content)
13341349
self.set_editor_caret_position()
13351350
self._words_cache.clear()
13361351
self._suggestions.update_from_local(self.words_cache(self.source_editor.GetLineCount()), self.language)
@@ -1472,7 +1487,7 @@ def write_ident(self):
14721487
self.source_editor.WriteText(spaces)
14731488

14741489
def reset(self):
1475-
if self._data and not self._data.wrapper_data.is_dirty:
1490+
if self._data and (hasattr(self._data, 'wrapper_data') and not self._data.wrapper_data.is_dirty):
14761491
self.mark_file_dirty(False)
14771492

14781493
def content_save(self, **args):

src/robotide/lib/robot/utils/normalizing.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@
2222
from .robottypes import is_dict_like, is_unicode
2323

2424

25-
def normalize(string, ignore=(), caseless=True, spaceless=True):
25+
def normalize(string, ignore=(), caseless=True, spaceless=True, suffixless=False):
2626
"""Normalizes given string according to given spec.
2727
2828
By default, string is turned to lower case and all whitespace is removed.
2929
Additional characters can be removed by giving them in ``ignore`` list.
30+
:param
31+
suffixless: the end char is removed if is a symbol
3032
"""
3133
if not string or string == '':
3234
return ''
@@ -44,6 +46,9 @@ def normalize(string, ignore=(), caseless=True, spaceless=True):
4446
for ign in ignore:
4547
if ign in string:
4648
string = string.replace(ign, empty)
49+
if suffixless:
50+
while len(string) > 1 and string[-1] in "=}])":
51+
string = string[:-1]
4752
return string
4853

4954

src/robotide/namespace/namespace.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,12 @@ def _get_default_keywords(self):
135135
return self._lib_cache.get_default_keywords()
136136

137137
def get_suggestions_for(self, controller, start):
138+
if not controller:
139+
return []
138140
datafile = controller.datafile
139141
ctx = self._context_factory.ctx_for_controller(controller)
140142
sugs = set() # self._words_cache or
141-
print(f"DEBUG: namespace.py Namespace get_suggestions_for ENTER start={start} {datafile=} {ctx=} {sugs=}")
143+
# print(f"DEBUG: namespace.py Namespace get_suggestions_for ENTER start={start} {datafile=} {ctx=} {sugs=}")
142144
while start and start[-1] in [']', '}', '=', ',']:
143145
start = start[:-1]
144146
sugs.update(self._get_suggestions_from_hooks(datafile, start))
@@ -147,16 +149,16 @@ def get_suggestions_for(self, controller, start):
147149
sugs.update(self._keyword_suggestions(datafile, start, ctx))
148150
else:
149151
sugs.update(self._variable_suggestions(controller, start, ctx))
150-
print(f"DEBUG: namespace.py Namespace get_suggestions_for BEFORE CONTENT start={start} {sugs=}")
152+
# print(f"DEBUG: namespace.py Namespace get_suggestions_for BEFORE CONTENT start={start} {sugs=}")
151153
if not self._looks_like_variable(start): # Search in content
152154
for v in ['${', '@{', '&{', '%{', '$']:
153155
sugs.update(self._content_suggestions(f'{v}{utils.normalize(start)}'))
154156
else:
155-
sugs.update(self._content_suggestions(start))
156-
print(f"DEBUG: namespace.py Namespace get_suggestions_for FROM CONTENT start={start} {sugs=}")
157+
sugs.update(self._content_suggestions(f'{utils.normalize(start, suffixless=True)}'))
158+
# print(f"DEBUG: namespace.py Namespace get_suggestions_for FROM CONTENT start={start} {sugs=}")
157159
sugs_list = list(sugs)
158160
sugs_list.sort()
159-
print(f"DEBUG: namespace.py Namespace get_suggestions_for RETURN {sugs_list=}")
161+
# print(f"DEBUG: namespace.py Namespace get_suggestions_for RETURN {sugs_list=}")
160162
return sugs_list
161163

162164
def _get_suggestions_from_hooks(self, datafile, start):
@@ -194,12 +196,12 @@ def _content_suggestions(self, start):
194196
sugs.add(v.name)
195197
elif isinstance(v, (VariableInfo, ArgumentInfo)):
196198
if v.name_matches(start):
197-
print(f"DEBUG: namespace.py Namespace _content_suggestions SUGGESTION from VARIABLE {v.name=}")
199+
# print(f"DEBUG: namespace.py Namespace _content_suggestions SUGGESTION from VARIABLE {v.name=}")
198200
sugs.add(v.name)
199201
elif (v.lower().startswith(start.lower()) or v.strip('$&@%{[()]}=').lower()
200202
.startswith(start.strip('$&@%{[()]}=').lower())):
201-
print(f"DEBUG: namespace.py Namespace _content_suggestions SUGGESTION from STRING {v=}"
202-
f"\n v.lower().startswith(start.lower() ={v.lower().startswith(start.lower())}")
203+
# print(f"DEBUG: namespace.py Namespace _content_suggestions SUGGESTION from STRING {v=}"
204+
# f"\n v.lower().startswith(start.lower() ={v.lower().startswith(start.lower())}")
203205
sugs.add(v)
204206
return sugs
205207

@@ -424,8 +426,8 @@ class Dummy:
424426
vars_from_file = VariableFileSetter(store)
425427
resulting_vars = vars_from_file._import_if_needed(varfile_path, args)
426428
except (robotapi.DataError, Exception) as e:
427-
print(f"namespace._VariableStash.set_from_file: unexpected DataError: variable_path {varfile_path} "
428-
f"args {args}")
429+
# print(f"namespace._VariableStash.set_from_file: unexpected DataError: variable_path {varfile_path} "
430+
# f"args {args}")
429431
raise e
430432
for name, value in resulting_vars:
431433
self.set(name, value, varfile_path)

src/robotide/namespace/suggesters.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ def get_suggestions(self, value, row=None):
3939
try:
4040
sugs.update(self._controller.get_local_namespace_for_row(row).get_suggestions(initial))
4141
except AttributeError:
42-
sugs.update(self._controller.get_local_namespace.get_suggestions(initial))
42+
try:
43+
sugs.update(self._controller.get_local_namespace.get_suggestions(initial))
44+
except AttributeError: # For example TestCaseFileController
45+
pass
4346
# return list(sugs)
44-
sugs.update(self._plugin.content_assist_values(initial)) # DEBUG: Remove old functionality when no more needed
47+
if self._plugin:
48+
sugs.update(self._plugin.content_assist_values(initial)) # DEBUG: Remove old functionality when no more needed
4549
print(f"DEBUG: suggesters.py SuggestionSource get_suggestions IN LOOP initial ={initial} len sugs={len(sugs)}")
4650
return list(sugs)
4751

src/robotide/pluginapi/plugin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,10 @@ def get_selected_item(self):
307307
"""
308308
if not self.tree:
309309
return
310-
return self.tree.get_selected_item()
310+
if hasattr(self, 'model'):
311+
return self.tree.get_selected_item() or self.model
312+
else:
313+
return self.tree.get_selected_item()
311314

312315
def content_assist_values(self, value=''):
313316
"""Returns content assist values for currently selected item."""

utest/editor/test_contentassist.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# limitations under the License.
1515

1616
import unittest
17-
from robotide.editor.contentassist import Suggestions
17+
from robotide.editor.contentassist import Suggestions, obtain_bdd_prefixes
1818
from robotide.namespace.suggesters import SuggestionSource, HistorySuggester
1919

2020
class TestSuggestionSources(unittest.TestCase):
@@ -85,6 +85,21 @@ def test_suggestions_for_duplicates(self):
8585
choices = suggestions.get_for('a')
8686
self.assertEqual(choices, ['aarnio', 'fo.aaatio', 'bA.AAATIO'])
8787

88+
def test_bdd_suggestions_en(self):
89+
choices = obtain_bdd_prefixes('En')
90+
self.assertEqual(choices.sort(), ['Given', 'When', 'Then', 'And', 'But'].sort())
91+
92+
def test_bdd_suggestions_pt(self):
93+
choices = obtain_bdd_prefixes('Portuguese')
94+
self.assertEqual(choices.sort(), ['Dado', 'Quando', 'Então', 'E', 'Mas'].sort())
95+
96+
def test_bdd_suggestions_fr(self):
97+
choices = obtain_bdd_prefixes('Fr')
98+
self.assertEqual(choices.sort(), ['Soit', 'Sachant', 'Sachant que', "Sachant qu'",
99+
'Étant donné', 'Étant donné que', "Etant donné qu'",
100+
'Quand', 'Lorsque', "Lorsqu'", 'Alors', 'Donc', 'Et',
101+
'Et que', "Et qu'", 'Mais', 'Mais que', "Mais qu'"].sort())
102+
88103
def _create_mock_source(self):
89104
mock_source = lambda:0
90105
mock_source.request_count = 0

0 commit comments

Comments
 (0)