Blame view

src/main/java/pl/labno/bernard/htmlunified/WebClientUtils.java 8.33 KB
bernard authored
1 2 3
package pl.labno.bernard.htmlunified;

import com.gargoylesoftware.htmlunit.WebClient;
bernard authored
4
import com.gargoylesoftware.htmlunit.html.DomNode;
bernard authored
5 6
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
tomek authored
7
import com.gargoylesoftware.htmlunit.html.HtmlInput;
bernard authored
8
import com.gargoylesoftware.htmlunit.html.HtmlPage;
tomek authored
9 10
import com.gargoylesoftware.htmlunit.html.HtmlSpan;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
bernard authored
11
import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
tomek authored
12
import com.gargoylesoftware.htmlunit.html.HtmlTableDataCell;
tomek authored
13
import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
bernard authored
14
tomek authored
15
import java.io.IOException;
bernard authored
16
import java.util.ArrayList;
bernard authored
17
import java.util.HashMap;
bernard authored
18
import java.util.List;
bernard authored
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
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;
    }
bernard authored
42 43
    public static int waitForJSJob(String message, WebClient webClient) {
        return waitForJSJob(message, webClient, webClient.waitForBackgroundJavaScript(10) - 1);
bernard authored
44 45
    }
bernard authored
46 47
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount) {
        return waitForJSJob(message, webClient, initialJobCount, defaultTimeout);
bernard authored
48 49
    }
bernard authored
50 51
    public static int waitForJSJob(WebClient webClient, int initialJobCount, int timeout) {
        return waitForJSJob(null, webClient, initialJobCount, timeout);
bernard authored
52 53
    }
bernard authored
54 55 56 57 58 59 60 61 62
    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) {
bernard authored
63 64 65 66 67
        int jobs;
        long startTime = System.currentTimeMillis();
        do {
            jobs = webClient.waitForBackgroundJavaScript(checkInterval);
            if (startTime + timeout < System.currentTimeMillis()) {
bernard authored
68
                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!");
bernard authored
69 70
            }
        } while (jobs > initialJobCount);
bernard authored
71
        System.out.println("Waiting" + (message == null ? "" : " for " + message) + " took: " + (System.currentTimeMillis() - startTime) + "ms");
bernard authored
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
        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<String, HtmlTableCell> getSuggestions(HtmlElement suggestion, int column) {
        final Map<String, HtmlTableCell> suggestions = new HashMap<String, HtmlTableCell>();
        final HtmlElement suggestElement = suggestion.getElementById(suggestion.getId() + ":suggest");
        @SuppressWarnings("unchecked")
        final DomNodeList<HtmlElement> suggestionRows = suggestElement.getElementsByTagName("tr");
        for (HtmlElement row : suggestionRows) {
tomek authored
88 89 90 91 92 93
            if (!row.getId().endsWith("NothingLabel")) {
                @SuppressWarnings("unchecked")
                final DomNodeList<HtmlElement> cells = row.getElementsByTagName("td");
                final HtmlTableCell cell = (HtmlTableCell) cells.get(column + 1);
                suggestions.put(cell.asText(), cell);
            }
bernard authored
94 95 96
        }
        return suggestions;
    }
bernard authored
97 98 99 100 101 102 103 104 105 106 107 108 109 110

    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());
    }
bernard authored
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

    public static void executeAjaxReRenderedScripts(HtmlPage page) {
        final DomNodeList<HtmlElement> scripts = page.getElementsByTagName("script");
        /**
         * We cannot iterate over html DomNodeList cause it depends on sibling relationship which we will modify.
         */
        final List<HtmlElement> scriptsList = new ArrayList<HtmlElement>();
        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);
                }
            }
        }
    }
tomek authored
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

    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();
    }
tomek authored
155 156 157 158 159 160 161

    @SuppressWarnings("unchecked")
    public static List<HtmlTableRow> getTableRows(HtmlTable table) {
        return (List<HtmlTableRow>) table.getByXPath(".//*[contains(@class,'rich-table-row')]");
    }

    @SuppressWarnings("unchecked")
tomek authored
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    public static List<HtmlSpan> getScheduleEventTitles(HtmlElement schedule) {
        return (List<HtmlSpan>) schedule.getByXPath(".//*[@class='fc-event-title']");
    }

    public static void switchScheduleToNextMonth(HtmlElement schedule) throws IOException {
        ((HtmlElement) schedule.getByXPath(".//*[contains(@class,'fc-button-next')]").get(0)).click();
    }

    /**
     * IMPORTANT: Because of bugs in htmlunit and jsfunit which make schedule component render improperly this method should be used only to retrieve
     * cell elements from the first row of schedule grid. Any operations on cell elements from other rows are likely to cause error.
     *
     * @param schedule   schedule element
     * @param dayOfMonth number of day of month representing cell you wish to retrieve
     * @return list of schedule cells
     */
    public static HtmlTableDataCell getScheduleDayCell(HtmlElement schedule, int dayOfMonth) {
        return (HtmlTableDataCell) schedule.getByXPath(".//td[contains(@class,'fc-day') and not(contains(@class,'fc-other-month'))]").get(dayOfMonth - 1);
tomek authored
180
    }
bernard authored
181
}