package pl.labno.bernard.htmlunified;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSpan;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WebClientUtils {
private static long defaultCheckInterval = 500;
private static long defaultTimeout = 10000;
public static long getDefaultCheckInterval() {
return defaultCheckInterval;
}
public static void setDefaultCheckInterval(long defaultCheckInterval) {
WebClientUtils.defaultCheckInterval = defaultCheckInterval;
}
public static long getDefaultTimeout() {
return defaultTimeout;
}
public static void setDefaultTimeout(long defaultTimeout) {
WebClientUtils.defaultTimeout = defaultTimeout;
}
public static int waitForJSJob(String message, WebClient webClient) {
return waitForJSJob(message, webClient, webClient.waitForBackgroundJavaScript(10) - 1);
}
public static int waitForJSJob(String message, WebClient webClient, int initialJobCount) {
return waitForJSJob(message, webClient, initialJobCount, defaultTimeout);
}
public static int waitForJSJob(WebClient webClient, int initialJobCount, int timeout) {
return waitForJSJob(null, webClient, initialJobCount, timeout);
}
public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, long timeout) {
return waitForJSJob(message, webClient, initialJobCount, timeout, defaultCheckInterval);
}
public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, int timeout) {
return waitForJSJob(message, webClient, initialJobCount, timeout, defaultCheckInterval);
}
public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, long timeout, long checkInterval) {
int jobs;
long startTime = System.currentTimeMillis();
do {
jobs = webClient.waitForBackgroundJavaScript(checkInterval);
if (startTime + timeout < System.currentTimeMillis()) {
throw new RuntimeException("Number of JavaScript jobs doesn't drop to initial level for " + timeout + " seconds. It's memory leak in your JavaScript rather then request taking so long!");
}
} while (jobs > initialJobCount);
System.out.println("Waiting" + (message == null ? "" : " for " + message) + " took: " + (System.currentTimeMillis() - startTime) + "ms");
return jobs;
}
/**
* Returns list of suggestions from rich:suggestionBox
*
* @param suggestion suggestionBox element
* @param column column of suggestionBox to extract text from
* @return list of suggestions
*/
public static Map getSuggestions(HtmlElement suggestion, int column) {
final Map suggestions = new HashMap();
final HtmlElement suggestElement = suggestion.getElementById(suggestion.getId() + ":suggest");
@SuppressWarnings("unchecked")
final DomNodeList suggestionRows = suggestElement.getElementsByTagName("tr");
for (HtmlElement row : suggestionRows) {
if (!row.getId().endsWith("NothingLabel")) {
@SuppressWarnings("unchecked")
final DomNodeList cells = row.getElementsByTagName("td");
final HtmlTableCell cell = (HtmlTableCell) cells.get(column + 1);
suggestions.put(cell.asText(), cell);
}
}
return suggestions;
}
public static void forceWait(int timeout) {
final long startTime = System.currentTimeMillis();
do {
try {
final long millis = startTime + timeout - System.currentTimeMillis();
if (millis > 0) {
Thread.sleep(millis);
}
} catch (InterruptedException ignore) {
} catch (IllegalArgumentException ignore) {
}
} while (startTime + timeout > System.currentTimeMillis());
}
public static void executeAjaxReRenderedScripts(HtmlPage page) {
final DomNodeList scripts = page.getElementsByTagName("script");
/**
* We cannot iterate over html DomNodeList cause it depends on sibling relationship which we will modify.
*/
final List scriptsList = new ArrayList();
for (HtmlElement element : scripts) {
scriptsList.add(element);
}
for (HtmlElement element : scriptsList) {
if (element.getChildNodes().size() > 1) {
element.removeChild(element.getFirstChild());
final DomNode sibling = element.getNextSibling();
final DomNode parentNode = element.getParentNode();
/**
* Script will be executed upon inserting into DOM tree, so we removed and add it again.
*/
if (sibling != null) {
parentNode.removeChild(element);
sibling.insertBefore(element);
} else {
parentNode.removeChild(element);
parentNode.appendChild(element);
}
}
}
}
public static void setColorPickerValue(WebClient webClient, HtmlElement colorPicker, String hex) throws IOException {
HtmlPage page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
colorPicker.click();
((HtmlInput) page.getElementById(colorPicker.getId() + "-colorPicker-hex")).setValueAttribute(hex);
page.getElementById(colorPicker.getId() + "-colorPicker-popup").getHtmlElementsByTagName("button").get(0).click();
}
public static void setColorPickerValue(WebClient webClient, HtmlElement colorPicker, int red, int green, int blue) throws IOException {
HtmlPage page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
colorPicker.click();
((HtmlInput) page.getElementById(colorPicker.getId() + "-colorPicker-rgb-r")).setValueAttribute(Integer.toString(red));
((HtmlInput) page.getElementById(colorPicker.getId() + "-colorPicker-rgb-g")).setValueAttribute(Integer.toString(green));
((HtmlInput) page.getElementById(colorPicker.getId() + "-colorPicker-rgb-b")).setValueAttribute(Integer.toString(blue));
page.getElementById(colorPicker.getId() + "-colorPicker-popup").getHtmlElementsByTagName("button").get(0).click();
}
@SuppressWarnings("unchecked")
public static List getTableRows(HtmlTable table) {
return (List) table.getByXPath(".//*[contains(@class,'rich-table-row')]");
}
@SuppressWarnings("unchecked")
public static List getScheduleEventTitles(HtmlElement schedule) {
final List titleElements = (List) schedule.getByXPath(".//*[@class='fc-event-title']");
List titles = new ArrayList(titleElements.size());
for (HtmlSpan o : titleElements) {
titles.add(o.asText());
}
return titles;
}
}