From 8ccfbf1d99c40be72ea486a7e6776e6753ab7e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Tue, 7 Nov 2017 16:12:58 +0200 Subject: [PATCH 1/5] Code cleanup to table related keywords. Includes enhancing error messages. Somewhat related to #925. --- src/SeleniumLibrary/keywords/tableelement.py | 129 +++++++++--------- .../keywords/tables/col_should_contain.robot | 14 +- .../tables/footer_should_contain.robot | 3 +- .../keywords/tables/get_table_cell.robot | 40 ++++-- .../tables/header_should_contain.robot | 2 +- .../keywords/tables/row_should_contain.robot | 5 +- .../keywords/tables/table_resource.robot | 8 +- .../tables/table_should_contain.robot | 21 +-- 8 files changed, 106 insertions(+), 116 deletions(-) diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index ffb0bcbfe..272989a84 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -20,7 +20,7 @@ class TableElementKeywords(LibraryComponent): @keyword - def get_table_cell(self, table_locator, row, column, loglevel='INFO'): + def get_table_cell(self, locator, row, column, loglevel='INFO'): """Returns the content from a table cell. Row and column number start from 1. Header and footer rows are @@ -32,33 +32,45 @@ def get_table_cell(self, table_locator, row, column, loglevel='INFO'): See `Page Should Contain` for explanation about `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') + cells += rows[index].find_elements_by_xpath('./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'): + def table_cell_should_contain(self, 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 @@ -73,22 +85,17 @@ def table_cell_should_contain(self, table_locator, row, column, expected, loglev See `Page Should Contain` for explanation about `loglevel` argument. """ - 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'): + def table_column_should_contain(self, locator, column, expected, loglevel='INFO'): """Verifies that a specific column contains `expected`. The first leftmost column is column number 1. A negative column @@ -108,16 +115,14 @@ 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(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'): + def table_footer_should_contain(self, locator, expected, loglevel='INFO'): """Verifies that the table footer contains `expected`. With table footer can be described as any -element that is @@ -127,16 +132,14 @@ 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(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'): + def table_header_should_contain(self, locator, expected, loglevel='INFO'): """Verifies that the table header, i.e. any ... element, contains `expected`. To understand how tables are identified, please take a look at @@ -145,16 +148,14 @@ 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(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'): + def table_row_should_contain(self, locator, row, expected, loglevel='INFO'): """Verifies that a specific table row contains `expected`. The uppermost row is row number 1. A negative column @@ -171,16 +172,14 @@ 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(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'): + def table_should_contain(self, locator, expected, loglevel='INFO'): """Verifies that `expected` can be found somewhere in the table. To understand how tables are identified, please take a look at @@ -189,10 +188,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(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/test/acceptance/keywords/tables/col_should_contain.robot b/test/acceptance/keywords/tables/col_should_contain.robot index ddcffaedb..6feccacaf 100644 --- a/test/acceptance/keywords/tables/col_should_contain.robot +++ b/test/acceptance/keywords/tables/col_should_contain.robot @@ -4,22 +4,22 @@ 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 + simpleTable 2 simpleTable_B2 + simpleWithNested 2 nestedTable_A1 + nestedTable 3 nestedTable_C1 tableWithSingleHeader 1 tableWithSingleHeader_A1 tableWithSingleHeader 1 tableWithSingleHeader_A3 - tableWithTwoHeaders 2 tableWithTwoHeaders_B2 + tableWithTwoHeaders 2 tableWithTwoHeaders_B2 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 diff --git a/test/acceptance/keywords/tables/footer_should_contain.robot b/test/acceptance/keywords/tables/footer_should_contain.robot index 3554212eb..ac6441799 100644 --- a/test/acceptance/keywords/tables/footer_should_contain.robot +++ b/test/acceptance/keywords/tables/footer_should_contain.robot @@ -1,5 +1,4 @@ *** Settings *** -Documentation Tests for table footer Resource table_resource.robot *** Test Cases *** @@ -12,7 +11,7 @@ Should Find Text In Footer 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 *** diff --git a/test/acceptance/keywords/tables/get_table_cell.robot b/test/acceptance/keywords/tables/get_table_cell.robot index 125ec38bf..4a35be658 100644 --- a/test/acceptance/keywords/tables/get_table_cell.robot +++ b/test/acceptance/keywords/tables/get_table_cell.robot @@ -1,33 +1,45 @@ *** 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 + simpleTable 1 1 simpleTable_A1 + 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 äöü€&äöü€& + 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 äöü€&äöü€& 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 + +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 With CSS And XPath Locators diff --git a/test/acceptance/keywords/tables/header_should_contain.robot b/test/acceptance/keywords/tables/header_should_contain.robot index d624e989e..8aedb8214 100644 --- a/test/acceptance/keywords/tables/header_should_contain.robot +++ b/test/acceptance/keywords/tables/header_should_contain.robot @@ -15,7 +15,7 @@ Should Find Text In Header 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 *** diff --git a/test/acceptance/keywords/tables/row_should_contain.robot b/test/acceptance/keywords/tables/row_should_contain.robot index 544b9a293..e9ae1a3fd 100644 --- a/test/acceptance/keywords/tables/row_should_contain.robot +++ b/test/acceptance/keywords/tables/row_should_contain.robot @@ -1,5 +1,4 @@ *** Settings *** -Documentation Tests table rows content Resource table_resource.robot *** Test Cases *** @@ -29,12 +28,12 @@ Should Find Text In Specific Row with CSS Specific Mechanics 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 *** 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..a245c1d27 100644 --- a/test/acceptance/keywords/tables/table_should_contain.robot +++ b/test/acceptance/keywords/tables/table_should_contain.robot @@ -1,5 +1,4 @@ *** Settings *** -Documentation Tests table contents Resource table_resource.robot *** Test Cases *** @@ -30,22 +29,12 @@ Should Find Text In Table Content with CSS Specific Mechanics Table Should Contain formattedTable formattedTable_D1 Should Give Error Message When Content Not Found In Table - [Template] Table Should Contain Fails With CSS And XPath Locators - simpleTable Not here + Run Keyword And Expect Error + ... Table 'simpleTable' did not contain text 'Not here'. + ... Table Should Contain 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 Table Keyword With CSS And XPath Locators + ... Table Should Contain ${table id} ${expected} From b8147b4a75a5711e7eb1adfbf18f6e5602214612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Tue, 7 Nov 2017 19:45:27 +0200 Subject: [PATCH 2/5] Fix table keywords handling th cells. - Fix "Get Table Cell" and "Table Cell Should Contain" with mixed th/td. - Fix "Table Column Should Contain" with th when using negative indexes. Fixes #990. --- src/SeleniumLibrary/keywords/tableelement.py | 3 +-- .../locators/tableelementfinder.py | 3 +-- .../keywords/tables/col_should_contain.robot | 15 +++++++++++++++ .../keywords/tables/get_table_cell.robot | 17 +++++++++++++++++ test/resources/html/tables/tables.html | 11 +++++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index 272989a84..58efd5525 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -50,8 +50,7 @@ def _get_cell(self, locator, row, column): "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') - cells += rows[index].find_elements_by_xpath('./td') + 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." diff --git a/src/SeleniumLibrary/locators/tableelementfinder.py b/src/SeleniumLibrary/locators/tableelementfinder.py index 3d86eada9..004bfe15b 100644 --- a/src/SeleniumLibrary/locators/tableelementfinder.py +++ b/src/SeleniumLibrary/locators/tableelementfinder.py @@ -25,8 +25,7 @@ class TableElementFinder(ContextAware): '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)]'] + 'last-col': ['//tr//*[self::td or self::th][position()=last()-({col}-1)]'], } def find_by_content(self, table_locator, content): diff --git a/test/acceptance/keywords/tables/col_should_contain.robot b/test/acceptance/keywords/tables/col_should_contain.robot index 6feccacaf..867966bcb 100644 --- a/test/acceptance/keywords/tables/col_should_contain.robot +++ b/test/acceptance/keywords/tables/col_should_contain.robot @@ -5,12 +5,27 @@ Resource table_resource.robot Should Find Text In Specific Column [Template] Table Column Should Contain With CSS And XPath Locators simpleTable 2 simpleTable_B2 + simpleTable -2 simpleTable_B2 simpleWithNested 2 nestedTable_A1 nestedTable 3 nestedTable_C1 + nestedTable -1 nestedTable_C1 tableWithSingleHeader 1 tableWithSingleHeader_A1 tableWithSingleHeader 1 tableWithSingleHeader_A3 tableWithTwoHeaders 2 tableWithTwoHeaders_B2 +Mixed th and td + [Template] Table Column Should Contain With CSS And XPath Locators + mixed-th-td 1 1.1 (th) + mixed-th-td 1 2.1 (td) + mixed-th-td 2 1.2 (td) + 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 ... Table 'id:simpleTable' column 2 did not contain text 'simpleTable_C3'. diff --git a/test/acceptance/keywords/tables/get_table_cell.robot b/test/acceptance/keywords/tables/get_table_cell.robot index 4a35be658..2148d13f0 100644 --- a/test/acceptance/keywords/tables/get_table_cell.robot +++ b/test/acceptance/keywords/tables/get_table_cell.robot @@ -20,6 +20,23 @@ Should Retrieve Text From Cell formattedTable 2 3 formattedTable_ÄÖÜäöüß formattedTable 2 4 äöü€&äöü€& +Mixed th and td + [Template] Table Cell Should Be Equal With CSS And XPath Locators + mixed-th-td 1 1 1.1 (th) + mixed-th-td 1 2 1.2 (td) + mixed-th-td 1 3 1.3 (td) + 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 ... Table 'simpleTable' cell on row 1 and column 2 should have contained text 'simpleTable_B3' but it had 'simpleTable_B1'. 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

