WebClientUtils.java
9.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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.HtmlTableDataCell;
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<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) {
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);
}
}
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<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);
}
}
}
}
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<HtmlTableRow> getTableRows(HtmlTable table)
{
return (List<HtmlTableRow>) table.getByXPath(".//*[contains(@class,'rich-table-row')]");
}
/**
* 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;
}
@SuppressWarnings("unchecked")
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();
}
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();
}
/**
* 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);
}
}