Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/SeleniumLibrary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
SelectElementKeywords,
TableElementKeywords,
WaitingKeywords)
from SeleniumLibrary.locators import ElementFinder
from SeleniumLibrary.locators import ElementFinder, TableElementFinder
from SeleniumLibrary.utils import (BrowserCache, Deprecated, LibraryListener,
timestr_to_secs)

Expand Down Expand Up @@ -260,6 +260,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')
Expand Down
8 changes: 8 additions & 0 deletions src/SeleniumLibrary/base/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 0 additions & 4 deletions src/SeleniumLibrary/base/librarycomponent.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ class LibraryComponent(ContextAware):
def __init__(self, ctx):
ContextAware.__init__(self, ctx)

@property
def element_finder(self):
return self.ctx.element_finder

def info(self, msg, html=False):
logger.info(msg, html)

Expand Down
27 changes: 11 additions & 16 deletions src/SeleniumLibrary/keywords/tableelement.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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:
Expand Down Expand Up @@ -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' "
Expand All @@ -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' "
Expand All @@ -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 "
Expand All @@ -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' "
Expand All @@ -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 "
Expand Down
4 changes: 0 additions & 4 deletions src/SeleniumLibrary/locators/tableelementfinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'): [''],
Expand Down
Empty file added test/unit/api/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions test/unit/api/test_public_api_objects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import unittest

from SeleniumLibrary import SeleniumLibrary
from SeleniumLibrary.locators import ElementFinder, 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)
136 changes: 64 additions & 72 deletions test/unit/locators/test_tableelementfinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down