From c0a389f725c397568d4e59838c595a206b33366a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Wed, 8 Nov 2017 00:15:24 +0200 Subject: [PATCH 3/5] Cleanup TableElementFinder. --- src/SeleniumLibrary/keywords/tableelement.py | 2 +- .../locators/tableelementfinder.py | 72 ++++++++----------- .../keywords/tables/col_should_contain.robot | 5 ++ .../keywords/tables/row_should_contain.robot | 5 ++ test/unit/locators/test_tableelementfinder.py | 47 ++++-------- 5 files changed, 54 insertions(+), 77 deletions(-) diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index 58efd5525..b7d631e3c 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -114,7 +114,7 @@ def table_column_should_contain(self, locator, column, expected, loglevel='INFO' See `Page Should Contain Element` for explanation about `loglevel` argument. """ - element = self.table_element_finder.find_by_col(locator, column, expected) + element = self.table_element_finder.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 " diff --git a/src/SeleniumLibrary/locators/tableelementfinder.py b/src/SeleniumLibrary/locators/tableelementfinder.py index 004bfe15b..054a5000a 100644 --- a/src/SeleniumLibrary/locators/tableelementfinder.py +++ b/src/SeleniumLibrary/locators/tableelementfinder.py @@ -18,56 +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': ['//tr//*[self::td or self::th][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 867966bcb..dc0195b8e 100644 --- a/test/acceptance/keywords/tables/col_should_contain.robot +++ b/test/acceptance/keywords/tables/col_should_contain.robot @@ -36,6 +36,11 @@ Should Give Error Message When Column Number Out Of Bounds ... Table '//*[@id="simpleTable"]' column 20 did not contain text 'simpleTable_B3'. ... Table Column Should Contain //*[@id="simpleTable"] 20 simpleTable_B3 +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 + *** Keywords *** Table Column Should Contain With CSS And XPath Locators [Documentation] Table Column Should Contain With CSS And XPath Locators diff --git a/test/acceptance/keywords/tables/row_should_contain.robot b/test/acceptance/keywords/tables/row_should_contain.robot index e9ae1a3fd..3de19cac8 100644 --- a/test/acceptance/keywords/tables/row_should_contain.robot +++ b/test/acceptance/keywords/tables/row_should_contain.robot @@ -36,6 +36,11 @@ Should Give Error Message When Row Number Out Of Bounds ... Table 'simpleTable' row 20 did not contain text 'simpleTable_B3'. ... Table Row Should Contain simpleTable 20 simpleTable_B3 +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 + *** Keywords *** Table Row Should Contain With CSS And XPath Locators [Arguments] ${table id} ${row} ${expected} 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') From 19ae783b49c60094c63a9aa5b4bdce673847cc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Wed, 8 Nov 2017 00:43:53 +0200 Subject: [PATCH 4/5] Clean-up table test execution. Earlier most table tests were run both using table locator as the default strategy and as XPATH. This has several problems: - It made test system unnecessarily complex. - Running most tests twice increased execution time considerable. - It wasn't possible to use any other locator strategy. - Keyword names said tests would be run using CSS and XPATH locators but that wasn't true. This system was now removed. Tests were changed to use ID, CSS and XPATH strategies here and there. --- .../keywords/tables/col_should_contain.robot | 21 +++----- .../tables/footer_should_contain.robot | 16 ++----- .../keywords/tables/get_table_cell.robot | 19 +++----- .../tables/header_should_contain.robot | 24 ++++------ .../keywords/tables/row_should_contain.robot | 40 +++++++--------- .../tables/table_should_contain.robot | 48 ++++++++----------- 6 files changed, 65 insertions(+), 103 deletions(-) diff --git a/test/acceptance/keywords/tables/col_should_contain.robot b/test/acceptance/keywords/tables/col_should_contain.robot index dc0195b8e..424c90418 100644 --- a/test/acceptance/keywords/tables/col_should_contain.robot +++ b/test/acceptance/keywords/tables/col_should_contain.robot @@ -3,22 +3,22 @@ Resource table_resource.robot *** Test Cases *** Should Find Text In Specific Column - [Template] Table Column Should Contain With CSS And XPath Locators + [Template] Table Column Should Contain simpleTable 2 simpleTable_B2 - simpleTable -2 simpleTable_B2 + id:simpleTable -2 simpleTable_B2 simpleWithNested 2 nestedTable_A1 - nestedTable 3 nestedTable_C1 + css:#nestedTable 3 nestedTable_C1 nestedTable -1 nestedTable_C1 tableWithSingleHeader 1 tableWithSingleHeader_A1 tableWithSingleHeader 1 tableWithSingleHeader_A3 tableWithTwoHeaders 2 tableWithTwoHeaders_B2 Mixed th and td - [Template] Table Column Should Contain With CSS And XPath Locators + [Template] Table Column Should Contain mixed-th-td 1 1.1 (th) - mixed-th-td 1 2.1 (td) - mixed-th-td 2 1.2 (td) - mixed-th-td 2 2.2 (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) @@ -40,10 +40,3 @@ 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 - -*** 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} diff --git a/test/acceptance/keywords/tables/footer_should_contain.robot b/test/acceptance/keywords/tables/footer_should_contain.robot index ac6441799..e414418cc 100644 --- a/test/acceptance/keywords/tables/footer_should_contain.robot +++ b/test/acceptance/keywords/tables/footer_should_contain.robot @@ -3,19 +3,13 @@ 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 ... 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 2148d13f0..ed58a658a 100644 --- a/test/acceptance/keywords/tables/get_table_cell.robot +++ b/test/acceptance/keywords/tables/get_table_cell.robot @@ -3,12 +3,12 @@ Resource table_resource.robot *** Test Cases *** Should Retrieve Text From Cell - [Template] Table Cell Should Be Equal With CSS And XPath Locators + [Template] Table Cell Should Be Equal simpleTable 1 1 simpleTable_A1 - simpleTable -1 -1 simpleTable_C3 + id:simpleTable -1 -1 simpleTable_C3 tableWithSingleHeader 1 1 tableWithSingleHeader_A1 tableWithSingleHeader 3 3 tableWithSingleHeader_C3 - withHeadAndFoot 1 2 withHeadAndFoot_BH1 + css:#withHeadAndFoot 1 2 withHeadAndFoot_BH1 withHeadAndFoot 4 3 withHeadAndFoot_C2 withHeadAndFoot 6 1 withHeadAndFoot_AF1 withHeadAndFoot -2 -3 withHeadAndFoot_AF1 @@ -21,11 +21,11 @@ Should Retrieve Text From Cell formattedTable 2 4 äöü€&äöü€& Mixed th and td - [Template] Table Cell Should Be Equal With CSS And XPath Locators + [Template] Table Cell Should Be Equal mixed-th-td 1 1 1.1 (th) - mixed-th-td 1 2 1.2 (td) - mixed-th-td 1 3 1.3 (td) - mixed-th-td 2 2 2.2 (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) @@ -59,11 +59,6 @@ Zero is invalid row and column index ... Table Cell Should Contain simpleTable -1 0 xxx *** 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} - 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 8aedb8214..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 ... 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 3de19cac8..af04cefe1 100644 --- a/test/acceptance/keywords/tables/row_should_contain.robot +++ b/test/acceptance/keywords/tables/row_should_contain.robot @@ -3,25 +3,25 @@ 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 @@ -40,9 +40,3 @@ 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 - -*** 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} diff --git a/test/acceptance/keywords/tables/table_should_contain.robot b/test/acceptance/keywords/tables/table_should_contain.robot index a245c1d27..757e4e25e 100644 --- a/test/acceptance/keywords/tables/table_should_contain.robot +++ b/test/acceptance/keywords/tables/table_should_contain.robot @@ -3,38 +3,30 @@ 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 Run Keyword And Expect Error ... Table 'simpleTable' did not contain text 'Not here'. ... Table Should Contain 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} From 0560186fb3bac8ca95de6712a80810d9a583574d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= Date: Wed, 8 Nov 2017 01:54:25 +0200 Subject: [PATCH 5/5] Clean up table keyword docs. #925 --- src/SeleniumLibrary/keywords/tableelement.py | 122 +++++++++---------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index b7d631e3c..72a483958 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -21,15 +21,22 @@ class TableElementKeywords(LibraryComponent): @keyword def get_table_cell(self, locator, row, column, loglevel='INFO'): - """Returns the content from a table cell. + """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 ``-element. To understand how tables are - identified, please take a look at the `introduction`. + Any ```` 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(locator, expected) if element is None: @@ -139,13 +136,16 @@ def table_footer_should_contain(self, locator, expected, loglevel='INFO'): @keyword def table_header_should_contain(self, locator, expected, loglevel='INFO'): - """Verifies that the table header, i.e. any element, contains `expected`. + """Verifies table header contains text ``expected``. + + Any ``
`` and ```` elements anywhere in the table are + considered to be cells. + + See `Page Should Contain` for explanation about the ``loglevel`` + argument. """ row = int(row) column = int(column) @@ -70,19 +77,10 @@ def _get_rows(self, locator, count): @keyword def table_cell_should_contain(self, 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`. - - To understand how tables are identified, please take a look at - the `introduction`. + """Verifies table cell contains text ``expected``. - See `Page Should Contain` for explanation about `loglevel` argument. + See `Get Table Cell` that this keyword uses internally for + explanation about accepted arguments. """ content = self.get_table_cell(locator, row, column, loglevel) if expected not in content: @@ -95,24 +93,21 @@ def table_cell_should_contain(self, locator, row, column, expected, loglevel='IN @keyword def table_column_should_contain(self, locator, column, expected, loglevel='INFO'): - """Verifies that a specific column contains `expected`. + """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_column(locator, column, expected) if element is None: @@ -122,14 +117,16 @@ def table_column_should_contain(self, locator, column, expected, loglevel='INFO' @keyword def table_footer_should_contain(self, locator, expected, loglevel='INFO'): - """Verifies that the table footer contains `expected`. + """Verifies table footer contains text ``expected``. - With table footer can be described as any -element that is - child of a
`` element inside ``
...`` 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(locator, expected) if element is None: @@ -155,21 +155,21 @@ def table_header_should_contain(self, locator, expected, loglevel='INFO'): @keyword def table_row_should_contain(self, locator, row, expected, loglevel='INFO'): - """Verifies that a specific table row contains `expected`. + """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. - 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. + 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 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`. + 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 `loglevel` argument. + See `Page Should Contain Element` for explanation about the + ``loglevel`` argument. """ element = self.table_element_finder.find_by_row(locator, row, expected) if element is None: @@ -179,13 +179,13 @@ def table_row_should_contain(self, locator, row, expected, loglevel='INFO'): @keyword def table_should_contain(self, locator, expected, loglevel='INFO'): - """Verifies that `expected` can be found somewhere in the table. + """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(locator, expected) if element is None: