diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py
index ffb0bcbfe..72a483958 100644
--- a/src/SeleniumLibrary/keywords/tableelement.py
+++ b/src/SeleniumLibrary/keywords/tableelement.py
@@ -20,179 +20,175 @@
class TableElementKeywords(LibraryComponent):
@keyword
- def get_table_cell(self, table_locator, row, column, loglevel='INFO'):
- """Returns the content from a table cell.
+ def get_table_cell(self, locator, row, column, loglevel='INFO'):
+ """Returns contents of table cell.
- Row and column number start from 1. Header and footer rows are
- included in the count. A negative row or column number can be used
- to get rows counting from the end (end: -1). Cell content from header
- or footer rows can be obtained with this keyword. To understand how
- tables are identified, please take a look at the `introduction`.
+ The table is located using the ``locator`` argument and its cell
+ found using ``row`` and ``column``. See the `Locating elements`
+ section for details about the locator syntax.
- See `Page Should Contain` for explanation about `loglevel` argument.
+ Both row and column indexes start from 1, and header and footer
+ rows are included in the count. It is possible to refer to rows
+ and columns from the end by using negative indexes so that -1
+ is the last row/column, -2 is the second last, and so on.
+
+ All ``
`` and `` | `` elements anywhere in the table are
+ considered to be cells.
+
+ See `Page Should Contain` for explanation about the ``loglevel``
+ argument.
"""
row = int(row)
- row_index = row
- if row > 0:
- row_index = row - 1
column = int(column)
- column_index = column
- if column > 0:
- column_index = column - 1
- table = self.element_finder.find(table_locator)
- if table:
- rows = table.find_elements_by_xpath("./thead/tr")
- if row_index >= len(rows) or row_index < 0:
- rows.extend(table.find_elements_by_xpath("./tbody/tr"))
- if row_index >= len(rows) or row_index < 0:
- rows.extend(table.find_elements_by_xpath("./tfoot/tr"))
- if row_index < len(rows):
- columns = rows[row_index].find_elements_by_tag_name('th')
- if column_index >= len(columns) or column_index < 0:
- columns.extend(rows[row_index].find_elements_by_tag_name('td'))
- if column_index < len(columns):
- return columns[column_index].text
- self.ctx.log_source(loglevel)
- raise AssertionError("Cell in table %s in row #%s and column #%s "
- "could not be found."
- % (table_locator, str(row), str(column)))
+ if row == 0 or column == 0:
+ raise ValueError('Both row and column must be non-zero, '
+ 'got row %d and column %d.' % (row, column))
+ try:
+ cell = self._get_cell(locator, row, column)
+ except AssertionError:
+ self.log_source(loglevel)
+ raise
+ return cell.text
+
+ def _get_cell(self, locator, row, column):
+ rows = self._get_rows(locator, row)
+ if len(rows) < abs(row):
+ raise AssertionError("Table '%s' should have had at least %d "
+ "rows but had only %d."
+ % (locator, abs(row), len(rows)))
+ index = row - 1 if row > 0 else row
+ cells = rows[index].find_elements_by_xpath('./th|./td')
+ if len(cells) < abs(column):
+ raise AssertionError("Table '%s' row %d should have had at "
+ "least %d columns but had only %d."
+ % (locator, row, abs(column), len(cells)))
+ index = column - 1 if column > 0 else column
+ return cells[index]
+
+ def _get_rows(self, locator, count):
+ # Get rows in same order as browsers render them.
+ table = self.find_element(locator, tag='table')
+ rows = table.find_elements_by_xpath("./thead/tr")
+ if count < 0 or len(rows) < count:
+ rows.extend(table.find_elements_by_xpath("./tbody/tr"))
+ if count < 0 or len(rows) < count:
+ rows.extend(table.find_elements_by_xpath("./tfoot/tr"))
+ return rows
@keyword
- def table_cell_should_contain(self, table_locator, row, column, expected, loglevel='INFO'):
- """Verifies that a certain cell in a table contains `expected`.
-
- Row and column number start from 1. This keyword passes if the
- specified cell contains the given content. If you want to test
- that the cell content matches exactly, or that it e.g. starts
- with some text, use `Get Table Cell` keyword in combination
- with built-in keywords such as `Should Be Equal` or `Should
- Start With`.
+ def table_cell_should_contain(self, locator, row, column, expected, loglevel='INFO'):
+ """Verifies table cell contains text ``expected``.
- To understand how tables are identified, please take a look at
- the `introduction`.
-
- See `Page Should Contain` for explanation about `loglevel` argument.
+ See `Get Table Cell` that this keyword uses internally for
+ explanation about accepted arguments.
"""
- message = ("Cell in table '%s' in row #%s and column #%s "
- "should have contained text '%s'."
- % (table_locator, row, column, expected))
- try:
- content = self.get_table_cell(table_locator, row, column, loglevel='NONE')
- except AssertionError as err:
- self.info(err)
- self.ctx.log_source(loglevel)
- raise AssertionError(message)
- self.info("Cell contains %s." % (content))
+ content = self.get_table_cell(locator, row, column, loglevel)
if expected not in content:
self.ctx.log_source(loglevel)
- raise AssertionError(message)
+ raise AssertionError("Table '%s' cell on row %s and column %s "
+ "should have contained text '%s' but it had "
+ "'%s'."
+ % (locator, row, column, expected, content))
+ self.info("Table cell contains '%s'." % content)
@keyword
- def table_column_should_contain(self, table_locator, col, expected, loglevel='INFO'):
- """Verifies that a specific column contains `expected`.
+ def table_column_should_contain(self, locator, column, expected, loglevel='INFO'):
+ """Verifies table column contains text ``expected``.
- The first leftmost column is column number 1. A negative column
- number can be used to get column counting from the end of the row (end: -1).
- If the table contains cells that span multiple columns, those merged cells
- count as a single column. For example both tests below work,
- if in one row columns A and B are merged with colspan="2", and
- the logical third column contains "C".
+ The table is located using the ``locator`` argument and its column
+ found using ``column``. See the `Locating elements` section for
+ details about the locator syntax.
- Example:
- | Table Column Should Contain | tableId | 3 | C |
- | Table Column Should Contain | tableId | 2 | C |
+ Column indexes start from 1. It is possible to refer to columns
+ from the end by using negative indexes so that -1 is the last column,
+ -2 is the second last, and so on.
- To understand how tables are identified, please take a look at
- the `introduction`.
+ If a table contains cells that span multiple columns, those merged
+ cells count as a single column.
- See `Page Should Contain Element` for explanation about
- `loglevel` argument.
+ See `Page Should Contain Element` for explanation about the
+ ``loglevel`` argument.
"""
- element = self.table_element_finder.find_by_col(table_locator, col,
- expected)
+ element = self.table_element_finder.find_by_column(locator, column, expected)
if element is None:
self.ctx.log_source(loglevel)
- raise AssertionError("Column #%s in table identified by '%s' "
- "should have contained text '%s'."
- % (col, table_locator, expected))
+ raise AssertionError("Table '%s' column %s did not contain text "
+ "'%s'." % (locator, column, expected))
@keyword
- def table_footer_should_contain(self, table_locator, expected, loglevel='INFO'):
- """Verifies that the table footer contains `expected`.
+ def table_footer_should_contain(self, locator, expected, loglevel='INFO'):
+ """Verifies table footer contains text ``expected``.
- With table footer can be described as any | -element that is
- child of a | -element. To understand how tables are
- identified, please take a look at the `introduction`.
+ Any ```` element inside `` | `` element is considered to
+ be part of the footer.
- See `Page Should Contain Element` for explanation about
- `loglevel` argument.
+ The table is located using the ``locator`` argument. See the
+ `Locating elements` section for details about the locator syntax.
+
+ See `Page Should Contain Element` for explanation about the
+ ``loglevel`` argument.
"""
- element = self.table_element_finder.find_by_footer(table_locator,
- expected)
+ element = self.table_element_finder.find_by_footer(locator, expected)
if element is None:
self.ctx.log_source(loglevel)
- raise AssertionError("Footer in table identified by '%s' "
- "should have contained "
- "text '%s'." % (table_locator, expected))
+ raise AssertionError("Table '%s' footer did not contain text "
+ "'%s'." % (locator, expected))
@keyword
- def table_header_should_contain(self, table_locator, expected, loglevel='INFO'):
- """Verifies that the table header, i.e. any ... | element, contains `expected`.
+ def table_header_should_contain(self, locator, expected, loglevel='INFO'):
+ """Verifies table header contains text ``expected``.
+
+ Any ```` element anywhere in the table is considered to be
+ part of the header.
- To understand how tables are identified, please take a look at
- the `introduction`.
+ The table is located using the ``locator`` argument. See the
+ `Locating elements` section for details about the locator syntax.
- See `Page Should Contain Element` for explanation about
- `loglevel` argument.
+ See `Page Should Contain Element` for explanation about the
+ ``loglevel`` argument.
"""
- element = self.table_element_finder.find_by_header(table_locator,
- expected)
+ element = self.table_element_finder.find_by_header(locator, expected)
if element is None:
self.ctx.log_source(loglevel)
- raise AssertionError("Header in table identified by '%s' should "
- "have contained "
- "text '%s'." % (table_locator, expected))
+ raise AssertionError("Table '%s' header did not contain text "
+ "'%s'." % (locator, expected))
@keyword
- def table_row_should_contain(self, table_locator, row, expected, loglevel='INFO'):
- """Verifies that a specific table row contains `expected`.
-
- The uppermost row is row number 1. A negative column
- number can be used to get column counting from the end of the row
- (end: -1). For tables that are structured with thead, tbody and tfoot,
- only the tbody section is searched. Please use `Table Header Should Contain`
- or `Table Footer Should Contain` for tests against the header or
- footer content.
-
- If the table contains cells that span multiple rows, a match
- only occurs for the uppermost row of those merged cells. To
- understand how tables are identified, please take a look at
- the `introduction`.
-
- See `Page Should Contain Element` for explanation about `loglevel` argument.
+ def table_row_should_contain(self, locator, row, expected, loglevel='INFO'):
+ """Verifies that table row contains text ``expected``.
+
+ The table is located using the ``locator`` argument and its column
+ found using ``column``. See the `Locating elements` section for
+ details about the locator syntax.
+
+ Row indexes start from 1. It is possible to refer to rows
+ from the end by using negative indexes so that -1 is the last row,
+ -2 is the second last, and so on.
+
+ If a table contains cells that span multiple rows, a match
+ only occurs for the uppermost row of those merged cells.
+
+ See `Page Should Contain Element` for explanation about the
+ ``loglevel`` argument.
"""
- element = self.table_element_finder.find_by_row(table_locator,
- row, expected)
+ element = self.table_element_finder.find_by_row(locator, row, expected)
if element is None:
self.ctx.log_source(loglevel)
- raise AssertionError("Row #%s in table identified by '%s' "
- "should have contained "
- "text '%s'." % (row, table_locator, expected))
+ raise AssertionError("Table '%s' row %s did not contain text "
+ "'%s'." % (locator, row, expected))
@keyword
- def table_should_contain(self, table_locator, expected, loglevel='INFO'):
- """Verifies that `expected` can be found somewhere in the table.
+ def table_should_contain(self, locator, expected, loglevel='INFO'):
+ """Verifies table contains text ``expected``.
- To understand how tables are identified, please take a look at
- the `introduction`.
+ The table is located using the ``locator`` argument. See the
+ `Locating elements` section for details about the locator syntax.
- See `Page Should Contain Element` for explanation about
- `loglevel` argument.
+ See `Page Should Contain Element` for explanation about the
+ ``loglevel`` argument.
"""
- element = self.table_element_finder.find_by_content(table_locator,
- expected)
+ element = self.table_element_finder.find_by_content(locator, expected)
if element is None:
self.ctx.log_source(loglevel)
- raise AssertionError("Table identified by '%s' should have "
- "contained text '%s'."
- % (table_locator, expected))
+ raise AssertionError("Table '%s' did not contain text '%s'."
+ % (locator, expected))
diff --git a/src/SeleniumLibrary/locators/tableelementfinder.py b/src/SeleniumLibrary/locators/tableelementfinder.py
index 3d86eada9..054a5000a 100644
--- a/src/SeleniumLibrary/locators/tableelementfinder.py
+++ b/src/SeleniumLibrary/locators/tableelementfinder.py
@@ -18,57 +18,42 @@
class TableElementFinder(ContextAware):
- locators = {
- 'content': ['//*'],
- 'header': ['//th'],
- 'footer': ['//tfoot//td'],
- 'row': ['//tr[{row}]//*'],
- 'last-row': ['//tbody/tr[position()=last()-({row}-1)]'],
- 'col': ['//tr//*[self::td or self::th][{col}]'],
- 'last-col': ['//tbody/tr/td[position()=last()-({col}-1)]',
- '//tbody/tr/td[position()=last()-({col}-1)]']
- }
def find_by_content(self, table_locator, content):
- locators = self.locators['content']
- return self._search_in_locators(table_locator, locators, content)
+ return self._find(table_locator, '//*', content)
def find_by_header(self, table_locator, content):
- locators = self.locators['header']
- return self._search_in_locators(table_locator, locators, content)
+ return self._find(table_locator, '//th', content)
def find_by_footer(self, table_locator, content):
- locators = self.locators['footer']
- return self._search_in_locators(table_locator, locators, content)
+ return self._find(table_locator, '//tfoot//td', content)
def find_by_row(self, table_locator, row, content):
- location_method = "row"
- row = str(row)
- if row[0] == "-":
- row = row[1:]
- location_method = "last-row"
- locators = [locator.format(row=row)
- for locator in self.locators[location_method]]
- return self._search_in_locators(table_locator, locators, content)
-
- def find_by_col(self, table_locator, col, content):
- location_method = "col"
- col = str(col)
- if col[0] == "-":
- col = col[1:]
- location_method = "last-col"
- locators = [locator.format(col=col)
- for locator in self.locators[location_method]]
- return self._search_in_locators(table_locator, locators, content)
-
- def _search_in_locators(self, table_locator, locators, 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)
- for locator in locators:
- elements = self.find_elements(locator, parent=table)
- for element in elements:
- if content is None:
- return element
- element_text = element.text
- if element_text and content in element_text:
- return element
+ 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/acceptance/keywords/tables/col_should_contain.robot b/test/acceptance/keywords/tables/col_should_contain.robot
index ddcffaedb..424c90418 100644
--- a/test/acceptance/keywords/tables/col_should_contain.robot
+++ b/test/acceptance/keywords/tables/col_should_contain.robot
@@ -3,27 +3,40 @@ Resource table_resource.robot
*** Test Cases ***
Should Find Text In Specific Column
- [Template] Table Column Should Contain With CSS And XPath Locators
- simpleTable 2 simpleTable_B2
- simpleWithNested 2 nestedTable_A1
- nestedTable 3 nestedTable_C1
+ [Template] Table Column Should Contain
+ simpleTable 2 simpleTable_B2
+ id:simpleTable -2 simpleTable_B2
+ simpleWithNested 2 nestedTable_A1
+ css:#nestedTable 3 nestedTable_C1
+ nestedTable -1 nestedTable_C1
tableWithSingleHeader 1 tableWithSingleHeader_A1
tableWithSingleHeader 1 tableWithSingleHeader_A3
- tableWithTwoHeaders 2 tableWithTwoHeaders_B2
+ tableWithTwoHeaders 2 tableWithTwoHeaders_B2
+
+Mixed th and td
+ [Template] Table Column Should Contain
+ mixed-th-td 1 1.1 (th)
+ id:mixed-th-td 1 2.1 (td)
+ css:#mixed-th-td 2 1.2 (td)
+ //*[@id="mixed-th-td"] 2 2.2 (th)
+ mixed-th-td 3 2.3 (td)
+ mixed-th-td 3 3.3 (th)
+ mixed-th-td -2 1.2 (td)
+ mixed-th-td -2 2.2 (th)
+ mixed-th-td -3 1.1 (th)
+ mixed-th-td -3 2.1 (td)
Should Give Error Message When Content Not Found In Table Column
Run Keyword And Expect Error
- ... Column #2 in table identified by 'id:simpleTable' should have contained text 'simpleTable_C3'.
+ ... Table 'id:simpleTable' column 2 did not contain text 'simpleTable_C3'.
... Table Column Should Contain id:simpleTable 2 simpleTable_C3
Should Give Error Message When Column Number Out Of Bounds
Run Keyword And Expect Error
- ... Column #20 in table identified by 'xpath=//*[@id="simpleTable"]' should have contained text 'simpleTable_B3'.
- ... Table Column Should Contain xpath=//*[@id="simpleTable"] 20 simpleTable_B3
+ ... Table '//*[@id="simpleTable"]' column 20 did not contain text 'simpleTable_B3'.
+ ... Table Column Should Contain //*[@id="simpleTable"] 20 simpleTable_B3
-*** Keywords ***
-Table Column Should Contain With CSS And XPath Locators
- [Documentation] Table Column Should Contain With CSS And XPath Locators
- [Arguments] ${table id} ${col} ${expected}
- Run Table Keyword With CSS And XPath Locators
- ... Table Column Should Contain ${table id} ${col} ${expected}
+Zero is invalid column index
+ Run Keyword And Expect Error
+ ... ValueError: Row and column indexes must be non-zero.
+ ... Table Column Should Contain simpleTable 0 xxx
diff --git a/test/acceptance/keywords/tables/footer_should_contain.robot b/test/acceptance/keywords/tables/footer_should_contain.robot
index 3554212eb..e414418cc 100644
--- a/test/acceptance/keywords/tables/footer_should_contain.robot
+++ b/test/acceptance/keywords/tables/footer_should_contain.robot
@@ -1,22 +1,15 @@
*** Settings ***
-Documentation Tests for table footer
Resource table_resource.robot
*** Test Cases ***
Should Find Text In Footer
- [Template] Table Footer Should Contain With CSS And XPath Locators
- withHeadAndFoot withHeadAndFoot_AF1
- withHeadAndFoot withHeadAndFoot_CF1
- withHeadAndFoot withHeadAndFoot_AF2
- withHeadAndFoot withHeadAndFoot_CF2
+ [Template] Table Footer Should Contain
+ withHeadAndFoot withHeadAndFoot_AF1
+ id:withHeadAndFoot withHeadAndFoot_CF1
+ css:#withHeadAndFoot withHeadAndFoot_AF2
+ withHeadAndFoot withHeadAndFoot_CF2
Should Give Error Message When Content Not Found In Table Footer
Run Keyword And Expect Error
- ... Footer in table identified by 'withHeadAndFoot' should have contained text 'withHeadAndFoot_B2'.
+ ... Table 'withHeadAndFoot' footer did not contain text 'withHeadAndFoot_B2'.
... Table Footer Should Contain withHeadAndFoot withHeadAndFoot_B2
-
-*** Keywords ***
-Table Footer Should Contain With CSS And XPath Locators
- [Arguments] ${tableId} ${content}
- Run Table Keyword With CSS And XPath Locators
- ... Table Footer Should Contain ${table id} ${content}
diff --git a/test/acceptance/keywords/tables/get_table_cell.robot b/test/acceptance/keywords/tables/get_table_cell.robot
index 125ec38bf..ed58a658a 100644
--- a/test/acceptance/keywords/tables/get_table_cell.robot
+++ b/test/acceptance/keywords/tables/get_table_cell.robot
@@ -1,40 +1,64 @@
*** Settings ***
-Documentation Tests cell contents
Resource table_resource.robot
*** Test Cases ***
Should Retrieve Text From Cell
- [Template] Table Cell Should Be Equal With CSS And XPath Locators
- simpleTable 1 1 simpleTable_A1
+ [Template] Table Cell Should Be Equal
+ simpleTable 1 1 simpleTable_A1
+ id:simpleTable -1 -1 simpleTable_C3
tableWithSingleHeader 1 1 tableWithSingleHeader_A1
tableWithSingleHeader 3 3 tableWithSingleHeader_C3
- withHeadAndFoot 1 2 withHeadAndFoot_BH1
- withHeadAndFoot 4 3 withHeadAndFoot_C2
- withHeadAndFoot 6 1 withHeadAndFoot_AF1
- mergedRows 2 1 mergedRows_B2
- mergedCols 1 2 mergedCols_C1
- formattedTable 1 1 formattedTable_A1
- formattedTable 1 4 formattedTable_D1
- formattedTable 2 2 formattedTable_B2
- formattedTable 2 3 formattedTable_ÄÖÜäöüß
- formattedTable 2 4 äöü€&äöü€&
+ css:#withHeadAndFoot 1 2 withHeadAndFoot_BH1
+ withHeadAndFoot 4 3 withHeadAndFoot_C2
+ withHeadAndFoot 6 1 withHeadAndFoot_AF1
+ withHeadAndFoot -2 -3 withHeadAndFoot_AF1
+ mergedRows 2 1 mergedRows_B2
+ mergedCols 1 2 mergedCols_C1
+ formattedTable 1 1 formattedTable_A1
+ formattedTable 1 4 formattedTable_D1
+ formattedTable 2 2 formattedTable_B2
+ formattedTable 2 3 formattedTable_ÄÖÜäöüß
+ formattedTable 2 4 äöü€&äöü€&
+
+Mixed th and td
+ [Template] Table Cell Should Be Equal
+ mixed-th-td 1 1 1.1 (th)
+ id:mixed-th-td 1 2 1.2 (td)
+ css:#mixed-th-td 1 3 1.3 (td)
+ //*[@id="mixed-th-td"] 2 2 2.2 (th)
+ mixed-th-td 3 2 3.2 (td)
+ mixed-th-td 4 2 4.2 (th)
+ mixed-th-td 5 2 5.2 (td)
+ mixed-th-td 6 2 6.2 (th)
+ mixed-th-td -1 -1 6.3 (th)
+ mixed-th-td -1 -2 6.2 (th)
+ mixed-th-td -1 -3 6.1 (td)
+ mixed-th-td -6 -3 1.1 (th)
+ mixed-th-td -6 -2 1.2 (td)
+ mixed-th-td -6 -1 1.3 (td)
Should Give Error Message When Content Not Found In Table Cell
Run Keyword And Expect Error
- ... Cell in table 'simpleTable' in row #1 and column #2 should have contained text 'simpleTable_B3'.
+ ... Table 'simpleTable' cell on row 1 and column 2 should have contained text 'simpleTable_B3' but it had 'simpleTable_B1'.
... Table Cell Should Contain simpleTable 1 2 simpleTable_B3
Should Give Error Message When Index Out Of Bounds
Run Keyword And Expect Error
- ... Cell in table 'simpleTable' in row #10 and column #20 should have contained text 'simpleTable_B3'.
+ ... Table 'simpleTable' should have had at least 10 rows but had only 3.
... Table Cell Should Contain simpleTable 10 20 simpleTable_B3
+ Run Keyword And Expect Error
+ ... Table 'simpleTable' row 1 should have had at least 20 columns but had only 3.
+ ... Table Cell Should Contain simpleTable 1 20 simpleTable_B3
-*** Keywords ***
-Table Cell Should Be Equal With CSS And XPath Locators
- [Arguments] ${tableId} ${row} ${col} ${content}
- Run Table Keyword With CSS And XPath Locators
- ... Table Cell Should Be Equal ${table id} ${row} ${col} ${content}
+Zero is invalid row and column index
+ Run Keyword And Expect Error
+ ... ValueError: Both row and column must be non-zero, got row 0 and column 2.
+ ... Table Cell Should Contain simpleTable 0 2 xxx
+ Run Keyword And Expect Error
+ ... ValueError: Both row and column must be non-zero, got row -1 and column 0.
+ ... Table Cell Should Contain simpleTable -1 0 xxx
+*** Keywords ***
Table Cell Should Be Equal
[Arguments] ${tableId} ${row} ${col} ${content}
${cell}= Get Table Cell ${tableId} ${row} ${col}
diff --git a/test/acceptance/keywords/tables/header_should_contain.robot b/test/acceptance/keywords/tables/header_should_contain.robot
index d624e989e..b553a71a1 100644
--- a/test/acceptance/keywords/tables/header_should_contain.robot
+++ b/test/acceptance/keywords/tables/header_should_contain.robot
@@ -3,23 +3,17 @@ Resource table_resource.robot
*** Test Cases ***
Should Find Text In Header
- [Template] Table Header Should Contain With CSS And XPath Locators
- tableWithSingleHeader tableWithSingleHeader_A1
- tableWithSingleHeader tableWithSingleHeader_B1
- tableWithTwoHeaders tableWithTwoHeaders_A1
- tableWithTwoHeaders tableWithTwoHeaders_C2
- withHeadAndFoot withHeadAndFoot_AH1
- withHeadAndFoot withHeadAndFoot_CH1
- withHeadAndFoot withHeadAndFoot_AH2
- withHeadAndFoot withHeadAndFoot_BH2
+ [Template] Table Header Should Contain
+ tableWithSingleHeader tableWithSingleHeader_A1
+ id:tableWithSingleHeader tableWithSingleHeader_B1
+ css:#tableWithTwoHeaders tableWithTwoHeaders_A1
+ tableWithTwoHeaders tableWithTwoHeaders_C2
+ withHeadAndFoot withHeadAndFoot_AH1
+ withHeadAndFoot withHeadAndFoot_CH1
+ withHeadAndFoot withHeadAndFoot_AH2
+ withHeadAndFoot withHeadAndFoot_BH2
Should Give Error Message When Content Not Found In Table Header
Run Keyword And Expect Error
- ... Header in table identified by 'withHeadAndFoot' should have contained text 'withHeadAndFoot_B2'.
+ ... Table 'withHeadAndFoot' header did not contain text 'withHeadAndFoot_B2'.
... Table Header Should Contain withHeadAndFoot withHeadAndFoot_B2
-
-*** Keywords ***
-Table Header Should Contain With CSS And XPath Locators
- [Arguments] ${table id} ${expected}
- Run Table Keyword With CSS And XPath Locators Table Header Should Contain
- ... ${table id} ${expected}
diff --git a/test/acceptance/keywords/tables/row_should_contain.robot b/test/acceptance/keywords/tables/row_should_contain.robot
index 544b9a293..af04cefe1 100644
--- a/test/acceptance/keywords/tables/row_should_contain.robot
+++ b/test/acceptance/keywords/tables/row_should_contain.robot
@@ -1,44 +1,42 @@
*** Settings ***
-Documentation Tests table rows content
Resource table_resource.robot
*** Test Cases ***
Should Find Text In Specific Row
- [Template] Table Row Should Contain With CSS And XPath Locators
- simpleTable 1 simpleTable_A1
- simpleTable 3 simpleTable_C3
- simpleWithNested 1 simpleWithNested_A1
- simpleWithNested 1 nestedTable_A1
- nestedTable 1 nestedTable_A1
- nestedTable 3 nestedTable_C3
+ [Template] Table Row Should Contain
+ simpleTable 1 simpleTable_A1
+ id:simpleTable 3 simpleTable_C3
+ simpleWithNested 1 simpleWithNested_A1
+ simpleWithNested 1 nestedTable_A1
+ css:#nestedTable 1 nestedTable_A1
+ nestedTable 3 nestedTable_C3
tableWithSingleHeader 1 tableWithSingleHeader_B1
tableWithSingleHeader 2 tableWithSingleHeader_B2
- withHeadAndFoot 2 withHeadAndFoot_B2
- mergedRows 1 mergedRows_A1
- mergedCols 2 mergedCols_B2
- formattedTable 1 formattedTable_A1
- formattedTable 1 formattedTable_B1
- formattedTable 1 formattedTable_C1
- formattedTable 2 formattedTable_A2
- formattedTable 2 formattedTable_B2
- formattedTable 2 formattedTable_ÄÖÜäöüß
- formattedTable 2 äöü€&äöü€&
+ withHeadAndFoot 2 withHeadAndFoot_B2
+ //*[@id="mergedRows"] 1 mergedRows_A1
+ mergedCols 2 mergedCols_B2
+ formattedTable 1 formattedTable_A1
+ formattedTable 1 formattedTable_B1
+ formattedTable 1 formattedTable_C1
+ formattedTable 2 formattedTable_A2
+ formattedTable 2 formattedTable_B2
+ formattedTable 2 formattedTable_ÄÖÜäöüß
+ formattedTable 2 äöü€&äöü€&
Should Find Text In Specific Row with CSS Specific Mechanics
Table Row Should Contain formattedTable 1 formattedTable_D1
Should Give Error Message When Content Not Found In Table Row
Run Keyword And Expect Error
- ... Row #2 in table identified by 'simpleTable' should have contained text 'simpleTable_B3'.
+ ... Table 'simpleTable' row 2 did not contain text 'simpleTable_B3'.
... Table Row Should Contain simpleTable 2 simpleTable_B3
Should Give Error Message When Row Number Out Of Bounds
Run Keyword And Expect Error
- ... Row #20 in table identified by 'simpleTable' should have contained text 'simpleTable_B3'.
+ ... Table 'simpleTable' row 20 did not contain text 'simpleTable_B3'.
... Table Row Should Contain simpleTable 20 simpleTable_B3
-*** Keywords ***
-Table Row Should Contain With CSS And XPath Locators
- [Arguments] ${table id} ${row} ${expected}
- Run Table Keyword With CSS And XPath Locators Table Row Should Contain
- ... ${table id} ${row} ${expected}
+Zero is invalid column index
+ Run Keyword And Expect Error
+ ... ValueError: Row and column indexes must be non-zero.
+ ... Table Row Should Contain simpleTable 0 xxx
diff --git a/test/acceptance/keywords/tables/table_resource.robot b/test/acceptance/keywords/tables/table_resource.robot
index 651b03c47..ca2eb42d3 100644
--- a/test/acceptance/keywords/tables/table_resource.robot
+++ b/test/acceptance/keywords/tables/table_resource.robot
@@ -1,14 +1,8 @@
*** Settings ***
-Documentation Keywords to test tables
Resource ../../resource.robot
*** Keywords ***
Run Table Keyword With CSS And XPath Locators
[Arguments] ${keyword} ${table id} @{args}
Run Keyword ${keyword} ${table id} @{args}
- ${xpath}= Get Table XPath ${table id}
- Run Keyword ${keyword} ${xpath} @{args}
-
-Get Table XPath
- [Arguments] ${table id}
- [Return] xpath=//table[@id="${table id}"]
+ Run Keyword ${keyword} //table[@id="${table id}"] @{args}
diff --git a/test/acceptance/keywords/tables/table_should_contain.robot b/test/acceptance/keywords/tables/table_should_contain.robot
index 6d75030e9..757e4e25e 100644
--- a/test/acceptance/keywords/tables/table_should_contain.robot
+++ b/test/acceptance/keywords/tables/table_should_contain.robot
@@ -1,51 +1,32 @@
*** Settings ***
-Documentation Tests table contents
Resource table_resource.robot
*** Test Cases ***
Should Find Text In Table Content
- [Template] Verify Table Contains With CSS And XPath Locators
- simpleTable simpleTable_A1
- simpleTable simpleTable_C3
- simpleWithNested simpleWithNested_A1
- simpleWithNested nestedTable_A1
- nestedTable nestedTable_A1
- nestedTable nestedTable_C3
+ [Template] Table Should Contain
+ simpleTable simpleTable_A1
+ id:simpleTable simpleTable_C3
+ css:#simpleWithNested simpleWithNested_A1
+ simpleWithNested nestedTable_A1
+ nestedTable nestedTable_A1
+ nestedTable nestedTable_C3
tableWithSingleHeader tableWithSingleHeader_B1
tableWithSingleHeader tableWithSingleHeader_B2
- withHeadAndFoot withHeadAndFoot_AH1
- withHeadAndFoot withHeadAndFoot_B2
- withHeadAndFoot withHeadAndFoot_CF1
- mergedRows mergedRows_A1
- mergedCols mergedCols_B2
- formattedTable formattedTable_A1
- formattedTable formattedTable_B1
- formattedTable formattedTable_C1
- formattedTable formattedTable_A2
- formattedTable formattedTable_B2
- formattedTable formattedTable_ÄÖÜäöüß
- formattedTable äöü€&äöü€&
-
-Should Find Text In Table Content with CSS Specific Mechanics
- Table Should Contain formattedTable formattedTable_D1
+ withHeadAndFoot withHeadAndFoot_AH1
+ withHeadAndFoot withHeadAndFoot_B2
+ withHeadAndFoot withHeadAndFoot_CF1
+ //*[@id="mergedRows"] mergedRows_A1
+ mergedCols mergedCols_B2
+ formattedTable formattedTable_A1
+ formattedTable formattedTable_B1
+ formattedTable formattedTable_C1
+ formattedTable formattedTable_D1
+ formattedTable formattedTable_A2
+ formattedTable formattedTable_B2
+ formattedTable formattedTable_ÄÖÜäöüß
+ formattedTable äöü€&äöü€&
Should Give Error Message When Content Not Found In Table
- [Template] Table Should Contain Fails With CSS And XPath Locators
- simpleTable Not here
-
-*** Keywords ***
-Verify Table Contains With CSS And XPath Locators
- [Arguments] ${table id} ${expected}
- Run Table Keyword With CSS And XPath Locators Table Should Contain
- ... ${table id} ${expected}
-
-Table Should Contain Fails With CSS And XPath Locators
- [Arguments] ${table id} ${expected}
- Run Table Keyword With CSS And XPath Locators Table Should Contain Fails
- ... ${table id} ${expected}
-
-Table Should Contain Fails
- [Arguments] ${locator} ${expected}
- ${err}= Set Variable
- ... Table identified by '${locator}' should have contained text '${expected}'.
- Run Keyword And Expect Error ${err} Table Should Contain ${locator} ${expected}
+ Run Keyword And Expect Error
+ ... Table 'simpleTable' did not contain text 'Not here'.
+ ... Table Should Contain simpleTable Not here
diff --git a/test/resources/html/tables/tables.html b/test/resources/html/tables/tables.html
index 60864dd4f..77cc48983 100644
--- a/test/resources/html/tables/tables.html
+++ b/test/resources/html/tables/tables.html
@@ -166,6 +166,17 @@ Table with thead, tfoot and tbody sections
+
+Table with mixed th and td
+
+ | 1.1 (th) | 1.2 (td) | 1.3 (td) |
+ | 2.1 (td) | 2.2 (th) | 2.3 (td) |
+ | 3.1 (td) | 3.2 (td) | 3.3 (th) |
+ | 4.1 (th) | 4.2 (th) | 4.3 (td) |
+ | 5.1 (th) | 5.2 (td) | 5.3 (th) |
+ | 6.1 (td) | 6.2 (th) | 6.3 (th) |
+
+
Table With Merged Cells In a Row
diff --git a/test/unit/locators/test_tableelementfinder.py b/test/unit/locators/test_tableelementfinder.py
index ceaf638be..e6ec6a0d1 100644
--- a/test/unit/locators/test_tableelementfinder.py
+++ b/test/unit/locators/test_tableelementfinder.py
@@ -1,6 +1,6 @@
import unittest
-from mockito import mock, verify, when, unstub
+from mockito import mock, when, unstub
from SeleniumLibrary.locators.tableelementfinder import TableElementFinder
@@ -15,41 +15,22 @@ def setUp(self):
def tearDown(self):
unstub()
- def test_find_by_col(self):
- element = mock()
- xpath = ['//tr//*[self::td or self::th][1]']
- when(self.finder)._search_in_locators('id:table', xpath,
- 'content').thenReturn(element)
- self.finder.find_by_col('id:table', 1, 'content')
+ 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')
- xpath = ['//tbody/tr/td[position()=last()-(2-1)]',
- '//tbody/tr/td[position()=last()-(2-1)]']
- when(self.finder)._search_in_locators('id:table', xpath,
- 'content').thenReturn(element)
- self.finder.find_by_col('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')
def test_find_by_row(self):
- element = mock()
- xpath = ['//tr[2]//*']
- when(self.finder)._search_in_locators('xpath=//table', xpath,
- 'content').thenReturn(element)
+ xpath = '//tr[2]'
+ when(self.finder)._find('xpath=//table', xpath, 'content').thenReturn(mock())
self.finder.find_by_row('xpath=//table', 2, 'content')
- xpath = ['//tbody/tr[position()=last()-(3-1)]']
- when(self.finder)._search_in_locators('xpath=//table', xpath,
- 'content').thenReturn(element)
+ 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')
-
- def test_by_search_in_locators(self):
- xpath = ['//th']
- table = mock()
- element1 = mock()
- element2 = mock()
- element1.text = 'not here'
- element2.text = 'content'
- table_elements = [element1, element2]
- when(self.ctx._element_finder).find(
- 'css=table', None, True, True, None).thenReturn(table)
- when(self.ctx._element_finder).find(
- xpath[0], None, False, False, table).thenReturn(table_elements)
- self.finder._search_in_locators('css=table', xpath, 'content')
|