Chris@0
|
1 var __indexOf = [].indexOf || function (item) {
|
Chris@0
|
2 for (var i = 0, l = this.length; i < l; i++) {
|
Chris@0
|
3 if (i in this && this[i] === item) return i;
|
Chris@0
|
4 }
|
Chris@0
|
5 return -1;
|
Chris@0
|
6 };
|
Chris@0
|
7
|
Chris@0
|
8 var xpathStringLiteral = function (s) {
|
Chris@0
|
9 if (s.indexOf('"') === -1)
|
Chris@0
|
10 return '"' + s + '"';
|
Chris@0
|
11 if (s.indexOf("'") === -1)
|
Chris@0
|
12 return "'" + s + "'";
|
Chris@0
|
13 return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
|
Chris@0
|
14 };
|
Chris@0
|
15
|
Chris@0
|
16 Poltergeist.Browser = (function () {
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Creates the "browser" inside phantomjs
|
Chris@0
|
19 * @param owner
|
Chris@0
|
20 * @param width
|
Chris@0
|
21 * @param height
|
Chris@0
|
22 * @param jsErrors
|
Chris@0
|
23 * @constructor
|
Chris@0
|
24 */
|
Chris@0
|
25 function Browser(owner, width, height, jsErrors) {
|
Chris@0
|
26 this.owner = owner;
|
Chris@0
|
27 this.width = width || 1024;
|
Chris@0
|
28 this.height = height || 768;
|
Chris@0
|
29 this.pages = [];
|
Chris@0
|
30 this.js_errors = (typeof jsErrors === 'boolean') ? jsErrors : true;
|
Chris@0
|
31 this._debug = false;
|
Chris@0
|
32 this._counter = 0;
|
Chris@0
|
33 this.resetPage();
|
Chris@0
|
34 }
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * Resets the browser to a clean slate
|
Chris@0
|
38 * @return {Function}
|
Chris@0
|
39 */
|
Chris@0
|
40 Browser.prototype.resetPage = function () {
|
Chris@0
|
41 var _ref;
|
Chris@0
|
42 var self = this;
|
Chris@0
|
43
|
Chris@0
|
44 _ref = [0, []];
|
Chris@0
|
45 this._counter = _ref[0];
|
Chris@0
|
46 this.pages = _ref[1];
|
Chris@0
|
47
|
Chris@0
|
48 if (this.page != null) {
|
Chris@0
|
49 if (!this.page.closed) {
|
Chris@0
|
50 if (this.page.currentUrl() !== 'about:blank') {
|
Chris@0
|
51 this.page.clearLocalStorage();
|
Chris@0
|
52 }
|
Chris@0
|
53 this.page.release();
|
Chris@0
|
54 }
|
Chris@0
|
55 phantom.clearCookies();
|
Chris@0
|
56 }
|
Chris@0
|
57
|
Chris@0
|
58 this.page = this.currentPage = new Poltergeist.WebPage;
|
Chris@0
|
59 this.page.setViewportSize({
|
Chris@0
|
60 width: this.width,
|
Chris@0
|
61 height: this.height
|
Chris@0
|
62 });
|
Chris@0
|
63 this.page.handle = "" + (this._counter++);
|
Chris@0
|
64 this.pages.push(this.page);
|
Chris@0
|
65
|
Chris@0
|
66 return this.page.onPageCreated = function (newPage) {
|
Chris@0
|
67 var page;
|
Chris@0
|
68 page = new Poltergeist.WebPage(newPage);
|
Chris@0
|
69 page.handle = "" + (self._counter++);
|
Chris@0
|
70 return self.pages.push(page);
|
Chris@0
|
71 };
|
Chris@0
|
72 };
|
Chris@0
|
73
|
Chris@0
|
74 /**
|
Chris@0
|
75 * Given a page handle id, tries to get it from the browser page list
|
Chris@0
|
76 * @param handle
|
Chris@0
|
77 * @return {WebPage}
|
Chris@0
|
78 */
|
Chris@0
|
79 Browser.prototype.getPageByHandle = function (handle) {
|
Chris@0
|
80 var filteredPages;
|
Chris@0
|
81
|
Chris@0
|
82 //TODO: perhaps we should throw a PageNotFoundByHandle or something like that..
|
Chris@0
|
83 if (handle === null || typeof handle == "undefined") {
|
Chris@0
|
84 return null;
|
Chris@0
|
85 }
|
Chris@0
|
86
|
Chris@0
|
87 filteredPages = this.pages.filter(function (p) {
|
Chris@0
|
88 return !p.closed && p.handle === handle;
|
Chris@0
|
89 });
|
Chris@0
|
90
|
Chris@0
|
91 if (filteredPages.length === 1) {
|
Chris@0
|
92 return filteredPages[0];
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 return null;
|
Chris@0
|
96 };
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * Sends a debug message to the console
|
Chris@0
|
100 * @param message
|
Chris@0
|
101 * @return {*}
|
Chris@0
|
102 */
|
Chris@0
|
103 Browser.prototype.debug = function (message) {
|
Chris@0
|
104 if (this._debug) {
|
Chris@0
|
105 return console.log("poltergeist [" + (new Date().getTime()) + "] " + message);
|
Chris@0
|
106 }
|
Chris@0
|
107 };
|
Chris@0
|
108
|
Chris@0
|
109 /**
|
Chris@0
|
110 * Given a page_id and id, gets if possible the node in such page
|
Chris@0
|
111 * @param page_id
|
Chris@0
|
112 * @param id
|
Chris@0
|
113 * @return {Poltergeist.Node}
|
Chris@0
|
114 */
|
Chris@0
|
115 Browser.prototype.node = function (page_id, id) {
|
Chris@0
|
116 if (this.currentPage.id === page_id) {
|
Chris@0
|
117 return this.currentPage.get(id);
|
Chris@0
|
118 } else {
|
Chris@0
|
119 throw new Poltergeist.ObsoleteNode;
|
Chris@0
|
120 }
|
Chris@0
|
121 };
|
Chris@0
|
122
|
Chris@0
|
123 /**
|
Chris@0
|
124 * Returns the frameUrl related to the frame given by name
|
Chris@0
|
125 * @param frame_name
|
Chris@0
|
126 * @return {*}
|
Chris@0
|
127 */
|
Chris@0
|
128 Browser.prototype.frameUrl = function (frame_name) {
|
Chris@0
|
129 return this.currentPage.frameUrl(frame_name);
|
Chris@0
|
130 };
|
Chris@0
|
131
|
Chris@0
|
132 /**
|
Chris@0
|
133 * This method defines the rectangular area of the web page to be rasterized when render is invoked.
|
Chris@0
|
134 * If no clipping rectangle is set, render will process the entire web page.
|
Chris@0
|
135 * @param full
|
Chris@0
|
136 * @param selector
|
Chris@0
|
137 * @return {*}
|
Chris@0
|
138 */
|
Chris@0
|
139 Browser.prototype.set_clip_rect = function (full, selector) {
|
Chris@0
|
140 var dimensions, clipDocument, rect, clipViewport;
|
Chris@0
|
141
|
Chris@0
|
142 dimensions = this.currentPage.validatedDimensions();
|
Chris@0
|
143 clipDocument = dimensions.document;
|
Chris@0
|
144 clipViewport = dimensions.viewport;
|
Chris@0
|
145
|
Chris@0
|
146 if (full) {
|
Chris@0
|
147 rect = {
|
Chris@0
|
148 left: 0,
|
Chris@0
|
149 top: 0,
|
Chris@0
|
150 width: clipDocument.width,
|
Chris@0
|
151 height: clipDocument.height
|
Chris@0
|
152 };
|
Chris@0
|
153 } else {
|
Chris@0
|
154 if (selector != null) {
|
Chris@0
|
155 rect = this.currentPage.elementBounds(selector);
|
Chris@0
|
156 } else {
|
Chris@0
|
157 rect = {
|
Chris@0
|
158 left: 0,
|
Chris@0
|
159 top: 0,
|
Chris@0
|
160 width: clipViewport.width,
|
Chris@0
|
161 height: clipViewport.height
|
Chris@0
|
162 };
|
Chris@0
|
163 }
|
Chris@0
|
164 }
|
Chris@0
|
165
|
Chris@0
|
166 this.currentPage.setClipRect(rect);
|
Chris@0
|
167 return dimensions;
|
Chris@0
|
168 };
|
Chris@0
|
169
|
Chris@0
|
170 /**
|
Chris@0
|
171 * Kill the browser, i.e kill phantomjs current process
|
Chris@0
|
172 * @return {int}
|
Chris@0
|
173 */
|
Chris@0
|
174 Browser.prototype.exit = function () {
|
Chris@0
|
175 return phantom.exit(0);
|
Chris@0
|
176 };
|
Chris@0
|
177
|
Chris@0
|
178 /**
|
Chris@0
|
179 * Do nothing
|
Chris@0
|
180 */
|
Chris@0
|
181 Browser.prototype.noop = function () {
|
Chris@0
|
182 };
|
Chris@0
|
183
|
Chris@0
|
184 /**
|
Chris@0
|
185 * Throws a new Object error
|
Chris@0
|
186 */
|
Chris@0
|
187 Browser.prototype.browser_error = function () {
|
Chris@0
|
188 throw new Error('zomg');
|
Chris@0
|
189 };
|
Chris@0
|
190
|
Chris@0
|
191 /**
|
Chris@0
|
192 * Visits a page and load its content
|
Chris@0
|
193 * @param serverResponse
|
Chris@0
|
194 * @param url
|
Chris@0
|
195 * @return {*}
|
Chris@0
|
196 */
|
Chris@0
|
197 Browser.prototype.visit = function (serverResponse, url) {
|
Chris@0
|
198 var prevUrl;
|
Chris@0
|
199 var self = this;
|
Chris@0
|
200 this.currentPage.state = 'loading';
|
Chris@0
|
201 prevUrl = this.currentPage.source === null ? 'about:blank' : this.currentPage.currentUrl();
|
Chris@0
|
202 this.currentPage.open(url);
|
Chris@0
|
203 if (/#/.test(url) && prevUrl.split('#')[0] === url.split('#')[0]) {
|
Chris@0
|
204 this.currentPage.state = 'default';
|
Chris@0
|
205 return this.serverSendResponse({
|
Chris@0
|
206 status: 'success'
|
Chris@0
|
207 }, serverResponse);
|
Chris@0
|
208 } else {
|
Chris@0
|
209 return this.currentPage.waitState('default', function () {
|
Chris@0
|
210 if (self.currentPage.statusCode === null && self.currentPage.status === 'fail') {
|
Chris@0
|
211 return self.owner.serverSendError(new Poltergeist.StatusFailError, serverResponse);
|
Chris@0
|
212 } else {
|
Chris@0
|
213 return self.serverSendResponse({
|
Chris@0
|
214 status: self.currentPage.status
|
Chris@0
|
215 }, serverResponse);
|
Chris@0
|
216 }
|
Chris@0
|
217 });
|
Chris@0
|
218 }
|
Chris@0
|
219 };
|
Chris@0
|
220
|
Chris@0
|
221 /**
|
Chris@0
|
222 * Puts the control of the browser inside the IFRAME given by name
|
Chris@0
|
223 * @param serverResponse
|
Chris@0
|
224 * @param name
|
Chris@0
|
225 * @param timeout
|
Chris@0
|
226 * @return {*}
|
Chris@0
|
227 */
|
Chris@0
|
228 Browser.prototype.push_frame = function (serverResponse, name, timeout) {
|
Chris@0
|
229 var _ref;
|
Chris@0
|
230 var self = this;
|
Chris@0
|
231
|
Chris@0
|
232 if (timeout == null) {
|
Chris@0
|
233 timeout = new Date().getTime() + 2000;
|
Chris@0
|
234 }
|
Chris@0
|
235
|
Chris@0
|
236 //TODO: WTF, else if after a if with return COMMON
|
Chris@0
|
237 if (_ref = this.frameUrl(name), __indexOf.call(this.currentPage.blockedUrls(), _ref) >= 0) {
|
Chris@0
|
238 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
239 } else if (this.currentPage.pushFrame(name)) {
|
Chris@0
|
240 if (this.currentPage.currentUrl() === 'about:blank') {
|
Chris@0
|
241 this.currentPage.state = 'awaiting_frame_load';
|
Chris@0
|
242 return this.currentPage.waitState('default', function () {
|
Chris@0
|
243 return self.serverSendResponse(true, serverResponse);
|
Chris@0
|
244 });
|
Chris@0
|
245 } else {
|
Chris@0
|
246 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
247 }
|
Chris@0
|
248 } else {
|
Chris@0
|
249 if (new Date().getTime() < timeout) {
|
Chris@0
|
250 return setTimeout((function () {
|
Chris@0
|
251 return self.push_frame(serverResponse, name, timeout);
|
Chris@0
|
252 }), 50);
|
Chris@0
|
253 } else {
|
Chris@0
|
254 return this.owner.serverSendError(new Poltergeist.FrameNotFound(name), serverResponse);
|
Chris@0
|
255 }
|
Chris@0
|
256 }
|
Chris@0
|
257 };
|
Chris@0
|
258
|
Chris@0
|
259 /**
|
Chris@0
|
260 * Injects a javascript into the current page
|
Chris@0
|
261 * @param serverResponse
|
Chris@0
|
262 * @param extension
|
Chris@0
|
263 * @return {*}
|
Chris@0
|
264 */
|
Chris@0
|
265 Browser.prototype.add_extension = function (serverResponse, extension) {
|
Chris@0
|
266 //TODO: error control when the injection was not possible
|
Chris@0
|
267 this.currentPage.injectExtension(extension);
|
Chris@0
|
268 return this.serverSendResponse('success', serverResponse);
|
Chris@0
|
269 };
|
Chris@0
|
270
|
Chris@0
|
271 /**
|
Chris@0
|
272 * Returns the url we are currently in
|
Chris@0
|
273 * @param serverResponse
|
Chris@0
|
274 * @return {*}
|
Chris@0
|
275 */
|
Chris@0
|
276 Browser.prototype.current_url = function (serverResponse) {
|
Chris@0
|
277 return this.serverSendResponse(this.currentPage.currentUrl(), serverResponse);
|
Chris@0
|
278 };
|
Chris@0
|
279
|
Chris@0
|
280 /**
|
Chris@0
|
281 * Returns the current page window name
|
Chris@0
|
282 * @param serverResponse
|
Chris@0
|
283 * @returns {*}
|
Chris@0
|
284 */
|
Chris@0
|
285 Browser.prototype.window_name = function (serverResponse) {
|
Chris@0
|
286 return this.serverSendResponse(this.currentPage.windowName(), serverResponse);
|
Chris@0
|
287 };
|
Chris@0
|
288
|
Chris@0
|
289 /**
|
Chris@0
|
290 * Returns the status code associated to the page
|
Chris@0
|
291 * @param serverResponse
|
Chris@0
|
292 * @return {*}
|
Chris@0
|
293 */
|
Chris@0
|
294 Browser.prototype.status_code = function (serverResponse) {
|
Chris@0
|
295 if (this.currentPage.statusCode === undefined || this.currentPage.statusCode === null) {
|
Chris@0
|
296 return this.owner.serverSendError(new Poltergeist.StatusFailError("status_code_error"), serverResponse);
|
Chris@0
|
297 }
|
Chris@0
|
298 return this.serverSendResponse(this.currentPage.statusCode, serverResponse);
|
Chris@0
|
299 };
|
Chris@0
|
300
|
Chris@0
|
301 /**
|
Chris@0
|
302 * Returns the source code of the active frame, useful for when inside an IFRAME
|
Chris@0
|
303 * @param serverResponse
|
Chris@0
|
304 * @return {*}
|
Chris@0
|
305 */
|
Chris@0
|
306 Browser.prototype.body = function (serverResponse) {
|
Chris@0
|
307 return this.serverSendResponse(this.currentPage.content(), serverResponse);
|
Chris@0
|
308 };
|
Chris@0
|
309
|
Chris@0
|
310 /**
|
Chris@0
|
311 * Returns the source code of the page all the html
|
Chris@0
|
312 * @param serverResponse
|
Chris@0
|
313 * @return {*}
|
Chris@0
|
314 */
|
Chris@0
|
315 Browser.prototype.source = function (serverResponse) {
|
Chris@0
|
316 return this.serverSendResponse(this.currentPage.source, serverResponse);
|
Chris@0
|
317 };
|
Chris@0
|
318
|
Chris@0
|
319 /**
|
Chris@0
|
320 * Returns the current page title
|
Chris@0
|
321 * @param serverResponse
|
Chris@0
|
322 * @return {*}
|
Chris@0
|
323 */
|
Chris@0
|
324 Browser.prototype.title = function (serverResponse) {
|
Chris@0
|
325 return this.serverSendResponse(this.currentPage.title(), serverResponse);
|
Chris@0
|
326 };
|
Chris@0
|
327
|
Chris@0
|
328 /**
|
Chris@0
|
329 * Finds the elements that match a method of selection and a selector
|
Chris@0
|
330 * @param serverResponse
|
Chris@0
|
331 * @param method
|
Chris@0
|
332 * @param selector
|
Chris@0
|
333 * @return {*}
|
Chris@0
|
334 */
|
Chris@0
|
335 Browser.prototype.find = function (serverResponse, method, selector) {
|
Chris@0
|
336 return this.serverSendResponse({
|
Chris@0
|
337 page_id: this.currentPage.id,
|
Chris@0
|
338 ids: this.currentPage.find(method, selector)
|
Chris@0
|
339 }, serverResponse);
|
Chris@0
|
340 };
|
Chris@0
|
341
|
Chris@0
|
342 /**
|
Chris@0
|
343 * Find elements within a given element
|
Chris@0
|
344 * @param serverResponse
|
Chris@0
|
345 * @param page_id
|
Chris@0
|
346 * @param id
|
Chris@0
|
347 * @param method
|
Chris@0
|
348 * @param selector
|
Chris@0
|
349 * @return {*}
|
Chris@0
|
350 */
|
Chris@0
|
351 Browser.prototype.find_within = function (serverResponse, page_id, id, method, selector) {
|
Chris@0
|
352 return this.serverSendResponse(this.node(page_id, id).find(method, selector), serverResponse);
|
Chris@0
|
353 };
|
Chris@0
|
354
|
Chris@0
|
355 /**
|
Chris@0
|
356 * Returns ALL the text, visible and not visible from the given element
|
Chris@0
|
357 * @param serverResponse
|
Chris@0
|
358 * @param page_id
|
Chris@0
|
359 * @param id
|
Chris@0
|
360 * @return {*}
|
Chris@0
|
361 */
|
Chris@0
|
362 Browser.prototype.all_text = function (serverResponse, page_id, id) {
|
Chris@0
|
363 return this.serverSendResponse(this.node(page_id, id).allText(), serverResponse);
|
Chris@0
|
364 };
|
Chris@0
|
365
|
Chris@0
|
366 /**
|
Chris@0
|
367 * Returns the inner or outer html of a given id
|
Chris@0
|
368 * @param serverResponse
|
Chris@0
|
369 * @param page_id
|
Chris@0
|
370 * @param id
|
Chris@0
|
371 * @param type
|
Chris@0
|
372 * @returns Object
|
Chris@0
|
373 */
|
Chris@0
|
374 Browser.prototype.all_html = function (serverResponse, page_id, id, type) {
|
Chris@0
|
375 return this.serverSendResponse(this.node(page_id, id).allHTML(type), serverResponse);
|
Chris@0
|
376 };
|
Chris@0
|
377
|
Chris@0
|
378 /**
|
Chris@0
|
379 * Returns only the visible text in a given element
|
Chris@0
|
380 * @param serverResponse
|
Chris@0
|
381 * @param page_id
|
Chris@0
|
382 * @param id
|
Chris@0
|
383 * @return {*}
|
Chris@0
|
384 */
|
Chris@0
|
385 Browser.prototype.visible_text = function (serverResponse, page_id, id) {
|
Chris@0
|
386 return this.serverSendResponse(this.node(page_id, id).visibleText(), serverResponse);
|
Chris@0
|
387 };
|
Chris@0
|
388
|
Chris@0
|
389 /**
|
Chris@0
|
390 * Deletes the text in a given element leaving it empty
|
Chris@0
|
391 * @param serverResponse
|
Chris@0
|
392 * @param page_id
|
Chris@0
|
393 * @param id
|
Chris@0
|
394 * @return {*}
|
Chris@0
|
395 */
|
Chris@0
|
396 Browser.prototype.delete_text = function (serverResponse, page_id, id) {
|
Chris@0
|
397 return this.serverSendResponse(this.node(page_id, id).deleteText(), serverResponse);
|
Chris@0
|
398 };
|
Chris@0
|
399
|
Chris@0
|
400 /**
|
Chris@0
|
401 * Gets the value of a given attribute in an element
|
Chris@0
|
402 * @param serverResponse
|
Chris@0
|
403 * @param page_id
|
Chris@0
|
404 * @param id
|
Chris@0
|
405 * @param name
|
Chris@0
|
406 * @return {*}
|
Chris@0
|
407 */
|
Chris@0
|
408 Browser.prototype.attribute = function (serverResponse, page_id, id, name) {
|
Chris@0
|
409 return this.serverSendResponse(this.node(page_id, id).getAttribute(name), serverResponse);
|
Chris@0
|
410 };
|
Chris@0
|
411
|
Chris@0
|
412 /**
|
Chris@0
|
413 * Allows the possibility to set an attribute on a given element
|
Chris@0
|
414 * @param serverResponse
|
Chris@0
|
415 * @param page_id
|
Chris@0
|
416 * @param id
|
Chris@0
|
417 * @param name
|
Chris@0
|
418 * @param value
|
Chris@0
|
419 * @returns {*}
|
Chris@0
|
420 */
|
Chris@0
|
421 Browser.prototype.set_attribute = function (serverResponse, page_id, id, name, value) {
|
Chris@0
|
422 return this.serverSendResponse(this.node(page_id, id).setAttribute(name, value), serverResponse);
|
Chris@0
|
423 };
|
Chris@0
|
424
|
Chris@0
|
425 /**
|
Chris@0
|
426 * Allows the possibility to remove an attribute on a given element
|
Chris@0
|
427 * @param serverResponse
|
Chris@0
|
428 * @param page_id
|
Chris@0
|
429 * @param id
|
Chris@0
|
430 * @param name
|
Chris@0
|
431 * @returns {*}
|
Chris@0
|
432 */
|
Chris@0
|
433 Browser.prototype.remove_attribute = function (serverResponse, page_id, id, name) {
|
Chris@0
|
434 return this.serverSendResponse(this.node(page_id, id).removeAttribute(name), serverResponse);
|
Chris@0
|
435 };
|
Chris@0
|
436
|
Chris@0
|
437 /**
|
Chris@0
|
438 * Returns all the attributes of a given element
|
Chris@0
|
439 * @param serverResponse
|
Chris@0
|
440 * @param page_id
|
Chris@0
|
441 * @param id
|
Chris@0
|
442 * @param name
|
Chris@0
|
443 * @return {*}
|
Chris@0
|
444 */
|
Chris@0
|
445 Browser.prototype.attributes = function (serverResponse, page_id, id, name) {
|
Chris@0
|
446 return this.serverSendResponse(this.node(page_id, id).getAttributes(), serverResponse);
|
Chris@0
|
447 };
|
Chris@0
|
448
|
Chris@0
|
449 /**
|
Chris@0
|
450 * Returns all the way to the document level the parents of a given element
|
Chris@0
|
451 * @param serverResponse
|
Chris@0
|
452 * @param page_id
|
Chris@0
|
453 * @param id
|
Chris@0
|
454 * @return {*}
|
Chris@0
|
455 */
|
Chris@0
|
456 Browser.prototype.parents = function (serverResponse, page_id, id) {
|
Chris@0
|
457 return this.serverSendResponse(this.node(page_id, id).parentIds(), serverResponse);
|
Chris@0
|
458 };
|
Chris@0
|
459
|
Chris@0
|
460 /**
|
Chris@0
|
461 * Returns the element.value of an element given by its page and id
|
Chris@0
|
462 * @param serverResponse
|
Chris@0
|
463 * @param page_id
|
Chris@0
|
464 * @param id
|
Chris@0
|
465 * @return {*}
|
Chris@0
|
466 */
|
Chris@0
|
467 Browser.prototype.value = function (serverResponse, page_id, id) {
|
Chris@0
|
468 return this.serverSendResponse(this.node(page_id, id).value(), serverResponse);
|
Chris@0
|
469 };
|
Chris@0
|
470
|
Chris@0
|
471 /**
|
Chris@0
|
472 * Sets the element.value of an element by the given value
|
Chris@0
|
473 * @param serverResponse
|
Chris@0
|
474 * @param page_id
|
Chris@0
|
475 * @param id
|
Chris@0
|
476 * @param value
|
Chris@0
|
477 * @return {*}
|
Chris@0
|
478 */
|
Chris@0
|
479 Browser.prototype.set = function (serverResponse, page_id, id, value) {
|
Chris@0
|
480 this.node(page_id, id).set(value);
|
Chris@0
|
481 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
482 };
|
Chris@0
|
483
|
Chris@0
|
484 /**
|
Chris@0
|
485 * Uploads a file to an input file element
|
Chris@0
|
486 * @param serverResponse
|
Chris@0
|
487 * @param page_id
|
Chris@0
|
488 * @param id
|
Chris@0
|
489 * @param file_path
|
Chris@0
|
490 * @return {*}
|
Chris@0
|
491 */
|
Chris@0
|
492 Browser.prototype.select_file = function (serverResponse, page_id, id, file_path) {
|
Chris@0
|
493 var node = this.node(page_id, id);
|
Chris@0
|
494
|
Chris@0
|
495 this.currentPage.beforeUpload(node.id);
|
Chris@0
|
496 this.currentPage.uploadFile('[_poltergeist_selected]', file_path);
|
Chris@0
|
497 this.currentPage.afterUpload(node.id);
|
Chris@0
|
498
|
Chris@0
|
499 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
500 };
|
Chris@0
|
501
|
Chris@0
|
502 /**
|
Chris@0
|
503 * Sets a value to the selected element (to be used in select elements)
|
Chris@0
|
504 * @param serverResponse
|
Chris@0
|
505 * @param page_id
|
Chris@0
|
506 * @param id
|
Chris@0
|
507 * @param value
|
Chris@0
|
508 * @return {*}
|
Chris@0
|
509 */
|
Chris@0
|
510 Browser.prototype.select = function (serverResponse, page_id, id, value) {
|
Chris@0
|
511 return this.serverSendResponse(this.node(page_id, id).select(value), serverResponse);
|
Chris@0
|
512 };
|
Chris@0
|
513
|
Chris@0
|
514 /**
|
Chris@0
|
515 * Selects an option with the given value
|
Chris@0
|
516 * @param serverResponse
|
Chris@0
|
517 * @param page_id
|
Chris@0
|
518 * @param id
|
Chris@0
|
519 * @param value
|
Chris@0
|
520 * @param multiple
|
Chris@0
|
521 * @return {*}
|
Chris@0
|
522 */
|
Chris@0
|
523 Browser.prototype.select_option = function (serverResponse, page_id, id, value, multiple) {
|
Chris@0
|
524 return this.serverSendResponse(this.node(page_id, id).select_option(value, multiple), serverResponse);
|
Chris@0
|
525 };
|
Chris@0
|
526
|
Chris@0
|
527 /**
|
Chris@0
|
528 *
|
Chris@0
|
529 * @param serverResponse
|
Chris@0
|
530 * @param page_id
|
Chris@0
|
531 * @param id
|
Chris@0
|
532 * @return {*}
|
Chris@0
|
533 */
|
Chris@0
|
534 Browser.prototype.tag_name = function (serverResponse, page_id, id) {
|
Chris@0
|
535 return this.serverSendResponse(this.node(page_id, id).tagName(), serverResponse);
|
Chris@0
|
536 };
|
Chris@0
|
537
|
Chris@0
|
538
|
Chris@0
|
539 /**
|
Chris@0
|
540 * Tells if an element is visible or not
|
Chris@0
|
541 * @param serverResponse
|
Chris@0
|
542 * @param page_id
|
Chris@0
|
543 * @param id
|
Chris@0
|
544 * @return {*}
|
Chris@0
|
545 */
|
Chris@0
|
546 Browser.prototype.visible = function (serverResponse, page_id, id) {
|
Chris@0
|
547 return this.serverSendResponse(this.node(page_id, id).isVisible(), serverResponse);
|
Chris@0
|
548 };
|
Chris@0
|
549
|
Chris@0
|
550 /**
|
Chris@0
|
551 * Tells if an element is disabled
|
Chris@0
|
552 * @param serverResponse
|
Chris@0
|
553 * @param page_id
|
Chris@0
|
554 * @param id
|
Chris@0
|
555 * @return {*}
|
Chris@0
|
556 */
|
Chris@0
|
557 Browser.prototype.disabled = function (serverResponse, page_id, id) {
|
Chris@0
|
558 return this.serverSendResponse(this.node(page_id, id).isDisabled(), serverResponse);
|
Chris@0
|
559 };
|
Chris@0
|
560
|
Chris@0
|
561 /**
|
Chris@0
|
562 * Evaluates a javascript and returns the outcome to the client
|
Chris@0
|
563 * This will be JSON response so your script better be returning objects that can be used
|
Chris@0
|
564 * in JSON.stringify
|
Chris@0
|
565 * @param serverResponse
|
Chris@0
|
566 * @param script
|
Chris@0
|
567 * @return {*}
|
Chris@0
|
568 */
|
Chris@0
|
569 Browser.prototype.evaluate = function (serverResponse, script) {
|
Chris@0
|
570 return this.serverSendResponse(this.currentPage.evaluate("function() { return " + script + " }"), serverResponse);
|
Chris@0
|
571 };
|
Chris@0
|
572
|
Chris@0
|
573 /**
|
Chris@0
|
574 * Executes a javascript and goes back to the client with true if there were no errors
|
Chris@0
|
575 * @param serverResponse
|
Chris@0
|
576 * @param script
|
Chris@0
|
577 * @return {*}
|
Chris@0
|
578 */
|
Chris@0
|
579 Browser.prototype.execute = function (serverResponse, script) {
|
Chris@0
|
580 this.currentPage.execute("function() { " + script + " }");
|
Chris@0
|
581 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
582 };
|
Chris@0
|
583
|
Chris@0
|
584 /**
|
Chris@0
|
585 * If inside a frame then we will go back to the parent
|
Chris@0
|
586 * Not defined behaviour if you pop and are not inside an iframe
|
Chris@0
|
587 * @param serverResponse
|
Chris@0
|
588 * @return {*}
|
Chris@0
|
589 */
|
Chris@0
|
590 Browser.prototype.pop_frame = function (serverResponse) {
|
Chris@0
|
591 return this.serverSendResponse(this.currentPage.popFrame(), serverResponse);
|
Chris@0
|
592 };
|
Chris@0
|
593
|
Chris@0
|
594 /**
|
Chris@0
|
595 * Gets the window handle id by a given window name
|
Chris@0
|
596 * @param serverResponse
|
Chris@0
|
597 * @param name
|
Chris@0
|
598 * @return {*}
|
Chris@0
|
599 */
|
Chris@0
|
600 Browser.prototype.window_handle = function (serverResponse, name) {
|
Chris@0
|
601 var handle, pageByWindowName;
|
Chris@0
|
602
|
Chris@0
|
603 if (name === null || typeof name == "undefined" || name.length === 0) {
|
Chris@0
|
604 return this.serverSendResponse(this.currentPage.handle, serverResponse);
|
Chris@0
|
605 }
|
Chris@0
|
606
|
Chris@0
|
607 handle = null;
|
Chris@0
|
608
|
Chris@0
|
609 //Lets search the handle by the given window name
|
Chris@0
|
610 var filteredPages = this.pages.filter(function (p) {
|
Chris@0
|
611 return !p.closed && p.windowName() === name;
|
Chris@0
|
612 });
|
Chris@0
|
613
|
Chris@0
|
614 //A bit of error control is always good
|
Chris@0
|
615 if (Array.isArray(filteredPages) && filteredPages.length >= 1) {
|
Chris@0
|
616 pageByWindowName = filteredPages[0];
|
Chris@0
|
617 } else {
|
Chris@0
|
618 pageByWindowName = null;
|
Chris@0
|
619 }
|
Chris@0
|
620
|
Chris@0
|
621 if (pageByWindowName !== null && typeof pageByWindowName != "undefined") {
|
Chris@0
|
622 handle = pageByWindowName.handle;
|
Chris@0
|
623 }
|
Chris@0
|
624
|
Chris@0
|
625 return this.serverSendResponse(handle, serverResponse);
|
Chris@0
|
626 };
|
Chris@0
|
627
|
Chris@0
|
628 /**
|
Chris@0
|
629 * Returns all the window handles of opened windows
|
Chris@0
|
630 * @param serverResponse
|
Chris@0
|
631 * @return {*}
|
Chris@0
|
632 */
|
Chris@0
|
633 Browser.prototype.window_handles = function (serverResponse) {
|
Chris@0
|
634 var handles, filteredPages;
|
Chris@0
|
635
|
Chris@0
|
636 filteredPages = this.pages.filter(function (p) {
|
Chris@0
|
637 return !p.closed;
|
Chris@0
|
638 });
|
Chris@0
|
639
|
Chris@0
|
640 if (filteredPages.length > 0) {
|
Chris@0
|
641 handles = filteredPages.map(function (p) {
|
Chris@0
|
642 return p.handle;
|
Chris@0
|
643 });
|
Chris@0
|
644 if (handles.length === 0) {
|
Chris@0
|
645 handles = null;
|
Chris@0
|
646 }
|
Chris@0
|
647 } else {
|
Chris@0
|
648 handles = null;
|
Chris@0
|
649 }
|
Chris@0
|
650
|
Chris@0
|
651 return this.serverSendResponse(handles, serverResponse);
|
Chris@0
|
652 };
|
Chris@0
|
653
|
Chris@0
|
654 /**
|
Chris@0
|
655 * Tries to switch to a window given by the handle id
|
Chris@0
|
656 * @param serverResponse
|
Chris@0
|
657 * @param handle
|
Chris@0
|
658 * @return {*}
|
Chris@0
|
659 */
|
Chris@0
|
660 Browser.prototype.switch_to_window = function (serverResponse, handle) {
|
Chris@0
|
661 var page;
|
Chris@0
|
662 var self = this;
|
Chris@0
|
663
|
Chris@0
|
664 page = this.getPageByHandle(handle);
|
Chris@0
|
665 if (page === null || typeof page == "undefined") {
|
Chris@0
|
666 throw new Poltergeist.NoSuchWindowError;
|
Chris@0
|
667 }
|
Chris@0
|
668
|
Chris@0
|
669 if (page !== this.currentPage) {
|
Chris@0
|
670 return page.waitState('default', function () {
|
Chris@0
|
671 self.currentPage = page;
|
Chris@0
|
672 return self.serverSendResponse(true, serverResponse);
|
Chris@0
|
673 });
|
Chris@0
|
674 }
|
Chris@0
|
675
|
Chris@0
|
676 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
677 };
|
Chris@0
|
678
|
Chris@0
|
679 /**
|
Chris@0
|
680 * Opens a new window where we can do stuff
|
Chris@0
|
681 * @param serverResponse
|
Chris@0
|
682 * @return {*}
|
Chris@0
|
683 */
|
Chris@0
|
684 Browser.prototype.open_new_window = function (serverResponse) {
|
Chris@0
|
685 return this.execute(serverResponse, 'window.open()');
|
Chris@0
|
686 };
|
Chris@0
|
687
|
Chris@0
|
688 /**
|
Chris@0
|
689 * Closes the window given by handle name if possible
|
Chris@0
|
690 * @param serverResponse
|
Chris@0
|
691 * @param handle
|
Chris@0
|
692 * @return {*}
|
Chris@0
|
693 */
|
Chris@0
|
694 Browser.prototype.close_window = function (serverResponse, handle) {
|
Chris@0
|
695 var page;
|
Chris@0
|
696
|
Chris@0
|
697 page = this.getPageByHandle(handle);
|
Chris@0
|
698 if (page === null || typeof page == "undefined") {
|
Chris@0
|
699 //TODO: should we throw error since we actually could not find the window?
|
Chris@0
|
700 return this.serverSendResponse(false, serverResponse);
|
Chris@0
|
701 }
|
Chris@0
|
702
|
Chris@0
|
703 //TODO: we have to add some control here to actually asses that the release has been done
|
Chris@0
|
704 page.release();
|
Chris@0
|
705 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
706 };
|
Chris@0
|
707
|
Chris@0
|
708 /**
|
Chris@0
|
709 * Generic mouse event on an element
|
Chris@0
|
710 * @param serverResponse
|
Chris@0
|
711 * @param page_id
|
Chris@0
|
712 * @param id
|
Chris@0
|
713 * @param name
|
Chris@0
|
714 * @return {number}
|
Chris@0
|
715 */
|
Chris@0
|
716 Browser.prototype.mouse_event = function (serverResponse, page_id, id, name) {
|
Chris@0
|
717 var node;
|
Chris@0
|
718 var self = this;
|
Chris@0
|
719 node = this.node(page_id, id);
|
Chris@0
|
720 this.currentPage.state = 'mouse_event';
|
Chris@0
|
721 this.last_mouse_event = node.mouseEvent(name);
|
Chris@0
|
722 return setTimeout(function () {
|
Chris@0
|
723 if (self.currentPage.state === 'mouse_event') {
|
Chris@0
|
724 self.currentPage.state = 'default';
|
Chris@0
|
725 return self.serverSendResponse({
|
Chris@0
|
726 position: self.last_mouse_event
|
Chris@0
|
727 }, serverResponse);
|
Chris@0
|
728 } else {
|
Chris@0
|
729 return self.currentPage.waitState('default', function () {
|
Chris@0
|
730 return self.serverSendResponse({
|
Chris@0
|
731 position: self.last_mouse_event
|
Chris@0
|
732 }, serverResponse);
|
Chris@0
|
733 });
|
Chris@0
|
734 }
|
Chris@0
|
735 }, 5);
|
Chris@0
|
736 };
|
Chris@0
|
737
|
Chris@0
|
738 /**
|
Chris@0
|
739 * Simple click on the element
|
Chris@0
|
740 * @param serverResponse
|
Chris@0
|
741 * @param page_id
|
Chris@0
|
742 * @param id
|
Chris@0
|
743 * @return {*}
|
Chris@0
|
744 */
|
Chris@0
|
745 Browser.prototype.click = function (serverResponse, page_id, id) {
|
Chris@0
|
746 return this.mouse_event(serverResponse, page_id, id, 'click');
|
Chris@0
|
747 };
|
Chris@0
|
748
|
Chris@0
|
749 /**
|
Chris@0
|
750 * Right click on the element
|
Chris@0
|
751 * @param serverResponse
|
Chris@0
|
752 * @param page_id
|
Chris@0
|
753 * @param id
|
Chris@0
|
754 * @return {*}
|
Chris@0
|
755 */
|
Chris@0
|
756 Browser.prototype.right_click = function (serverResponse, page_id, id) {
|
Chris@0
|
757 return this.mouse_event(serverResponse, page_id, id, 'rightclick');
|
Chris@0
|
758 };
|
Chris@0
|
759
|
Chris@0
|
760 /**
|
Chris@0
|
761 * Double click on the element given by page and id
|
Chris@0
|
762 * @param serverResponse
|
Chris@0
|
763 * @param page_id
|
Chris@0
|
764 * @param id
|
Chris@0
|
765 * @return {*}
|
Chris@0
|
766 */
|
Chris@0
|
767 Browser.prototype.double_click = function (serverResponse, page_id, id) {
|
Chris@0
|
768 return this.mouse_event(serverResponse, page_id, id, 'doubleclick');
|
Chris@0
|
769 };
|
Chris@0
|
770
|
Chris@0
|
771 /**
|
Chris@0
|
772 * Executes a mousemove event on the page and given element
|
Chris@0
|
773 * @param serverResponse
|
Chris@0
|
774 * @param page_id
|
Chris@0
|
775 * @param id
|
Chris@0
|
776 * @return {*}
|
Chris@0
|
777 */
|
Chris@0
|
778 Browser.prototype.hover = function (serverResponse, page_id, id) {
|
Chris@0
|
779 return this.mouse_event(serverResponse, page_id, id, 'mousemove');
|
Chris@0
|
780 };
|
Chris@0
|
781
|
Chris@0
|
782 /**
|
Chris@0
|
783 * Triggers a mouse click event on the given coordinates
|
Chris@0
|
784 * @param serverResponse
|
Chris@0
|
785 * @param x
|
Chris@0
|
786 * @param y
|
Chris@0
|
787 * @return {*}
|
Chris@0
|
788 */
|
Chris@0
|
789 Browser.prototype.click_coordinates = function (serverResponse, x, y) {
|
Chris@0
|
790 var response;
|
Chris@0
|
791
|
Chris@0
|
792 this.currentPage.sendEvent('click', x, y);
|
Chris@0
|
793 response = {
|
Chris@0
|
794 click: {
|
Chris@0
|
795 x: x,
|
Chris@0
|
796 y: y
|
Chris@0
|
797 }
|
Chris@0
|
798 };
|
Chris@0
|
799
|
Chris@0
|
800 return this.serverSendResponse(response, serverResponse);
|
Chris@0
|
801 };
|
Chris@0
|
802
|
Chris@0
|
803 /**
|
Chris@0
|
804 * Drags one element into another, useful for nice javascript thingies
|
Chris@0
|
805 * @param serverResponse
|
Chris@0
|
806 * @param page_id
|
Chris@0
|
807 * @param id
|
Chris@0
|
808 * @param other_id
|
Chris@0
|
809 * @return {*}
|
Chris@0
|
810 */
|
Chris@0
|
811 Browser.prototype.drag = function (serverResponse, page_id, id, other_id) {
|
Chris@0
|
812 this.node(page_id, id).dragTo(this.node(page_id, other_id));
|
Chris@0
|
813 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
814 };
|
Chris@0
|
815
|
Chris@0
|
816 /**
|
Chris@0
|
817 * Triggers an event on the given page and element
|
Chris@0
|
818 * @param serverResponse
|
Chris@0
|
819 * @param page_id
|
Chris@0
|
820 * @param id
|
Chris@0
|
821 * @param event
|
Chris@0
|
822 * @return {*}
|
Chris@0
|
823 */
|
Chris@0
|
824 Browser.prototype.trigger = function (serverResponse, page_id, id, event) {
|
Chris@0
|
825 this.node(page_id, id).trigger(event);
|
Chris@0
|
826 return this.serverSendResponse(event, serverResponse);
|
Chris@0
|
827 };
|
Chris@0
|
828
|
Chris@0
|
829 /**
|
Chris@0
|
830 * Checks if two elements are equal on a dom level
|
Chris@0
|
831 * @param serverResponse
|
Chris@0
|
832 * @param page_id
|
Chris@0
|
833 * @param id
|
Chris@0
|
834 * @param other_id
|
Chris@0
|
835 * @return {*}
|
Chris@0
|
836 */
|
Chris@0
|
837 Browser.prototype.equals = function (serverResponse, page_id, id, other_id) {
|
Chris@0
|
838 return this.serverSendResponse(this.node(page_id, id).isEqual(this.node(page_id, other_id)), serverResponse);
|
Chris@0
|
839 };
|
Chris@0
|
840
|
Chris@0
|
841 /**
|
Chris@0
|
842 * Resets the current page to a clean slate
|
Chris@0
|
843 * @param serverResponse
|
Chris@0
|
844 * @return {*}
|
Chris@0
|
845 */
|
Chris@0
|
846 Browser.prototype.reset = function (serverResponse) {
|
Chris@0
|
847 this.resetPage();
|
Chris@0
|
848 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
849 };
|
Chris@0
|
850
|
Chris@0
|
851 /**
|
Chris@0
|
852 * Scrolls to a position given by the left, top coordinates
|
Chris@0
|
853 * @param serverResponse
|
Chris@0
|
854 * @param left
|
Chris@0
|
855 * @param top
|
Chris@0
|
856 * @return {*}
|
Chris@0
|
857 */
|
Chris@0
|
858 Browser.prototype.scroll_to = function (serverResponse, left, top) {
|
Chris@0
|
859 this.currentPage.setScrollPosition({
|
Chris@0
|
860 left: left,
|
Chris@0
|
861 top: top
|
Chris@0
|
862 });
|
Chris@0
|
863 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
864 };
|
Chris@0
|
865
|
Chris@0
|
866 /**
|
Chris@0
|
867 * Sends keys to an element simulating as closest as possible what a user would do
|
Chris@0
|
868 * when typing
|
Chris@0
|
869 * @param serverResponse
|
Chris@0
|
870 * @param page_id
|
Chris@0
|
871 * @param id
|
Chris@0
|
872 * @param keys
|
Chris@0
|
873 * @return {*}
|
Chris@0
|
874 */
|
Chris@0
|
875 Browser.prototype.send_keys = function (serverResponse, page_id, id, keys) {
|
Chris@0
|
876 var key, sequence, target, _i, _len;
|
Chris@0
|
877 target = this.node(page_id, id);
|
Chris@0
|
878 if (!target.containsSelection()) {
|
Chris@0
|
879 target.mouseEvent('click');
|
Chris@0
|
880 }
|
Chris@0
|
881 for (_i = 0, _len = keys.length; _i < _len; _i++) {
|
Chris@0
|
882 sequence = keys[_i];
|
Chris@0
|
883 key = sequence.key != null ? this.currentPage.keyCode(sequence.key) : sequence;
|
Chris@0
|
884 this.currentPage.sendEvent('keypress', key);
|
Chris@0
|
885 }
|
Chris@0
|
886 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
887 };
|
Chris@0
|
888
|
Chris@0
|
889 /**
|
Chris@0
|
890 * Sends a native phantomjs key event to element
|
Chris@0
|
891 * @param serverResponse
|
Chris@0
|
892 * @param page_id
|
Chris@0
|
893 * @param id
|
Chris@0
|
894 * @param keyEvent
|
Chris@0
|
895 * @param key
|
Chris@0
|
896 * @param modifier
|
Chris@0
|
897 */
|
Chris@0
|
898 Browser.prototype.key_event = function (serverResponse, page_id, id, keyEvent, key, modifier) {
|
Chris@0
|
899 var keyEventModifierMap;
|
Chris@0
|
900 var keyEventModifier;
|
Chris@0
|
901 var target;
|
Chris@0
|
902
|
Chris@0
|
903 keyEventModifierMap = {
|
Chris@0
|
904 'none': 0x0,
|
Chris@0
|
905 'shift': 0x02000000,
|
Chris@0
|
906 'ctrl': 0x04000000,
|
Chris@0
|
907 'alt': 0x08000000,
|
Chris@0
|
908 'meta': 0x10000000
|
Chris@0
|
909 };
|
Chris@0
|
910 keyEventModifier = keyEventModifierMap[modifier];
|
Chris@0
|
911
|
Chris@0
|
912 target = this.node(page_id, id);
|
Chris@0
|
913 if (!target.containsSelection()) {
|
Chris@0
|
914 target.mouseEvent('click');
|
Chris@0
|
915 }
|
Chris@0
|
916 target.page.sendEvent(keyEvent, key, null, null, keyEventModifier);
|
Chris@0
|
917
|
Chris@0
|
918 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
919 };
|
Chris@0
|
920
|
Chris@0
|
921 /**
|
Chris@0
|
922 * Sends the rendered page in a base64 encoding
|
Chris@0
|
923 * @param serverResponse
|
Chris@0
|
924 * @param format
|
Chris@0
|
925 * @param full
|
Chris@0
|
926 * @param selector
|
Chris@0
|
927 * @return {*}
|
Chris@0
|
928 */
|
Chris@0
|
929 Browser.prototype.render_base64 = function (serverResponse, format, full, selector) {
|
Chris@0
|
930 var encoded_image;
|
Chris@0
|
931 if (selector == null) {
|
Chris@0
|
932 selector = null;
|
Chris@0
|
933 }
|
Chris@0
|
934 this.set_clip_rect(full, selector);
|
Chris@0
|
935 encoded_image = this.currentPage.renderBase64(format);
|
Chris@0
|
936 return this.serverSendResponse(encoded_image, serverResponse);
|
Chris@0
|
937 };
|
Chris@0
|
938
|
Chris@0
|
939 /**
|
Chris@0
|
940 * Renders the current page entirely or a given selection
|
Chris@0
|
941 * @param serverResponse
|
Chris@0
|
942 * @param path
|
Chris@0
|
943 * @param full
|
Chris@0
|
944 * @param selector
|
Chris@0
|
945 * @return {*}
|
Chris@0
|
946 */
|
Chris@0
|
947 Browser.prototype.render = function (serverResponse, path, full, selector) {
|
Chris@0
|
948 var dimensions;
|
Chris@0
|
949 if (selector == null) {
|
Chris@0
|
950 selector = null;
|
Chris@0
|
951 }
|
Chris@0
|
952 dimensions = this.set_clip_rect(full, selector);
|
Chris@0
|
953 this.currentPage.setScrollPosition({
|
Chris@0
|
954 left: 0,
|
Chris@0
|
955 top: 0
|
Chris@0
|
956 });
|
Chris@0
|
957 this.currentPage.render(path);
|
Chris@0
|
958 this.currentPage.setScrollPosition({
|
Chris@0
|
959 left: dimensions.left,
|
Chris@0
|
960 top: dimensions.top
|
Chris@0
|
961 });
|
Chris@0
|
962 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
963 };
|
Chris@0
|
964
|
Chris@0
|
965
|
Chris@0
|
966 /**
|
Chris@0
|
967 * Sets the paper size, useful when printing to PDF
|
Chris@0
|
968 * @param serverResponse
|
Chris@0
|
969 * @param size
|
Chris@0
|
970 * @return {*}
|
Chris@0
|
971 */
|
Chris@0
|
972 Browser.prototype.set_paper_size = function (serverResponse, size) {
|
Chris@0
|
973 this.currentPage.setPaperSize(size);
|
Chris@0
|
974 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
975 };
|
Chris@0
|
976
|
Chris@0
|
977 /**
|
Chris@0
|
978 * Sets the zoom factor on the current page
|
Chris@0
|
979 * @param serverResponse
|
Chris@0
|
980 * @param zoom_factor
|
Chris@0
|
981 * @return {*}
|
Chris@0
|
982 */
|
Chris@0
|
983 Browser.prototype.set_zoom_factor = function (serverResponse, zoom_factor) {
|
Chris@0
|
984 this.currentPage.setZoomFactor(zoom_factor);
|
Chris@0
|
985 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
986 };
|
Chris@0
|
987
|
Chris@0
|
988 /**
|
Chris@0
|
989 * Resizes the browser viewport, useful when testing mobile stuff
|
Chris@0
|
990 * @param serverResponse
|
Chris@0
|
991 * @param width
|
Chris@0
|
992 * @param height
|
Chris@0
|
993 * @return {*}
|
Chris@0
|
994 */
|
Chris@0
|
995 Browser.prototype.resize = function (serverResponse, width, height) {
|
Chris@0
|
996 this.currentPage.setViewportSize({
|
Chris@0
|
997 width: width,
|
Chris@0
|
998 height: height
|
Chris@0
|
999 });
|
Chris@0
|
1000 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1001 };
|
Chris@0
|
1002
|
Chris@0
|
1003 /**
|
Chris@0
|
1004 * Gets the browser viewport size
|
Chris@0
|
1005 * Because PhantomJS is headless (nothing is shown)
|
Chris@0
|
1006 * viewportSize effectively simulates the size of the window like in a traditional browser.
|
Chris@0
|
1007 * @param serverResponse
|
Chris@0
|
1008 * @param handle
|
Chris@0
|
1009 * @return {*}
|
Chris@0
|
1010 */
|
Chris@0
|
1011 Browser.prototype.window_size = function (serverResponse, handle) {
|
Chris@0
|
1012 //TODO: add support for window handles
|
Chris@0
|
1013 return this.serverSendResponse(this.currentPage.viewportSize(), serverResponse);
|
Chris@0
|
1014 };
|
Chris@0
|
1015
|
Chris@0
|
1016 /**
|
Chris@0
|
1017 * Returns the network traffic that the current page has generated
|
Chris@0
|
1018 * @param serverResponse
|
Chris@0
|
1019 * @return {*}
|
Chris@0
|
1020 */
|
Chris@0
|
1021 Browser.prototype.network_traffic = function (serverResponse) {
|
Chris@0
|
1022 return this.serverSendResponse(this.currentPage.networkTraffic(), serverResponse);
|
Chris@0
|
1023 };
|
Chris@0
|
1024
|
Chris@0
|
1025 /**
|
Chris@0
|
1026 * Clears the accumulated network_traffic in the current page
|
Chris@0
|
1027 * @param serverResponse
|
Chris@0
|
1028 * @return {*}
|
Chris@0
|
1029 */
|
Chris@0
|
1030 Browser.prototype.clear_network_traffic = function (serverResponse) {
|
Chris@0
|
1031 this.currentPage.clearNetworkTraffic();
|
Chris@0
|
1032 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1033 };
|
Chris@0
|
1034
|
Chris@0
|
1035 /**
|
Chris@0
|
1036 * Gets the headers of the current page
|
Chris@0
|
1037 * @param serverResponse
|
Chris@0
|
1038 * @return {*}
|
Chris@0
|
1039 */
|
Chris@0
|
1040 Browser.prototype.get_headers = function (serverResponse) {
|
Chris@0
|
1041 return this.serverSendResponse(this.currentPage.getCustomHeaders(), serverResponse);
|
Chris@0
|
1042 };
|
Chris@0
|
1043
|
Chris@0
|
1044 /**
|
Chris@0
|
1045 * Set headers in the browser
|
Chris@0
|
1046 * @param serverResponse
|
Chris@0
|
1047 * @param headers
|
Chris@0
|
1048 * @return {*}
|
Chris@0
|
1049 */
|
Chris@0
|
1050 Browser.prototype.set_headers = function (serverResponse, headers) {
|
Chris@0
|
1051 if (headers['User-Agent']) {
|
Chris@0
|
1052 this.currentPage.setUserAgent(headers['User-Agent']);
|
Chris@0
|
1053 }
|
Chris@0
|
1054 this.currentPage.setCustomHeaders(headers);
|
Chris@0
|
1055 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1056 };
|
Chris@0
|
1057
|
Chris@0
|
1058 /**
|
Chris@0
|
1059 * Given an array of headers, adds them to the page
|
Chris@0
|
1060 * @param serverResponse
|
Chris@0
|
1061 * @param headers
|
Chris@0
|
1062 * @return {*}
|
Chris@0
|
1063 */
|
Chris@0
|
1064 Browser.prototype.add_headers = function (serverResponse, headers) {
|
Chris@0
|
1065 var allHeaders, name, value;
|
Chris@0
|
1066 allHeaders = this.currentPage.getCustomHeaders();
|
Chris@0
|
1067 for (name in headers) {
|
Chris@0
|
1068 if (headers.hasOwnProperty(name)) {
|
Chris@0
|
1069 value = headers[name];
|
Chris@0
|
1070 allHeaders[name] = value;
|
Chris@0
|
1071 }
|
Chris@0
|
1072 }
|
Chris@0
|
1073 return this.set_headers(serverResponse, allHeaders);
|
Chris@0
|
1074 };
|
Chris@0
|
1075
|
Chris@0
|
1076 /**
|
Chris@0
|
1077 * Adds a header to the page temporary or permanently
|
Chris@0
|
1078 * @param serverResponse
|
Chris@0
|
1079 * @param header
|
Chris@0
|
1080 * @param permanent
|
Chris@0
|
1081 * @return {*}
|
Chris@0
|
1082 */
|
Chris@0
|
1083 Browser.prototype.add_header = function (serverResponse, header, permanent) {
|
Chris@0
|
1084 if (!permanent) {
|
Chris@0
|
1085 this.currentPage.addTempHeader(header);
|
Chris@0
|
1086 }
|
Chris@0
|
1087 return this.add_headers(serverResponse, header);
|
Chris@0
|
1088 };
|
Chris@0
|
1089
|
Chris@0
|
1090
|
Chris@0
|
1091 /**
|
Chris@0
|
1092 * Sends back the client the response headers sent from the browser when making
|
Chris@0
|
1093 * the page request
|
Chris@0
|
1094 * @param serverResponse
|
Chris@0
|
1095 * @return {*}
|
Chris@0
|
1096 */
|
Chris@0
|
1097 Browser.prototype.response_headers = function (serverResponse) {
|
Chris@0
|
1098 return this.serverSendResponse(this.currentPage.responseHeaders(), serverResponse);
|
Chris@0
|
1099 };
|
Chris@0
|
1100
|
Chris@0
|
1101 /**
|
Chris@0
|
1102 * Returns the cookies of the current page being browsed
|
Chris@0
|
1103 * @param serverResponse
|
Chris@0
|
1104 * @return {*}
|
Chris@0
|
1105 */
|
Chris@0
|
1106 Browser.prototype.cookies = function (serverResponse) {
|
Chris@0
|
1107 return this.serverSendResponse(this.currentPage.cookies(), serverResponse);
|
Chris@0
|
1108 };
|
Chris@0
|
1109
|
Chris@0
|
1110 /**
|
Chris@0
|
1111 * Sets a cookie in the browser, the format of the cookies has to be the format it says
|
Chris@0
|
1112 * on phantomjs documentation and as such you can set it in other domains, not on the
|
Chris@0
|
1113 * current page
|
Chris@0
|
1114 * @param serverResponse
|
Chris@0
|
1115 * @param cookie
|
Chris@0
|
1116 * @return {*}
|
Chris@0
|
1117 */
|
Chris@0
|
1118 Browser.prototype.set_cookie = function (serverResponse, cookie) {
|
Chris@0
|
1119 return this.serverSendResponse(phantom.addCookie(cookie), serverResponse);
|
Chris@0
|
1120 };
|
Chris@0
|
1121
|
Chris@0
|
1122 /**
|
Chris@0
|
1123 * Remove a cookie set on the current page
|
Chris@0
|
1124 * @param serverResponse
|
Chris@0
|
1125 * @param name
|
Chris@0
|
1126 * @return {*}
|
Chris@0
|
1127 */
|
Chris@0
|
1128 Browser.prototype.remove_cookie = function (serverResponse, name) {
|
Chris@0
|
1129 //TODO: add error control to check if the cookie was properly deleted
|
Chris@0
|
1130 this.currentPage.deleteCookie(name);
|
Chris@0
|
1131 phantom.deleteCookie(name);
|
Chris@0
|
1132 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1133 };
|
Chris@0
|
1134
|
Chris@0
|
1135 /**
|
Chris@0
|
1136 * Clear the cookies in the browser
|
Chris@0
|
1137 * @param serverResponse
|
Chris@0
|
1138 * @return {*}
|
Chris@0
|
1139 */
|
Chris@0
|
1140 Browser.prototype.clear_cookies = function (serverResponse) {
|
Chris@0
|
1141 phantom.clearCookies();
|
Chris@0
|
1142 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1143 };
|
Chris@0
|
1144
|
Chris@0
|
1145 /**
|
Chris@0
|
1146 * Enables / Disables the cookies on the browser
|
Chris@0
|
1147 * @param serverResponse
|
Chris@0
|
1148 * @param flag
|
Chris@0
|
1149 * @return {*}
|
Chris@0
|
1150 */
|
Chris@0
|
1151 Browser.prototype.cookies_enabled = function (serverResponse, flag) {
|
Chris@0
|
1152 phantom.cookiesEnabled = flag;
|
Chris@0
|
1153 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1154 };
|
Chris@0
|
1155
|
Chris@0
|
1156 /**
|
Chris@0
|
1157 * US19: DONE
|
Chris@0
|
1158 * Sets a basic authentication credential to access a page
|
Chris@0
|
1159 * THIS SHOULD BE USED BEFORE accessing a page
|
Chris@0
|
1160 * @param serverResponse
|
Chris@0
|
1161 * @param user
|
Chris@0
|
1162 * @param password
|
Chris@0
|
1163 * @return {*}
|
Chris@0
|
1164 */
|
Chris@0
|
1165 Browser.prototype.set_http_auth = function (serverResponse, user, password) {
|
Chris@0
|
1166 this.currentPage.setHttpAuth(user, password);
|
Chris@0
|
1167 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1168 };
|
Chris@0
|
1169
|
Chris@0
|
1170 /**
|
Chris@0
|
1171 * Sets the flag whether to fail on javascript errors or not.
|
Chris@0
|
1172 * @param serverResponse
|
Chris@0
|
1173 * @param value
|
Chris@0
|
1174 * @return {*}
|
Chris@0
|
1175 */
|
Chris@0
|
1176 Browser.prototype.set_js_errors = function (serverResponse, value) {
|
Chris@0
|
1177 this.js_errors = value;
|
Chris@0
|
1178 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1179 };
|
Chris@0
|
1180
|
Chris@0
|
1181 /**
|
Chris@0
|
1182 * Sets the debug mode to boolean value
|
Chris@0
|
1183 * @param serverResponse
|
Chris@0
|
1184 * @param value
|
Chris@0
|
1185 * @return {*}
|
Chris@0
|
1186 */
|
Chris@0
|
1187 Browser.prototype.set_debug = function (serverResponse, value) {
|
Chris@0
|
1188 this._debug = value;
|
Chris@0
|
1189 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1190 };
|
Chris@0
|
1191
|
Chris@0
|
1192 /**
|
Chris@0
|
1193 * Goes back in the history when possible
|
Chris@0
|
1194 * @param serverResponse
|
Chris@0
|
1195 * @return {*}
|
Chris@0
|
1196 */
|
Chris@0
|
1197 Browser.prototype.go_back = function (serverResponse) {
|
Chris@0
|
1198 var self = this;
|
Chris@0
|
1199 if (this.currentPage.canGoBack()) {
|
Chris@0
|
1200 this.currentPage.state = 'loading';
|
Chris@0
|
1201 this.currentPage.goBack();
|
Chris@0
|
1202 return this.currentPage.waitState('default', function () {
|
Chris@0
|
1203 return self.serverSendResponse(true, serverResponse);
|
Chris@0
|
1204 });
|
Chris@0
|
1205 } else {
|
Chris@0
|
1206 return this.serverSendResponse(false, serverResponse);
|
Chris@0
|
1207 }
|
Chris@0
|
1208 };
|
Chris@0
|
1209
|
Chris@0
|
1210 /**
|
Chris@0
|
1211 * Reloads the page if possible
|
Chris@0
|
1212 * @return {*}
|
Chris@0
|
1213 */
|
Chris@0
|
1214 Browser.prototype.reload = function (serverResponse) {
|
Chris@0
|
1215 var self = this;
|
Chris@0
|
1216 this.currentPage.state = 'loading';
|
Chris@0
|
1217 this.currentPage.reload();
|
Chris@0
|
1218 return this.currentPage.waitState('default', function () {
|
Chris@0
|
1219 return self.serverSendResponse(true, serverResponse);
|
Chris@0
|
1220 });
|
Chris@0
|
1221 };
|
Chris@0
|
1222
|
Chris@0
|
1223 /**
|
Chris@0
|
1224 * Goes forward in the browser history if possible
|
Chris@0
|
1225 * @param serverResponse
|
Chris@0
|
1226 * @return {*}
|
Chris@0
|
1227 */
|
Chris@0
|
1228 Browser.prototype.go_forward = function (serverResponse) {
|
Chris@0
|
1229 var self = this;
|
Chris@0
|
1230 if (this.currentPage.canGoForward()) {
|
Chris@0
|
1231 this.currentPage.state = 'loading';
|
Chris@0
|
1232 this.currentPage.goForward();
|
Chris@0
|
1233 return this.currentPage.waitState('default', function () {
|
Chris@0
|
1234 return self.serverSendResponse(true, serverResponse);
|
Chris@0
|
1235 });
|
Chris@0
|
1236 } else {
|
Chris@0
|
1237 return this.serverSendResponse(false, serverResponse);
|
Chris@0
|
1238 }
|
Chris@0
|
1239 };
|
Chris@0
|
1240
|
Chris@0
|
1241 /**
|
Chris@0
|
1242 * Sets the urlBlacklist for the given urls as parameters
|
Chris@0
|
1243 * @return {boolean}
|
Chris@0
|
1244 */
|
Chris@0
|
1245 Browser.prototype.set_url_blacklist = function (serverResponse, blackList) {
|
Chris@0
|
1246 this.currentPage.urlBlacklist = Array.prototype.slice.call(blackList);
|
Chris@0
|
1247 return this.serverSendResponse(true, serverResponse);
|
Chris@0
|
1248 };
|
Chris@0
|
1249
|
Chris@0
|
1250 /**
|
Chris@0
|
1251 * Runs a browser command and returns the response back to the client
|
Chris@0
|
1252 * when the command has finished the execution
|
Chris@0
|
1253 * @param command
|
Chris@0
|
1254 * @param serverResponse
|
Chris@0
|
1255 * @return {*}
|
Chris@0
|
1256 */
|
Chris@0
|
1257 Browser.prototype.serverRunCommand = function (command, serverResponse) {
|
Chris@0
|
1258 var commandData;
|
Chris@0
|
1259 var commandArgs;
|
Chris@0
|
1260 var commandName;
|
Chris@0
|
1261
|
Chris@0
|
1262 commandName = command.name;
|
Chris@0
|
1263 commandArgs = command.args;
|
Chris@0
|
1264 this.currentPage.state = 'default';
|
Chris@0
|
1265 commandData = [serverResponse].concat(commandArgs);
|
Chris@0
|
1266
|
Chris@0
|
1267 if (typeof this[commandName] !== "function") {
|
Chris@0
|
1268 //We can not run such command
|
Chris@0
|
1269 throw new Poltergeist.Error();
|
Chris@0
|
1270 }
|
Chris@0
|
1271
|
Chris@0
|
1272 return this[commandName].apply(this, commandData);
|
Chris@0
|
1273 };
|
Chris@0
|
1274
|
Chris@0
|
1275 /**
|
Chris@0
|
1276 * Sends a response back to the client who made the request
|
Chris@0
|
1277 * @param response
|
Chris@0
|
1278 * @param serverResponse
|
Chris@0
|
1279 * @return {*}
|
Chris@0
|
1280 */
|
Chris@0
|
1281 Browser.prototype.serverSendResponse = function (response, serverResponse) {
|
Chris@0
|
1282 var errors;
|
Chris@0
|
1283 errors = this.currentPage.errors;
|
Chris@0
|
1284 this.currentPage.clearErrors();
|
Chris@0
|
1285 if (errors.length > 0 && this.js_errors) {
|
Chris@0
|
1286 return this.owner.serverSendError(new Poltergeist.JavascriptError(errors), serverResponse);
|
Chris@0
|
1287 } else {
|
Chris@0
|
1288 return this.owner.serverSendResponse(response, serverResponse);
|
Chris@0
|
1289 }
|
Chris@0
|
1290 };
|
Chris@0
|
1291
|
Chris@0
|
1292 return Browser;
|
Chris@0
|
1293
|
Chris@0
|
1294 })();
|