From 3db727d939d28163502dc7936dbcc69160b598e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Wed, 8 Nov 2017 22:04:27 +0200 Subject: [PATCH 1/2] Remove TableElementFinder. This class was pretty useless after latest cleanups and having it as an attribute in library itself didn't make much sense. It was also only used by TableElementKeywords, which somewhat inconsistently handled finding table cells itself. This commit moves TableElementFinder functionality into TableElementKeywords. --- src/SeleniumLibrary/__init__.py | 3 +- src/SeleniumLibrary/base/context.py | 4 -- src/SeleniumLibrary/keywords/tableelement.py | 49 +++++++++++++-- src/SeleniumLibrary/locators/__init__.py | 1 - .../locators/tableelementfinder.py | 59 ------------------- .../test_tablekeywords.py} | 14 ++--- 6 files changed, 52 insertions(+), 78 deletions(-) delete mode 100644 src/SeleniumLibrary/locators/tableelementfinder.py rename test/unit/{locators/test_tableelementfinder.py => keywords/test_tablekeywords.py} (67%) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 4f60b044b..3e13e34b7 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -33,7 +33,7 @@ TableElementKeywords, WaitingKeywords, WindowKeywords) -from SeleniumLibrary.locators import ElementFinder, TableElementFinder +from SeleniumLibrary.locators import ElementFinder from SeleniumLibrary.utils import (BrowserCache, Deprecated, LibraryListener, timestr_to_secs) @@ -346,7 +346,6 @@ def __init__(self, timeout=5.0, implicit_wait=0.0, DynamicCore.__init__(self, libraries) self.ROBOT_LIBRARY_LISTENER = LibraryListener() self._element_finder = ElementFinder(self) - self._table_element_finder = TableElementFinder(self) _speed_in_secs = Deprecated('_speed_in_secs', 'speed') _timeout_in_secs = Deprecated('_timeout_in_secs', 'timeout') diff --git a/src/SeleniumLibrary/base/context.py b/src/SeleniumLibrary/base/context.py index 5eda0bc7c..52c502c9f 100644 --- a/src/SeleniumLibrary/base/context.py +++ b/src/SeleniumLibrary/base/context.py @@ -39,10 +39,6 @@ def browsers(self): def element_finder(self): return self.ctx._element_finder - @property - def table_element_finder(self): - return self.ctx._table_element_finder - def find_element(self, locator, tag=None, required=True, parent=None): """Find element matching `locator`. diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index 72a483958..2270e141f 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -109,7 +109,7 @@ def table_column_should_contain(self, locator, column, expected, loglevel='INFO' See `Page Should Contain Element` for explanation about the ``loglevel`` argument. """ - element = self.table_element_finder.find_by_column(locator, column, expected) + element = self._find_by_column(locator, column, expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Table '%s' column %s did not contain text " @@ -128,7 +128,7 @@ def table_footer_should_contain(self, locator, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about the ``loglevel`` argument. """ - element = self.table_element_finder.find_by_footer(locator, expected) + element = self._find_by_footer(locator, expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Table '%s' footer did not contain text " @@ -147,7 +147,7 @@ def table_header_should_contain(self, locator, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about the ``loglevel`` argument. """ - element = self.table_element_finder.find_by_header(locator, expected) + element = self._find_by_header(locator, expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Table '%s' header did not contain text " @@ -171,7 +171,7 @@ def table_row_should_contain(self, locator, row, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about the ``loglevel`` argument. """ - element = self.table_element_finder.find_by_row(locator, row, expected) + element = self._find_by_row(locator, row, expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Table '%s' row %s did not contain text " @@ -187,8 +187,47 @@ def table_should_contain(self, locator, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about the ``loglevel`` argument. """ - element = self.table_element_finder.find_by_content(locator, expected) + element = self._find_by_content(locator, expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Table '%s' did not contain text '%s'." % (locator, expected)) + + def _find_by_content(self, table_locator, content): + return self._find(table_locator, '//*', content) + + def _find_by_header(self, table_locator, content): + return self._find(table_locator, '//th', content) + + def _find_by_footer(self, table_locator, content): + return self._find(table_locator, '//tfoot//td', content) + + def _find_by_row(self, table_locator, row, content): + position = self._index_to_position(row) + locator = '//tr[{}]'.format(position) + return self._find(table_locator, locator, content) + + def _find_by_column(self, table_locator, col, content): + position = self._index_to_position(col) + locator = '//tr//*[self::td or self::th][{}]'.format(position) + return self._find(table_locator, locator, content) + + def _index_to_position(self, index): + index = int(index) + if index == 0: + raise ValueError('Row and column indexes must be non-zero.') + if index > 0: + return str(index) + if index == -1: + return 'position()=last()' + return 'position()=last()-{}'.format(abs(index) - 1) + + def _find(self, table_locator, locator, content): + table = self.find_element(table_locator) + elements = self.find_elements(locator, parent=table) + for element in elements: + if content is None: + return element + if element.text and content in element.text: + return element + return None diff --git a/src/SeleniumLibrary/locators/__init__.py b/src/SeleniumLibrary/locators/__init__.py index 6366fdfb2..a2115d86a 100644 --- a/src/SeleniumLibrary/locators/__init__.py +++ b/src/SeleniumLibrary/locators/__init__.py @@ -16,5 +16,4 @@ from .customlocator import CustomLocator from .elementfinder import ElementFinder -from .tableelementfinder import TableElementFinder from .windowmanager import WindowManager diff --git a/src/SeleniumLibrary/locators/tableelementfinder.py b/src/SeleniumLibrary/locators/tableelementfinder.py deleted file mode 100644 index 054a5000a..000000000 --- a/src/SeleniumLibrary/locators/tableelementfinder.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2008-2011 Nokia Networks -# Copyright 2011-2016 Ryan Tomac, Ed Manlove and contributors -# Copyright 2016- Robot Framework Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from SeleniumLibrary.base import ContextAware - - -class TableElementFinder(ContextAware): - - def find_by_content(self, table_locator, content): - return self._find(table_locator, '//*', content) - - def find_by_header(self, table_locator, content): - return self._find(table_locator, '//th', content) - - def find_by_footer(self, table_locator, content): - return self._find(table_locator, '//tfoot//td', content) - - def find_by_row(self, table_locator, row, content): - position = self._index_to_position(row) - locator = '//tr[{}]'.format(position) - return self._find(table_locator, locator, content) - - def find_by_column(self, table_locator, col, content): - position = self._index_to_position(col) - locator = '//tr//*[self::td or self::th][{}]'.format(position) - return self._find(table_locator, locator, content) - - def _index_to_position(self, index): - index = int(index) - if index == 0: - raise ValueError('Row and column indexes must be non-zero.') - if index > 0: - return str(index) - if index == -1: - return 'position()=last()' - return 'position()=last()-{}'.format(abs(index) - 1) - - def _find(self, table_locator, locator, content): - table = self.find_element(table_locator) - elements = self.find_elements(locator, parent=table) - for element in elements: - if content is None: - return element - if element.text and content in element.text: - return element - return None diff --git a/test/unit/locators/test_tableelementfinder.py b/test/unit/keywords/test_tablekeywords.py similarity index 67% rename from test/unit/locators/test_tableelementfinder.py rename to test/unit/keywords/test_tablekeywords.py index e6ec6a0d1..b6853dd3b 100644 --- a/test/unit/locators/test_tableelementfinder.py +++ b/test/unit/keywords/test_tablekeywords.py @@ -2,15 +2,15 @@ from mockito import mock, when, unstub -from SeleniumLibrary.locators.tableelementfinder import TableElementFinder +from SeleniumLibrary.keywords import TableElementKeywords -class ElementFinderTest(unittest.TestCase): +class TableKeywordsTest(unittest.TestCase): def setUp(self): self.ctx = mock() self.ctx._element_finder = mock() - self.finder = TableElementFinder(self.ctx) + self.finder = TableElementKeywords(self.ctx) def tearDown(self): unstub() @@ -18,19 +18,19 @@ def tearDown(self): def test_find_by_column(self): xpath = '//tr//*[self::td or self::th][1]' when(self.finder)._find('id:table', xpath, 'content').thenReturn(mock()) - self.finder.find_by_column('id:table', 1, 'content') + self.finder._find_by_column('id:table', 1, 'content') def test_find_by_column_with_negative_index(self): xpath = '//tr//*[self::td or self::th][position()=last()]' when(self.finder)._find('id:table', xpath, 'content').thenReturn(mock()) - self.finder.find_by_column('id:table', -1, 'content') + self.finder._find_by_column('id:table', -1, 'content') def test_find_by_row(self): xpath = '//tr[2]' when(self.finder)._find('xpath=//table', xpath, 'content').thenReturn(mock()) - self.finder.find_by_row('xpath=//table', 2, 'content') + self.finder._find_by_row('xpath=//table', 2, 'content') def test_find_by_row_with_negative_index(self): xpath = '//tr[position()=last()-2]' when(self.finder)._find('xpath=//table', xpath, 'content').thenReturn(mock()) - self.finder.find_by_row('xpath=//table', -3, 'content') + self.finder._find_by_row('xpath=//table', -3, 'content') From e28df0439da8798b3c7f2e22771b6e744ea4efb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Thu, 9 Nov 2017 01:00:30 +0200 Subject: [PATCH 2/2] Remove empty line left by manual merge --- src/SeleniumLibrary/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 1a1320e95..d8146dc60 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -34,7 +34,6 @@ TableElementKeywords, WaitingKeywords, WindowKeywords) - from SeleniumLibrary.locators import ElementFinder from SeleniumLibrary.utils import (Deprecated, LibraryListener, timestr_to_secs, WebDriverCache)