package com.redheap.selenium.component; import java.util.ArrayList; import java.util.List; import org.openqa.selenium.Keys; import org.openqa.selenium.Platform; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; public class AdfTable extends AdfComponent { private static final String SUBID_disclosureID = "disclosureID"; // [99]disclosureId returns <a> element private static final String JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWKEY = JS_FIND_COMPONENT + "var child=comp.findComponent(arguments[1],arguments[2]); return child?child.getClientId():null"; private static final String JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWINDEX = JS_FIND_PEER + "var idx=peer.getRowKey(arguments[2]); if (!idx){return null}var child=comp.findComponent(arguments[1],idx); return child?child.getClientId():null"; private static final String JS_IS_ROW_DISCLOSED = JS_FIND_COMPONENT + "return comp.isDisclosed(arguments[1])===true"; private static final String JS_SCROLLTO_ROWINDEX = JS_FIND_COMPONENT + "comp.scrollToRowIndex(arguments[1])"; private static final String JS_GET_FOCUSED_ROWKEY = JS_FIND_PEER + "return peer.GetFocusedRowKey()"; private static final String JS_GET_ROWKEY = JS_FIND_PEER + "return peer.getRowKey(arguments[1])"; private static final String JS_GET_ROWINDEX = JS_FIND_PEER + "return peer.getRowIndex(arguments[1])"; private static final String JS_SELECTED_ROWS = JS_FIND_PEER + "var keys=Object.keys(comp.getSelectedRowKeys()); var retval=[]; keys.forEach(function(key){retval.push(peer.getRowIndex(key))}); return retval;"; private static final String JS_DISCLOSED_ROWS = JS_FIND_PEER + "var keys=Object.keys(comp.getDisclosedRowKeys()); var retval=[]; keys.forEach(function(key){retval.push(peer.getRowIndex(key))}); return retval;"; private static final String JS_GET_ROW_BY_INDEX = JS_FIND_PEER + "var rowinfo=peer.FindRowByKey(peer.getRowIndex(arguments[1])); if (rowinfo){return rowinfo.tr}else{return null}"; private static final String JS_GET_ROW_COUNT = JS_FIND_PEER + "return peer.GetRowCount();"; public AdfTable(WebDriver webDriver, String clientid) { super(webDriver, clientid); } public <T extends AdfComponent> T findAdfComponent(String relativeClientId, String rowKey) { String clientid = (String) executeScript(JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWKEY, getClientId(), relativeClientId, rowKey); if (clientid == null) { return null; } return AdfComponent.forClientId(getDriver(), clientid); } public <T extends AdfComponent> T findAdfComponent(String relativeClientId, int rowIndex) { scrollToRowIndex(rowIndex); // scroll to row (and possibly fetch additional data) String clientid = (String) executeScript(JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWINDEX, getClientId(), relativeClientId, rowIndex); if (clientid == null) { return null; } T retval = AdfComponent.forClientId(getDriver(), clientid); // TODO; would be niced to use TablePeer.scrollColumnIntoView but we haven't figured out a way to // determine column index for a component retval.scrollIntoView(); return retval; } public List<Integer> getSelectedRows() { return rowIndices((List<Long>) executeScript(JS_SELECTED_ROWS, getClientId())); } public List<Integer> getDisclosedRows() { return rowIndices((List<Long>) executeScript(JS_DISCLOSED_ROWS, getClientId())); } private List<Integer> rowIndices(List<Long> longs) { List<Integer> retval = new ArrayList<Integer>(longs.size()); for (Long l : longs) { retval.add(l.intValue()); } return retval; } public boolean isRowDisclosed(int rowIndex) { scrollToRowIndex(rowIndex); String rowkey = getRowKey(rowIndex); return (Boolean) executeScript(JS_IS_ROW_DISCLOSED, getClientId(), rowkey); } public void discloseRowDetail(int rowIndex) { scrollToRowIndex(rowIndex); // scroll the table rows WebElement link = findDisclosureLink(rowIndex); if (link != null) { scrollIntoView(link); // scroll the browser document link.click(); waitForPpr(); } } public void scrollToRowIndex(int rowIndex) { // could also accept a callback function executeScript(JS_SCROLLTO_ROWINDEX, getClientId(), rowIndex); waitForPpr(); } public String getFocusedRowKey() { return (String) executeScript(JS_GET_FOCUSED_ROWKEY, getClientId()); } /** * Returns the rowKey to identify a row based on its index. There is no guarantee that a row identified by a * rowKey can be found on the client since all the rows are not rendered on the client. Also keep in mind that * the rowKey on the client is not the same as the one on the server, since the server provides a mechanism for * converting client row keys into server row keys. * @param index the rowIndex of the row * @return the rowKey to identify a row if found otherwise null */ public String getRowKey(int index) { return (String) executeScript(JS_GET_ROWKEY, getClientId(), index); } /** * Returns the index of a row identified by rowKey. There is no guarantee that a row identified by a * rowKey can be found on the client since all the rows are not rendered on the client. Also keep in mind that * the rowKey on the client is not the same as the one on the server, since the server provides a mechanism for * converting client row keys into server row keys. * @param rowKey the client side rowKey that identifies the row * @return the index of a row for a row key if it is found otherwise -1 */ public int getRowIndex(String rowKey) { return ((Number) executeScript(JS_GET_ROWINDEX, getClientId(), rowKey)).intValue(); } public long getRowCount() { return ((Number) executeScript(JS_GET_ROW_COUNT, getClientId())).longValue(); } public void selectRow(int index) { scrollToRowIndex(index); WebElement row = findRow(index); row.click(); waitForPpr(); } public void selectToRow(int index) { scrollToRowIndex(index); WebElement row = findRow(index); new Actions(getDriver()).keyDown(Keys.SHIFT).click(row).keyUp(Keys.SHIFT).perform(); waitForPpr(); } public void selectAdditionalRow(int index) { scrollToRowIndex(index); WebElement row = findRow(index); final Keys key = isPlatform(Platform.MAC) ? Keys.COMMAND : Keys.CONTROL; new Actions(getDriver()).keyDown(key).click(row).keyUp(key).perform(); waitForPpr(); } protected WebElement findDisclosureLink(int index) { // warning: when a row is disclosed all rows lower in the tabel cannot be found due to a bug in // AdfDhtmlTableBasePeer.convertLocatorToClientId which doesn't account for the extra <tr> row // injected by the disclosed detailStamp return findSubIdElement("[" + index + "]" + SUBID_disclosureID); } protected WebElement findRow(int index) { return (WebElement) executeScript(JS_GET_ROW_BY_INDEX, getClientId(), String.valueOf(index)); } }