/* * $Id: TableControl.java 103519 2013-09-19 15:17:48Z nahlikm1 $ * * Copyright (c) 2010 AspectWorks, spol. s r.o. */ package com.pageobject; import java.util.ArrayList; import java.util.List; import org.springframework.util.StringUtils; import com.pageobject.component.AbstractComponent; import com.pageobject.component.Component; /** * Control for simple manipulation with HTML table. * * @author Pavel Muller * @version $Revision: 103519 $ */ @Component("prototype") public class TableControl extends AbstractComponent { private String previousPageButton = "xpath=//a/img[contains(@src,'prev-page.gif')]"; private String nextPageButton = "xpath=//a/img[contains(@src,'next-page.gif')]"; private String firstPageButton = "xpath=//a/img[contains(@src,'first-page.gif')]"; private String lastPageButton = "xpath=//a/img[contains(@src,'last-page.gif')]"; private String tableLocator; private String selectedRowAttributeName; private String selectedRowAttributeValue; /** * Configures location of a table within a page. * Set this property before use. * @param tableLocator an element locator */ public void setTableLocator(String tableLocator) { this.tableLocator = tableLocator; } /** * Returns a table locator on a page. * @return table XPath locator */ protected String getTableLocator() { if (!StringUtils.hasText(tableLocator)) { return "//table"; } return tableLocator; } /** * Get the previous page button locator. * * @return */ public String getPreviousPageButton() { return previousPageButton; } /** * Set the previous page button locator. * * @param previousPageButton */ public void setPreviousPageButton(String previousPageButton) { this.previousPageButton = previousPageButton; } /** * Get the next page button locator. * * @return */ public String getNextPageButton() { return nextPageButton; } /** * Set the next page button locator. * * @param nextPageButton */ public void setNextPageButton(String nextPageButton) { this.nextPageButton = nextPageButton; } /** * Get the first page button locator. * * @return */ public String getFirstPageButton() { return firstPageButton; } /** * Set the first page button locator. * * @param firstPageButton */ public void setFirstPageButton(String firstPageButton) { this.firstPageButton = firstPageButton; } /** * Get the last page button locator. * * @return */ public String getLastPageButton() { return lastPageButton; } /** * Set the last page button locator. * * @param lastPageButton */ public void setLastPageButton(String lastPageButton) { this.lastPageButton = lastPageButton; } /** * Set attribute name to recognize selected row. * Applies if the table supports row selection. * @param selectedRowAttributeName name of a <code>tr</code> attribute to inspect */ public void setSelectedRowAttributeName(String selectedRowAttributeName) { this.selectedRowAttributeName = selectedRowAttributeName; } /** * Returns attribute name to inspect to recognize if a table row is selected. * @return the selectedRowAttributeName */ protected String getSelectedRowAttributeName() { return selectedRowAttributeName; } /** * Set attribute value to recognize selected row. * It can be only part of the value such as an HTML class. * Applies if the table supports row selection. * @param selectedRowAttributeValue attribute value indicating selected row */ public void setSelectedRowAttributeValue(String selectedRowAttributeValue) { this.selectedRowAttributeValue = selectedRowAttributeValue; } /** * Returns attribute value to recognize if the row is selected. * @return the selectedRowAttributeValue */ protected String getSelectedRowAttributeValue() { return selectedRowAttributeValue; } /** * Returns a row locator in a table. Default is <code>/tbody/tr</code>. * @return row XPath locator */ protected String getRowLocator() { return "/tbody/tr"; } /** * Returns a cell locator in a row. Default is <code>/td</code>. * @return cell XPath locator */ protected String getCellLocator() { return "/td"; } /** * Returns a header locator in a table. Default is <code>/thead/tr</code>. * @return header row XPath locator */ protected String getHeaderLocator() { return "/thead/tr"; } /** * Returns a header cell locator in a row. Default is <code>/th</code>. * @return header cell XPath locator */ protected String getHeaderCellLocator() { return "/th"; } /** * Finds a column based on a header cell text, returning number of the * column or <code>null</code> if none was found. * * @param headerCellText * @return column number starting from 1 or <code>null</code> if not found */ public Integer findColumn(String headerCellText) { String headerCellLocator = tableLocator + getHeaderLocator() + getHeaderCellLocator(); int columnNumber = 1; while(isElementPresent(headerCellLocator + "[" + columnNumber + "]")) { String thText = getText(headerCellLocator + "[" + columnNumber + "]"); if(thText.contains(headerCellText)) { return columnNumber; } columnNumber++; } return null; } /** * Returns whether a row with a given row number is selected or not. * Set {@link #setSelectedRowAttributeName(String)} and {@link #setSelectedRowAttributeValue(String)} * if your table supports row selection. * @param rowNumber row to check, starting from 1 * @return whether the row is selected or not * @throws UnsupportedOperationException is the table does not support row selection */ public boolean isRowSelected(int rowNumber) { String rowAttrName = getSelectedRowAttributeName(); String rowAttrValue = getSelectedRowAttributeValue(); if (rowAttrName == null || rowAttrValue == null) { throw new UnsupportedOperationException("Table does not support row selection. " + "Configure attribute name and value to check selected rows."); } String rowLocator = getTableLocator() + getRowLocator() + "[" + rowNumber + "]"; String attributeValue; try { attributeValue = browser.getElementAttribute("xpath=" + rowLocator, rowAttrName); } catch (Exception e) { return false; } return attributeValue != null && attributeValue.contains(rowAttrValue); } /** * Returns number of rows in the table including all pages. * @return row count, 0 for empty table */ public int getRowCount() { int rowCount = getRowCountOnPage(); while (isElementPresent(nextPageButton)) { click(nextPageButton); rowCount += getRowCountOnPage(); } return rowCount; } /** * @return */ private int getRowCountOnPage() { String rowInTable = getTableLocator() + getRowLocator(); return browser.getElementCount("xpath=" + rowInTable); } /** * @param entity * @return */ public Integer findRow(TableEntity entity) { return findRow(entity.getSearchAttributes()); } /** * Finds a row in a table according to a given cell value to search. * Returns <code>null</code> if row not found. * @param cellValue cell value to search. Not only exact cell content but substrings too. * @return row number starting from 1 or <code>null</code> if not found */ public Integer findRow(String cellValue) { return findRow(new String[] {cellValue}); } /** * Finds a row in a table according to given cell values to search. * Use more cell values if the entity in the table does not have one unique key. * Returns <code>null</code> if row not found. * @param cellValue cell value to search. Not only exact cell content but substrings too. * @return row number starting from 1 or <code>null</code> if not found */ public Integer findRow(String[] cellValues) { Integer rowNumber = findRowOnPage(cellValues); if (rowNumber != null) { return rowNumber; } while (isElementPresent(nextPageButton)) { click(nextPageButton); rowNumber = findRowOnPage(cellValues); if (rowNumber != null) { return rowNumber; } } return null; } private Integer findRowOnPage(String[] cellValues) { String rowLocator = getTableLocator() + getRowLocator(); int rowNumber = 1; while (isElementPresent("xpath=" + rowLocator + "[" + rowNumber + "]")) { String rowContent = browser.getElementValue("xpath=" + rowLocator + "[" + rowNumber + "]"); boolean result = true; for (String cell : cellValues) { if (rowContent.indexOf(cell) == -1) { result = false; } } if (result == true) { return rowNumber; } rowNumber++; } return null; } /** * @param entity * @return */ public TableRow getRow(TableEntity entity) { return getRow(entity.getSearchAttributes()); } /** * Returns a row content in a table according to given cell value to search. * Returns <code>null</code> if row not found. * @param cellValues cell values to search in one row. Not only exact cell contents but substrings too. * @return row contents or <code>null</code> if not found */ public TableRow getRow(String cellValue) { return getRow(new String[] {cellValue}); } /** * Returns a row content in a table according to given cell values to search. * Use more cell values if the entity in the table does not have one unique key. * Returns <code>null</code> if row not found. * @param cellValues cell values to search in one row. Not only exact cell contents but substrings too. * @return row contents or <code>null</code> if not found */ public TableRow getRow(String[] cellValues) { Integer rowNumber = findRow(cellValues); if (rowNumber == null) { return null; } return getRowOnPage(rowNumber); } /** * Returns a row content of a given row. * @param rowNumber number of row starting from 1 * @return row control */ public TableRow getRowOnPage(int rowNumber) { TableRow row = new TableRow(); String cellLocator = getTableLocator() + getRowLocator() + "[" + rowNumber + "]" + getCellLocator(); int cellNumber = 1; while (isElementPresent("xpath=" + cellLocator + "[" + cellNumber + "]")) { String cellContent = browser.getElementValue("xpath=" + cellLocator + "[" + cellNumber + "]"); row.addCell(cellNumber, cellContent); cellNumber++; } return row; } /** * Returns all rows in a table. * @return all row controls, empty list if the table is empty */ public List<TableRow> getAllRows() { List<TableRow> table = new ArrayList<TableRow>(); int rowCount = getRowCountOnPage(); for (int i = rowCount; i > 0 ; i--) { TableRow row = getRowOnPage(i); table.add(0, row); } while (isElementPresent(nextPageButton)) { click(nextPageButton); rowCount = getRowCountOnPage(); for (int i = rowCount; i > 0 ; i--) { TableRow row = getRowOnPage(i); table.add(0, row); } } return table; } /** * Clicks on a specific row in the table. Does not handle the reloading * of current page. If it should cause a page refresh, you should use * {@link TableControl#clickOnRowAndWait(int)}. * * @param rowNumber - number of the row you want to click on */ public void clickOnRow(int rowNumber) { click("xpath=" + getTableLocator() + getRowLocator() + "[" + rowNumber + "]"); } /** * Display the last page of the table. */ public void gotoLastPage() { if (isElementPresent(lastPageButton)) { click(lastPageButton); } } /** * Display the first page of the table. */ public void gotoFirstPage() { if (isElementPresent(firstPageButton)) { click(firstPageButton); } } /** * Display the next page of the table. */ public void gotoNextPage() { if (isElementPresent(nextPageButton)) { click(nextPageButton); } } /** * Display the previous page of the table. */ public void gotoPreviousPage() { if (isElementPresent(previousPageButton)) { click(previousPageButton); } } }