From dedf99aae30d970107ddb6ad880babc9d9ed3cc9 Mon Sep 17 00:00:00 2001 From: Tatu Aalto Date: Thu, 21 Sep 2017 22:42:40 +0300 Subject: [PATCH 1/4] Added TableElementFinder in the public API --- src/SeleniumLibrary/__init__.py | 2 ++ src/SeleniumLibrary/base/librarycomponent.py | 4 +++ src/SeleniumLibrary/keywords/tableelement.py | 27 ++++++++------------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 07e658c12..b3129dfe7 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -32,6 +32,7 @@ TableElementKeywords, WaitingKeywords) from SeleniumLibrary.locators import ElementFinder +from SeleniumLibrary.locators import TableElementFinder from SeleniumLibrary.utils import (BrowserCache, Deprecated, LibraryListener, timestr_to_secs) @@ -260,6 +261,7 @@ def __init__(self, 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/librarycomponent.py b/src/SeleniumLibrary/base/librarycomponent.py index 949db41f3..cc2d4c6ba 100644 --- a/src/SeleniumLibrary/base/librarycomponent.py +++ b/src/SeleniumLibrary/base/librarycomponent.py @@ -35,6 +35,10 @@ def __init__(self, ctx): def element_finder(self): return self.ctx.element_finder + @property + def table_element_finder(self): + return self.ctx.table_element_finder + def info(self, msg, html=False): logger.info(msg, html) diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index 05ab83366..c087a8086 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -15,15 +15,10 @@ # limitations under the License. from SeleniumLibrary.base import LibraryComponent, keyword -from SeleniumLibrary.locators import TableElementFinder class TableElementKeywords(LibraryComponent): - def __init__(self, ctx): - LibraryComponent.__init__(self, ctx) - self._table_element_finder = TableElementFinder(ctx) - @keyword def get_table_cell(self, table_locator, row, column, loglevel='INFO'): """Returns the content from a table cell. @@ -44,7 +39,7 @@ def get_table_cell(self, table_locator, row, column, loglevel='INFO'): column_index = column if column > 0: column_index = column - 1 - table = self._table_element_finder.find(table_locator) + table = self.table_element_finder.find(table_locator) if table: rows = table.find_elements_by_xpath("./thead/tr") if row_index >= len(rows) or row_index < 0: @@ -113,8 +108,8 @@ def table_column_should_contain(self, table_locator, col, expected, loglevel='IN See `Page Should Contain Element` for explanation about `loglevel` argument. """ - element = self._table_element_finder.find_by_col(table_locator, col, - expected) + element = self.table_element_finder.find_by_col(table_locator, col, + expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Column #%s in table identified by '%s' " @@ -132,8 +127,8 @@ def table_footer_should_contain(self, table_locator, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about `loglevel` argument. """ - element = self._table_element_finder.find_by_footer(table_locator, - expected) + element = self.table_element_finder.find_by_footer(table_locator, + expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Footer in table identified by '%s' " @@ -150,8 +145,8 @@ def table_header_should_contain(self, table_locator, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about `loglevel` argument. """ - element = self._table_element_finder.find_by_header(table_locator, - expected) + element = self.table_element_finder.find_by_header(table_locator, + expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Header in table identified by '%s' should " @@ -176,8 +171,8 @@ def table_row_should_contain(self, table_locator, row, expected, loglevel='INFO' See `Page Should Contain Element` for explanation about `loglevel` argument. """ - element = self._table_element_finder.find_by_row(table_locator, - row, expected) + element = self.table_element_finder.find_by_row(table_locator, + row, expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Row #%s in table identified by '%s' " @@ -194,8 +189,8 @@ def table_should_contain(self, table_locator, expected, loglevel='INFO'): See `Page Should Contain Element` for explanation about `loglevel` argument. """ - element = self._table_element_finder.find_by_content(table_locator, - expected) + element = self.table_element_finder.find_by_content(table_locator, + expected) if element is None: self.ctx.log_source(loglevel) raise AssertionError("Table identified by '%s' should have " From d7914caf1e2a92a342e23ff7e09111e217fb6341 Mon Sep 17 00:00:00 2001 From: Tatu Aalto Date: Thu, 21 Sep 2017 22:55:31 +0300 Subject: [PATCH 2/4] Added test for ElementFinder and TableElementFinder in public API --- test/unit/api/__init__.py | 0 test/unit/api/test_public_api_objects.py | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 test/unit/api/__init__.py create mode 100644 test/unit/api/test_public_api_objects.py diff --git a/test/unit/api/__init__.py b/test/unit/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/api/test_public_api_objects.py b/test/unit/api/test_public_api_objects.py new file mode 100644 index 000000000..58361199d --- /dev/null +++ b/test/unit/api/test_public_api_objects.py @@ -0,0 +1,19 @@ +import unittest + +from SeleniumLibrary import SeleniumLibrary +from SeleniumLibrary.locators import ElementFinder +from SeleniumLibrary.locators import TableElementFinder + + +class TableElementFinderInAPITest(unittest.TestCase): + + def test_table_finder(self): + sl = SeleniumLibrary() + self.assertIsInstance(sl.table_element_finder, TableElementFinder) + + +class ElementFinderInAPITest(unittest.TestCase): + + def test_table_finder(self): + sl = SeleniumLibrary() + self.assertIsInstance(sl.element_finder, ElementFinder) From a848e7d2b1fac0eabfb5cf95905c1a272b19b826 Mon Sep 17 00:00:00 2001 From: Tatu Aalto Date: Fri, 22 Sep 2017 23:38:29 +0300 Subject: [PATCH 3/4] Made table_element_finder as private method --- src/SeleniumLibrary/__init__.py | 2 +- src/SeleniumLibrary/base/context.py | 8 ++ src/SeleniumLibrary/base/librarycomponent.py | 8 -- .../locators/tableelementfinder.py | 4 - test/unit/api/test_public_api_objects.py | 2 +- test/unit/locators/test_tableelementfinder.py | 136 +++++++++--------- 6 files changed, 74 insertions(+), 86 deletions(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index b3129dfe7..53ecd8075 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -261,7 +261,7 @@ def __init__(self, DynamicCore.__init__(self, libraries) self.ROBOT_LIBRARY_LISTENER = LibraryListener() self.element_finder = ElementFinder(self) - self.table_element_finder = TableElementFinder(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 0dc3ebc81..c55634494 100644 --- a/src/SeleniumLibrary/base/context.py +++ b/src/SeleniumLibrary/base/context.py @@ -27,3 +27,11 @@ def browser(self): @property def browsers(self): return self.ctx._browsers + + @property + def element_finder(self): + return self.ctx.element_finder + + @property + def table_element_finder(self): + return self.ctx._table_element_finder diff --git a/src/SeleniumLibrary/base/librarycomponent.py b/src/SeleniumLibrary/base/librarycomponent.py index cc2d4c6ba..235185e18 100644 --- a/src/SeleniumLibrary/base/librarycomponent.py +++ b/src/SeleniumLibrary/base/librarycomponent.py @@ -31,14 +31,6 @@ class LibraryComponent(ContextAware): def __init__(self, ctx): ContextAware.__init__(self, ctx) - @property - def element_finder(self): - return self.ctx.element_finder - - @property - def table_element_finder(self): - return self.ctx.table_element_finder - def info(self, msg, html=False): logger.info(msg, html) diff --git a/src/SeleniumLibrary/locators/tableelementfinder.py b/src/SeleniumLibrary/locators/tableelementfinder.py index 3728ef55e..e71403286 100644 --- a/src/SeleniumLibrary/locators/tableelementfinder.py +++ b/src/SeleniumLibrary/locators/tableelementfinder.py @@ -16,15 +16,11 @@ from SeleniumLibrary.base import ContextAware -from .elementfinder import ElementFinder - class TableElementFinder(ContextAware): def __init__(self, ctx): ContextAware.__init__(self, ctx) - self.element_finder = ElementFinder(ctx) - self._locator_suffixes = { ('css', 'default'): [''], ('css', 'content'): [''], diff --git a/test/unit/api/test_public_api_objects.py b/test/unit/api/test_public_api_objects.py index 58361199d..db6441eb2 100644 --- a/test/unit/api/test_public_api_objects.py +++ b/test/unit/api/test_public_api_objects.py @@ -9,7 +9,7 @@ class TableElementFinderInAPITest(unittest.TestCase): def test_table_finder(self): sl = SeleniumLibrary() - self.assertIsInstance(sl.table_element_finder, TableElementFinder) + self.assertIsInstance(sl._table_element_finder, TableElementFinder) class ElementFinderInAPITest(unittest.TestCase): diff --git a/test/unit/locators/test_tableelementfinder.py b/test/unit/locators/test_tableelementfinder.py index 823e365ee..65a7166a8 100644 --- a/test/unit/locators/test_tableelementfinder.py +++ b/test/unit/locators/test_tableelementfinder.py @@ -9,129 +9,121 @@ class ElementFinderTests(unittest.TestCase): def setUp(self): self.ctx = mock() - self.ctx.browser = self.browser = mock() + self.ctx.element_finder = mock() self.finder = TableElementFinder(self.ctx) + self.args = {'first_only': False, 'required': False} def tearDown(self): unstub() def test_find_with_implicit_css_locator(self): - when(self.browser).find_elements_by_css_selector( - "table#test1").thenReturn([]) + when(self.ctx.element_finder).find("css=table#test1", + **self.args).thenReturn([]) self.finder.find("test1") - verify(self.browser).find_elements_by_css_selector("table#test1") + verify(self.ctx.element_finder).find("css=table#test1", **self.args) def test_find_with_css_selector(self): elements = self._make_mock_elements('table', 'table', 'table') - when(self.browser).find_elements_by_css_selector( - "table#test1").thenReturn(elements) - self.assertEqual( - self.finder.find("css=table#test1"), - elements[0]) - verify(self.browser).find_elements_by_css_selector("table#test1") + when(self.ctx.element_finder).find("css=table#test1", + **self.args).thenReturn(elements) + self.assertEqual(self.finder.find("css=table#test1"), + elements[0]) + verify(self.ctx.element_finder).find("css=table#test1", **self.args) def test_find_with_xpath_selector(self): elements = self._make_mock_elements('table', 'table', 'table') - when(self.browser).find_elements_by_xpath( - "//table[@id='test1']").thenReturn(elements) - self.assertEqual( - self.finder.find("xpath=//table[@id='test1']"), - elements[0]) - verify(self.browser).find_elements_by_xpath( - "//table[@id='test1']") + when(self.ctx.element_finder).find("xpath=//table[@id='test1']", + **self.args).thenReturn(elements) + self.assertEqual(self.finder.find("xpath=//table[@id='test1']"), + elements[0]) + verify(self.ctx.element_finder).find("xpath=//table[@id='test1']", + **self.args) def test_find_with_content_constraint(self): elements = self._make_mock_elements('td', 'td', 'td') elements[1].text = 'hi' - when(self.browser).find_elements_by_css_selector( - "table#test1").thenReturn(elements) - self.assertEqual( - self.finder.find_by_content("test1", 'hi'), - elements[1]) - verify(self.browser).find_elements_by_css_selector("table#test1") + when(self.ctx.element_finder).find("css=table#test1", + **self.args).thenReturn(elements) + self.assertEqual(self.finder.find_by_content("test1", 'hi'), + elements[1]) + verify(self.ctx.element_finder).find("css=table#test1", + **self.args) def test_find_with_null_content_constraint(self): elements = self._make_mock_elements('td', 'td', 'td') elements[1].text = 'hi' - when(self.browser).find_elements_by_css_selector( - "table#test1").thenReturn(elements) - self.assertEqual( - self.finder.find_by_content("test1", None), - elements[0]) - verify(self.browser).find_elements_by_css_selector("table#test1") + when(self.ctx.element_finder).find("css=table#test1", + **self.args).thenReturn(elements) + self.assertEqual(self.finder.find_by_content("test1", None), + elements[0]) + verify(self.ctx.element_finder).find("css=table#test1", **self.args) def test_find_by_content_with_css_locator(self): - when(self.browser).find_elements_by_css_selector( - "table#test1").thenReturn([]) + when(self.ctx.element_finder).find("css=table#test1", + **self.args).thenReturn([]) self.finder.find_by_content("css=table#test1", 'hi') - verify(self.browser).find_elements_by_css_selector("table#test1") + verify(self.ctx.element_finder).find("css=table#test1", **self.args) def test_find_by_content_with_xpath_locator(self): - when(self.browser).find_elements_by_xpath( - "//table[@id='test1']//*").thenReturn([]) + when(self.ctx.element_finder).find("xpath=//table[@id='test1']//*", + **self.args).thenReturn([]) self.finder.find_by_content("xpath=//table[@id='test1']", 'hi') - verify(self.browser).find_elements_by_xpath("//table[@id='test1']//*") + verify(self.ctx.element_finder).find("xpath=//table[@id='test1']//*", + **self.args) def test_find_by_header_with_css_locator(self): - when(self.browser).find_elements_by_css_selector( - "table#test1 th").thenReturn([]) + when(self.ctx.element_finder).find("css=table#test1 th", + **self.args).thenReturn([]) self.finder.find_by_header("css=table#test1", 'hi') - verify(self.browser).find_elements_by_css_selector("table#test1 th") + verify(self.ctx.element_finder).find("css=table#test1 th", **self.args) def test_find_by_header_with_xpath_locator(self): - when(self.browser).find_elements_by_xpath( - "//table[@id='test1']//th").thenReturn([]) + when(self.ctx.element_finder).find("xpath=//table[@id='test1']//th", + **self.args).thenReturn([]) self.finder.find_by_header("xpath=//table[@id='test1']", 'hi') - verify(self.browser).find_elements_by_xpath( - "//table[@id='test1']//th") + verify(self.ctx.element_finder).find("xpath=//table[@id='test1']//th", + **self.args) def test_find_by_footer_with_css_locator(self): - when(self.browser).find_elements_by_css_selector( - "table#test1 tfoot td").thenReturn([]) + when(self.ctx.element_finder).find("css=table#test1 tfoot td", + **self.args).thenReturn([]) self.finder.find_by_footer("css=table#test1", 'hi') - verify(self.browser).find_elements_by_css_selector( - "table#test1 tfoot td") + verify(self.ctx.element_finder).find("css=table#test1 tfoot td", + **self.args) def test_find_by_footer_with_xpath_locator(self): - when(self.browser).find_elements_by_xpath( - "//table[@id='test1']//tfoot//td").thenReturn([]) + xpath = "xpath=//table[@id='test1']//tfoot//td" + when(self.ctx.element_finder).find(xpath, **self.args).thenReturn([]) self.finder.find_by_footer("xpath=//table[@id='test1']", 'hi') - verify(self.browser).find_elements_by_xpath("//table[@id='test1']" - "//tfoot//td") + verify(self.ctx.element_finder).find(xpath, **self.args) def test_find_by_row_with_css_locator(self): - when(self.browser).find_elements_by_css_selector( - "table#test1 tr:nth-child(2)").thenReturn([]) + when(self.ctx.element_finder).find("css=table#test1 tr:nth-child(2)", + **self.args).thenReturn([]) self.finder.find_by_row("css=table#test1", 2, 'hi') - verify(self.browser).find_elements_by_css_selector("table#test1 " - "tr:nth-child(2)") + verify(self.ctx.element_finder).find("css=table#test1 tr:nth-child(2)", + **self.args) def test_find_by_row_with_xpath_locator(self): - when(self.browser).find_elements_by_xpath( - "//table[@id='test1']//tr[2]//*").thenReturn([]) + xpath = "xpath=//table[@id='test1']//tr[2]//*" + when(self.ctx.element_finder).find(xpath, **self.args).thenReturn([]) self.finder.find_by_row("xpath=//table[@id='test1']", 2, 'hi') - verify(self.browser).find_elements_by_xpath("//table[@id='test1']" - "//tr[2]//*") + verify(self.ctx.element_finder).find(xpath, **self.args) def test_find_by_col_with_css_locator(self): - when(self.browser).find_elements_by_css_selector( - "table#test1 tr td:nth-child(2)").thenReturn([]) - when(self.browser).find_elements_by_css_selector( - "table#test1 tr th:nth-child(2)").thenReturn([]) + css1 = "css=table#test1 tr td:nth-child(2)" + css2 = "css=table#test1 tr th:nth-child(2)" + when(self.ctx.element_finder).find(css1, **self.args).thenReturn([]) + when(self.ctx.element_finder).find(css2, **self.args).thenReturn([]) self.finder.find_by_col("css=table#test1", 2, 'hi') - verify(self.browser).find_elements_by_css_selector( - "table#test1 tr td:nth-child(2)") - verify(self.browser).find_elements_by_css_selector( - "table#test1 tr th:nth-child(2)") + verify(self.ctx.element_finder).find(css1, **self.args) + verify(self.ctx.element_finder).find(css2, **self.args) def test_find_by_col_with_xpath_locator(self): - when(self.browser).find_elements_by_xpath("//table[@id='test1']//tr//" - "*[self::td or self" - "::th][2]").thenReturn([]) + xpath = "xpath=//table[@id='test1']//tr//*[self::td or self::th][2]" + when(self.ctx.element_finder).find(xpath, **self.args).thenReturn([]) self.finder.find_by_col("xpath=//table[@id='test1']", 2, 'hi') - verify(self.browser).find_elements_by_xpath("//table[@id='test1']" - "//tr//*[self::td or self" - "::th][2]") + verify(self.ctx.element_finder).find(xpath, **self.args) def _make_mock_elements(self, *tags): elements = [] From 59c4e2bf42db4a08671bd1fdb89feeb35c246373 Mon Sep 17 00:00:00 2001 From: Tatu Aalto Date: Sat, 23 Sep 2017 12:16:35 +0300 Subject: [PATCH 4/4] Fixed some imports --- src/SeleniumLibrary/__init__.py | 3 +-- test/unit/api/test_public_api_objects.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 53ecd8075..bf1bac81f 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -31,8 +31,7 @@ SelectElementKeywords, TableElementKeywords, WaitingKeywords) -from SeleniumLibrary.locators import ElementFinder -from SeleniumLibrary.locators import TableElementFinder +from SeleniumLibrary.locators import ElementFinder, TableElementFinder from SeleniumLibrary.utils import (BrowserCache, Deprecated, LibraryListener, timestr_to_secs) diff --git a/test/unit/api/test_public_api_objects.py b/test/unit/api/test_public_api_objects.py index db6441eb2..10df765ff 100644 --- a/test/unit/api/test_public_api_objects.py +++ b/test/unit/api/test_public_api_objects.py @@ -1,8 +1,7 @@ import unittest from SeleniumLibrary import SeleniumLibrary -from SeleniumLibrary.locators import ElementFinder -from SeleniumLibrary.locators import TableElementFinder +from SeleniumLibrary.locators import ElementFinder, TableElementFinder class TableElementFinderInAPITest(unittest.TestCase):