Blame view

src/main/java/pl/labno/bernard/htmlunified/WebClientUtils.java 9.76 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
import java.util.Map;

public class WebClientUtils {

    private static long defaultCheckInterval = 500;
tomek authored
24
bernard authored
25 26
    private static long defaultTimeout = 10000;
tomek authored
27 28
    public static long getDefaultCheckInterval()
    {
bernard authored
29 30 31
        return defaultCheckInterval;
    }
tomek authored
32 33
    public static void setDefaultCheckInterval(long defaultCheckInterval)
    {
bernard authored
34 35 36
        WebClientUtils.defaultCheckInterval = defaultCheckInterval;
    }
tomek authored
37 38
    public static long getDefaultTimeout()
    {
bernard authored
39 40 41
        return defaultTimeout;
    }
tomek authored
42 43
    public static void setDefaultTimeout(long defaultTimeout)
    {
bernard authored
44 45 46
        WebClientUtils.defaultTimeout = defaultTimeout;
    }
tomek authored
47 48
    public static int waitForJSJob(String message, WebClient webClient)
    {
bernard authored
49
        return waitForJSJob(message, webClient, webClient.waitForBackgroundJavaScript(10) - 1);
bernard authored
50 51
    }
tomek authored
52 53
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount)
    {
bernard authored
54
        return waitForJSJob(message, webClient, initialJobCount, defaultTimeout);
bernard authored
55 56
    }
tomek authored
57 58
    public static int waitForJSJob(WebClient webClient, int initialJobCount, int timeout)
    {
bernard authored
59
        return waitForJSJob(null, webClient, initialJobCount, timeout);
bernard authored
60 61
    }
tomek authored
62 63
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, long timeout)
    {
bernard authored
64 65 66
        return waitForJSJob(message, webClient, initialJobCount, timeout, defaultCheckInterval);
    }
tomek authored
67 68
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, int timeout)
    {
bernard authored
69 70 71
        return waitForJSJob(message, webClient, initialJobCount, timeout, defaultCheckInterval);
    }
tomek authored
72 73
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, long timeout, long checkInterval)
    {
bernard authored
74 75 76 77 78
        int jobs;
        long startTime = System.currentTimeMillis();
        do {
            jobs = webClient.waitForBackgroundJavaScript(checkInterval);
            if (startTime + timeout < System.currentTimeMillis()) {
tomek authored
79 80
                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
81 82
            }
        } while (jobs > initialJobCount);
bernard authored
83
        System.out.println("Waiting" + (message == null ? "" : " for " + message) + " took: " + (System.currentTimeMillis() - startTime) + "ms");
bernard authored
84 85 86 87 88 89 90 91
        return jobs;
    }

    /**
     * Returns list of suggestions from rich:suggestionBox
     *
     * @param suggestion suggestionBox element
     * @param column     column of suggestionBox to extract text from
tomek authored
92
     *
bernard authored
93 94
     * @return list of suggestions
     */
tomek authored
95 96
    public static Map<String, HtmlTableCell> getSuggestions(HtmlElement suggestion, int column)
    {
bernard authored
97 98 99 100 101
        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
102 103 104 105 106 107
            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
108 109 110
        }
        return suggestions;
    }
bernard authored
111
tomek authored
112 113
    public static void forceWait(int timeout)
    {
bernard authored
114 115 116 117 118 119 120 121 122 123 124 125
        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
126
tomek authored
127 128
    public static void executeAjaxReRenderedScripts(HtmlPage page)
    {
bernard authored
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        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
155
tomek authored
156 157
    public static void setColorPickerValue(WebClient webClient, HtmlElement colorPicker, String hex) throws IOException
    {
tomek authored
158 159 160 161 162 163
        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();
    }
tomek authored
164 165
    public static void setColorPickerValue(WebClient webClient, HtmlElement colorPicker, int red, int green, int blue) throws IOException
    {
tomek authored
166 167 168 169 170 171 172
        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
173 174

    @SuppressWarnings("unchecked")
tomek authored
175 176
    public static List<HtmlTableRow> getTableRows(HtmlTable table)
    {
tomek authored
177 178 179
        return (List<HtmlTableRow>) table.getByXPath(".//*[contains(@class,'rich-table-row')]");
    }
tomek authored
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    /**
     * Checks if a specified cell in given table contains searched text.
     *
     * @param table        HtmlTable element in which text is searched.
     * @param cellNumber   Number of column of the table in which text is searched.
     * @param searchedText Text to be searched
     *
     * @return True if text was found, false otherwise.
     */
    public static boolean contains(HtmlTable table, int cellNumber, String searchedText)
    {
        List<HtmlTableRow> rows = getTableRows(table);
        for (HtmlTableRow row : rows) {
            if (row.getCell(cellNumber).getTextContent().contains(searchedText)) {
                return true;
            }
        }
        return false;
    }
tomek authored
200
    @SuppressWarnings("unchecked")
tomek authored
201 202
    public static List<HtmlSpan> getScheduleEventTitles(HtmlElement schedule)
    {
tomek authored
203 204 205
        return (List<HtmlSpan>) schedule.getByXPath(".//*[@class='fc-event-title']");
    }
tomek authored
206 207
    public static void switchScheduleToNextMonth(HtmlElement schedule) throws IOException
    {
tomek authored
208 209 210
        ((HtmlElement) schedule.getByXPath(".//*[contains(@class,'fc-button-next')]").get(0)).click();
    }
tomek authored
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    public static void switchScheduleToMonthlyView(HtmlElement schedule) throws IOException
    {
        ((HtmlElement) schedule.getByXPath(".//*[contains(@class,'fc-button-month')]").get(0)).click();
    }

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

    public static void switchScheduleToDailyView(HtmlElement schedule) throws IOException
    {
        ((HtmlElement) schedule.getByXPath(".//*[contains(@class,'fc-button-agendaDay')]").get(0)).click();
    }
tomek authored
226 227 228 229 230 231
    /**
     * 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
tomek authored
232
     *
tomek authored
233 234
     * @return list of schedule cells
     */
tomek authored
235 236
    public static HtmlTableDataCell getScheduleDayCell(HtmlElement schedule, int dayOfMonth)
    {
tomek authored
237
        return (HtmlTableDataCell) schedule.getByXPath(".//td[contains(@class,'fc-day') and not(contains(@class,'fc-other-month'))]").get(dayOfMonth - 1);
tomek authored
238
    }
bernard authored
239
}