[ Index ] |
|
Code source de PRADO 3.0.6 |
1 /* 2 * Copyright 2004 ThoughtWorks, Inc 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 /* 19 * This script provides the Javascript API to drive the test application contained within 20 * a Browser Window. 21 * TODO: 22 * Add support for more events (keyboard and mouse) 23 * Allow to switch "user-entry" mode from mouse-based to keyboard-based, firing different 24 * events in different modes. 25 */ 26 27 // The window to which the commands will be sent. For example, to click on a 28 // popup window, first select that window, and then do a normal click command. 29 30 var BrowserBot = function(topLevelApplicationWindow) { 31 this.topWindow = topLevelApplicationWindow; 32 33 // the buttonWindow is the Selenium window 34 // it contains the Run/Pause buttons... this should *not* be the AUT window 35 // todo: Here the buttonWindow is not Selenium window. It will be set to Selenium window in pollForLoad. 36 // Change this!!! 37 this.buttonWindow = this.topWindow; 38 // not sure what this is used for 39 this.currentPage = null; 40 this.currentWindow = this.topWindow; 41 this.currentWindowName = null; 42 43 this.modalDialogTest = null; 44 this.recordedAlerts = new Array(); 45 this.recordedConfirmations = new Array(); 46 this.recordedPrompts = new Array(); 47 this.openedWindows = {}; 48 this.nextConfirmResult = true; 49 this.nextPromptResult = ''; 50 this.newPageLoaded = false; 51 this.pageLoadError = null; 52 53 this.uniqueId = new Date().getTime(); 54 this.pollingForLoad = new Object(); 55 this.windowPollers = new Array(); 56 57 var self = this; 58 this.recordPageLoad = function() { 59 LOG.debug("Page load detected"); 60 try { 61 LOG.debug("Page load location=" + self.getCurrentWindow(true).location); 62 } catch (e) { 63 self.pageLoadError = e; 64 return; 65 } 66 self.currentPage = null; 67 self.newPageLoaded = true; 68 }; 69 70 this.isNewPageLoaded = function() { 71 if (this.pageLoadError) { 72 var e = this.pageLoadError; 73 this.pageLoadError = null; 74 throw e; 75 } 76 return self.newPageLoaded; 77 }; 78 }; 79 80 BrowserBot.createForWindow = function(window) { 81 var browserbot; 82 LOG.debug('createForWindow'); 83 LOG.debug("browserName: " + browserVersion.name); 84 LOG.debug("userAgent: " + navigator.userAgent); 85 if (browserVersion.isIE) { 86 browserbot = new IEBrowserBot(window); 87 } 88 else if (browserVersion.isKonqueror) { 89 browserbot = new KonquerorBrowserBot(window); 90 } 91 else if (browserVersion.isOpera) { 92 browserbot = new OperaBrowserBot(window); 93 } 94 else if (browserVersion.isSafari) { 95 browserbot = new SafariBrowserBot(window); 96 } 97 else { 98 // Use mozilla by default 99 browserbot = new MozillaBrowserBot(window); 100 } 101 browserbot.getCurrentWindow(); 102 // todo: why? 103 return browserbot; 104 }; 105 106 // todo: rename? This doesn't actually "do" anything. 107 BrowserBot.prototype.doModalDialogTest = function(test) { 108 this.modalDialogTest = test; 109 }; 110 111 BrowserBot.prototype.cancelNextConfirmation = function() { 112 this.nextConfirmResult = false; 113 }; 114 115 BrowserBot.prototype.setNextPromptResult = function(result) { 116 this.nextPromptResult = result; 117 }; 118 119 BrowserBot.prototype.hasAlerts = function() { 120 return (this.recordedAlerts.length > 0); 121 }; 122 123 BrowserBot.prototype.relayBotToRC = function() { 124 }; 125 // override in injection.html 126 127 BrowserBot.prototype.resetPopups = function() { 128 this.recordedAlerts = []; 129 this.recordedConfirmations = []; 130 this.recordedPrompts = []; 131 } 132 133 BrowserBot.prototype.getNextAlert = function() { 134 var t = this.recordedAlerts.shift(); 135 this.relayBotToRC("browserbot.recordedAlerts"); 136 return t; 137 }; 138 139 BrowserBot.prototype.hasConfirmations = function() { 140 return (this.recordedConfirmations.length > 0); 141 }; 142 143 BrowserBot.prototype.getNextConfirmation = function() { 144 var t = this.recordedConfirmations.shift(); 145 this.relayBotToRC("browserbot.recordedConfirmations"); 146 return t; 147 }; 148 149 BrowserBot.prototype.hasPrompts = function() { 150 return (this.recordedPrompts.length > 0); 151 }; 152 153 BrowserBot.prototype.getNextPrompt = function() { 154 var t = this.recordedPrompts.shift(); 155 this.relayBotToRC("browserbot.recordedPrompts"); 156 return t; 157 }; 158 159 BrowserBot.prototype._windowClosed = function(win) { 160 var c = win.closed; 161 if (c == null) return true; 162 return c; 163 }; 164 165 BrowserBot.prototype._modifyWindow = function(win) { 166 if (this._windowClosed(win)) { 167 LOG.error("modifyWindow: Window was closed!"); 168 return null; 169 } 170 LOG.debug('modifyWindow ' + this.uniqueId + ":" + win[this.uniqueId]); 171 if (!win[this.uniqueId]) { 172 win[this.uniqueId] = true; 173 this.modifyWindowToRecordPopUpDialogs(win, this); 174 this.currentPage = PageBot.createForWindow(this); 175 this.newPageLoaded = false; 176 } 177 this.modifySeparateTestWindowToDetectPageLoads(win); 178 return win; 179 }; 180 181 BrowserBot.prototype.selectWindow = function(target) { 182 // we've moved to a new page - clear the current one 183 this.currentPage = null; 184 185 if (target && target != "null") { 186 this._selectWindowByName(target); 187 } else { 188 this._selectTopWindow(); 189 } 190 }; 191 192 BrowserBot.prototype._selectTopWindow = function() { 193 this.currentWindowName = null; 194 this.currentWindow = this.topWindow; 195 } 196 197 BrowserBot.prototype._selectWindowByName = function(target) { 198 this.currentWindow = this.getWindowByName(target, false); 199 this.currentWindowName = target; 200 } 201 202 BrowserBot.prototype.selectFrame = function(target) { 203 if (target == "relative=up") { 204 this.currentWindow = this.getCurrentWindow().parent; 205 } else if (target == "relative=top") { 206 this.currentWindow = this.topWindow; 207 } else { 208 var frame = this.getCurrentPage().findElement(target); 209 if (frame == null) { 210 throw new SeleniumError("Not found: " + target); 211 } 212 // now, did they give us a frame or a frame ELEMENT? 213 if (frame.contentWindow) { 214 // this must be a frame element 215 this.currentWindow = frame.contentWindow; 216 } else if (frame.document) { 217 // must be an actual window frame 218 this.currentWindow = frame; 219 } else { 220 // neither 221 throw new SeleniumError("Not a frame: " + target); 222 } 223 } 224 this.currentPage = null; 225 }; 226 227 BrowserBot.prototype.openLocation = function(target) { 228 // We're moving to a new page - clear the current one 229 var win = this.getCurrentWindow(); 230 LOG.debug("openLocation newPageLoaded = false"); 231 this.currentPage = null; 232 this.newPageLoaded = false; 233 234 this.setOpenLocation(win, target); 235 }; 236 237 BrowserBot.prototype.setIFrameLocation = function(iframe, location) { 238 iframe.src = location; 239 }; 240 241 BrowserBot.prototype.setOpenLocation = function(win, loc) { 242 243 // is there a Permission Denied risk here? setting a timeout breaks Firefox 244 //win.setTimeout(function() { win.location.href = loc; }, 0); 245 win.location.href = loc; 246 }; 247 248 BrowserBot.prototype.getCurrentPage = function() { 249 if (this.currentPage == null) { 250 var testWindow = this.getCurrentWindow(); 251 this.currentPage = PageBot.createForWindow(this); 252 this.newPageLoaded = false; 253 } 254 255 return this.currentPage; 256 }; 257 258 BrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { 259 var self = this; 260 261 windowToModify.alert = function(alert) { 262 browserBot.recordedAlerts.push(alert); 263 self.relayBotToRC("browserbot.recordedAlerts"); 264 }; 265 266 windowToModify.confirm = function(message) { 267 browserBot.recordedConfirmations.push(message); 268 var result = browserBot.nextConfirmResult; 269 browserBot.nextConfirmResult = true; 270 self.relayBotToRC("browserbot.recordedConfirmations"); 271 return result; 272 }; 273 274 windowToModify.prompt = function(message) { 275 browserBot.recordedPrompts.push(message); 276 var result = !browserBot.nextConfirmResult ? null : browserBot.nextPromptResult; 277 browserBot.nextConfirmResult = true; 278 browserBot.nextPromptResult = ''; 279 self.relayBotToRC("browserbot.recordedPrompts"); 280 return result; 281 }; 282 283 // Keep a reference to all popup windows by name 284 // note that in IE the "windowName" argument must be a valid javascript identifier, it seems. 285 var originalOpen = windowToModify.open; 286 windowToModify.open = function(url, windowName, windowFeatures, replaceFlag) { 287 var openedWindow = originalOpen(url, windowName, windowFeatures, replaceFlag); 288 selenium.browserbot.openedWindows[windowName] = openedWindow; 289 return openedWindow; 290 }; 291 }; 292 293 /** 294 * Call the supplied function when a the current page unloads and a new one loads. 295 * This is done by polling continuously until the document changes and is fully loaded. 296 */ 297 BrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads = function(windowObject) { 298 // Since the unload event doesn't fire in Safari 1.3, we start polling immediately 299 if (!windowObject) { 300 LOG.warn("modifySeparateTestWindowToDetectPageLoads: no windowObject!"); 301 return; 302 } 303 if (this._windowClosed(windowObject)) { 304 LOG.info("modifySeparateTestWindowToDetectPageLoads: windowObject was closed"); 305 return; 306 } 307 var oldMarker = this.isPollingForLoad(windowObject); 308 if (oldMarker) { 309 LOG.debug("modifySeparateTestWindowToDetectPageLoads: already polling this window: " + oldMarker); 310 return; 311 } 312 313 var marker = 'selenium' + new Date().getTime(); 314 LOG.debug("Starting pollForLoad (" + marker + "): " + windowObject.document.location); 315 this.pollingForLoad[marker] = true; 316 // if this is a frame, add a load listener, otherwise, attach a poller 317 if (this._getFrameElement(windowObject)) { 318 LOG.debug("modifySeparateTestWindowToDetectPageLoads: this window is a frame; attaching a load listener"); 319 addLoadListener(windowObject.frameElement, this.recordPageLoad); 320 windowObject.frameElement[marker] = true; 321 windowObject.frameElement[this.uniqueId] = marker; 322 } else { 323 windowObject.document.location[marker] = true; 324 windowObject[this.uniqueId] = marker; 325 this.pollForLoad(this.recordPageLoad, windowObject, windowObject.document, windowObject.location, windowObject.location.href, marker); 326 } 327 }; 328 329 BrowserBot.prototype._getFrameElement = function(win) { 330 var frameElement = null; 331 try { 332 frameElement = win.frameElement; 333 } catch (e) { 334 } // on IE, checking frameElement on a pop-up results in a "No such interface supported" exception 335 return frameElement; 336 } 337 338 /** 339 * Set up a polling timer that will keep checking the readyState of the document until it's complete. 340 * Since we might call this before the original page is unloaded, we first check to see that the current location 341 * or href is different from the original one. 342 */ 343 BrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { 344 LOG.debug("pollForLoad original (" + marker + "): " + originalHref); 345 346 try { 347 if (this._windowClosed(windowObject)) { 348 LOG.debug("pollForLoad WINDOW CLOSED (" + marker + ")"); 349 delete this.pollingForLoad[marker]; 350 return; 351 } 352 // todo: Change this!!! 353 // under multi-window layout, buttonWindow should be TestRunner window 354 // but only after the _windowClosed checking, we can ensure that this.topWindow exists 355 // then we can assign the TestRunner window to buttonWindow 356 this.buttonWindow = windowObject.opener; 357 358 var isSamePage = this._isSamePage(windowObject, originalDocument, originalLocation, originalHref, marker); 359 var rs = this.getReadyState(windowObject, windowObject.document); 360 361 if (!isSamePage && rs == 'complete') { 362 var currentHref = windowObject.location.href; 363 LOG.debug("pollForLoad FINISHED (" + marker + "): " + rs + " (" + currentHref + ")"); 364 delete this.pollingForLoad[marker]; 365 this._modifyWindow(windowObject); 366 var newMarker = this.isPollingForLoad(windowObject); 367 if (!newMarker) { 368 LOG.debug("modifyWindow didn't start new poller: " + newMarker); 369 this.modifySeparateTestWindowToDetectPageLoads(windowObject); 370 } 371 newMarker = this.isPollingForLoad(windowObject); 372 LOG.debug("pollForLoad (" + marker + ") restarting " + newMarker); 373 if (/(TestRunner-splash|Blank)\.html\?start=true$/.test(currentHref)) { 374 LOG.debug("pollForLoad Oh, it's just the starting page. Never mind!"); 375 } else if (this.currentWindow[this.uniqueId] == newMarker) { 376 loadFunction(); 377 } else { 378 LOG.debug("pollForLoad page load detected in non-current window; ignoring"); 379 } 380 return; 381 } 382 LOG.debug("pollForLoad continue (" + marker + "): " + currentHref); 383 this.reschedulePoller(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 384 } catch (e) { 385 LOG.error("Exception during pollForLoad; this should get noticed soon (" + e.message + ")!"); 386 LOG.exception(e); 387 this.pageLoadError = e; 388 } 389 }; 390 391 BrowserBot.prototype._isSamePage = function(windowObject, originalDocument, originalLocation, originalHref, marker) { 392 var currentDocument = windowObject.document; 393 var currentLocation = windowObject.location; 394 var currentHref = currentLocation.href 395 396 var sameDoc = this._isSameDocument(originalDocument, currentDocument); 397 398 var sameLoc = (originalLocation === currentLocation); 399 var sameHref = (originalHref === currentHref); 400 var markedLoc = currentLocation[marker]; 401 402 if (browserVersion.isKonqueror || browserVersion.isSafari) { 403 // the mark disappears too early on these browsers 404 markedLoc = true; 405 } 406 return sameDoc && sameLoc && sameHref && markedLoc 407 }; 408 409 BrowserBot.prototype._isSameDocument = function(originalDocument, currentDocument) { 410 return originalDocument === currentDocument; 411 }; 412 413 414 BrowserBot.prototype.getReadyState = function(windowObject, currentDocument) { 415 var rs = currentDocument.readyState; 416 if (rs == null) { 417 if ((this.buttonWindow!=null && this.buttonWindow.document.readyState == null) // not proxy injection mode (and therefore buttonWindow isn't null) 418 || (top.document.readyState == null)) { // proxy injection mode (and therefore everything's in the top window, but buttonWindow doesn't exist) 419 // uh oh! we're probably on Firefox with no readyState extension installed! 420 // We'll have to just take a guess as to when the document is loaded; this guess 421 // will never be perfect. :-( 422 if (typeof currentDocument.getElementsByTagName != 'undefined' 423 && typeof currentDocument.getElementById != 'undefined' 424 && ( currentDocument.getElementsByTagName('body')[0] != null 425 || currentDocument.body != null )) { 426 if (windowObject.frameElement && windowObject.location.href == "about:blank" && windowObject.frameElement.src != "about:blank") { 427 LOG.info("getReadyState not loaded, frame location was about:blank, but frame src = " + windowObject.frameElement.src); 428 return null; 429 } 430 LOG.debug("getReadyState = windowObject.frames.length = " + windowObject.frames.length); 431 for (var i = 0; i < windowObject.frames.length; i++) { 432 LOG.debug("i = " + i); 433 if (this.getReadyState(windowObject.frames[i], windowObject.frames[i].document) != 'complete') { 434 LOG.debug("getReadyState aha! the nested frame " + windowObject.frames[i].name + " wasn't ready!"); 435 return null; 436 } 437 } 438 439 rs = 'complete'; 440 } else { 441 LOG.debug("pollForLoad readyState was null and DOM appeared to not be ready yet"); 442 } 443 } 444 } 445 else if (rs == "loading" && browserVersion.isIE) { 446 LOG.debug("pageUnloading = true!!!!"); 447 this.pageUnloading = true; 448 } 449 LOG.debug("getReadyState returning " + rs); 450 return rs; 451 }; 452 453 /** This function isn't used normally, but was the way we used to schedule pollers: 454 asynchronously executed autonomous units. This is deprecated, but remains here 455 for future reference. 456 */ 457 BrowserBot.prototype.XXXreschedulePoller = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { 458 var self = this; 459 window.setTimeout(function() { 460 self.pollForLoad(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 461 }, 500); 462 }; 463 464 /** This function isn't used normally, but is useful for debugging asynchronous pollers 465 * To enable it, rename it to "reschedulePoller", so it will override the 466 * existing reschedulePoller function 467 */ 468 BrowserBot.prototype.XXXreschedulePoller = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { 469 var doc = this.buttonWindow.document; 470 var button = doc.createElement("button"); 471 var buttonName = doc.createTextNode(marker + " - " + windowObject.name); 472 button.appendChild(buttonName); 473 var tools = doc.getElementById("tools"); 474 var self = this; 475 button.onclick = function() { 476 tools.removeChild(button); 477 self.pollForLoad(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 478 }; 479 tools.appendChild(button); 480 window.setTimeout(button.onclick, 500); 481 }; 482 483 BrowserBot.prototype.reschedulePoller = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { 484 var self = this; 485 var pollerFunction = function() { 486 self.pollForLoad(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 487 }; 488 this.windowPollers.push(pollerFunction); 489 }; 490 491 BrowserBot.prototype.runScheduledPollers = function() { 492 var oldPollers = this.windowPollers; 493 this.windowPollers = new Array(); 494 for (var i = 0; i < oldPollers.length; i++) { 495 oldPollers[i].call(); 496 } 497 }; 498 499 BrowserBot.prototype.isPollingForLoad = function(win) { 500 var marker; 501 if (this._getFrameElement(win)) { 502 marker = win.frameElement[this.uniqueId]; 503 } else { 504 marker = win[this.uniqueId]; 505 } 506 if (!marker) { 507 LOG.debug("isPollingForLoad false, missing uniqueId " + this.uniqueId + ": " + marker); 508 return false; 509 } 510 if (!this.pollingForLoad[marker]) { 511 LOG.debug("isPollingForLoad false, this.pollingForLoad[" + marker + "]: " + this.pollingForLoad[marker]); 512 return false; 513 } 514 return marker; 515 }; 516 517 BrowserBot.prototype.getWindowByName = function(windowName, doNotModify) { 518 LOG.debug("getWindowByName(" + windowName + ")"); 519 // First look in the map of opened windows 520 var targetWindow = this.openedWindows[windowName]; 521 if (!targetWindow) { 522 targetWindow = this.topWindow[windowName]; 523 } 524 if (!targetWindow) { 525 throw new SeleniumError("Window does not exist"); 526 } 527 if (!doNotModify) { 528 this._modifyWindow(targetWindow); 529 } 530 return targetWindow; 531 }; 532 533 BrowserBot.prototype.getCurrentWindow = function(doNotModify) { 534 var testWindow = this.currentWindow; 535 if (!doNotModify) { 536 this._modifyWindow(testWindow); 537 } 538 return testWindow; 539 }; 540 541 function MozillaBrowserBot(frame) { 542 BrowserBot.call(this, frame); 543 } 544 MozillaBrowserBot.prototype = new BrowserBot; 545 546 function KonquerorBrowserBot(frame) { 547 BrowserBot.call(this, frame); 548 } 549 KonquerorBrowserBot.prototype = new BrowserBot; 550 551 KonquerorBrowserBot.prototype.setIFrameLocation = function(iframe, location) { 552 // Window doesn't fire onload event when setting src to the current value, 553 // so we set it to blank first. 554 iframe.src = "about:blank"; 555 iframe.src = location; 556 }; 557 558 KonquerorBrowserBot.prototype.setOpenLocation = function(win, loc) { 559 // Window doesn't fire onload event when setting src to the current value, 560 // so we set it to blank first. 561 win.location.href = "about:blank"; 562 win.location.href = loc; 563 // force the current polling thread to detect a page load 564 var marker = this.isPollingForLoad(win); 565 if (marker) { 566 delete win.location[marker]; 567 } 568 }; 569 570 KonquerorBrowserBot.prototype._isSameDocument = function(originalDocument, currentDocument) { 571 // under Konqueror, there may be this case: 572 // originalDocument and currentDocument are different objects 573 // while their location are same. 574 if (originalDocument) { 575 return originalDocument.location == currentDocument.location 576 } else { 577 return originalDocument === currentDocument; 578 } 579 }; 580 581 function SafariBrowserBot(frame) { 582 BrowserBot.call(this, frame); 583 } 584 SafariBrowserBot.prototype = new BrowserBot; 585 586 SafariBrowserBot.prototype.setIFrameLocation = KonquerorBrowserBot.prototype.setIFrameLocation; 587 SafariBrowserBot.prototype.setOpenLocation = KonquerorBrowserBot.prototype.setOpenLocation; 588 589 590 function OperaBrowserBot(frame) { 591 BrowserBot.call(this, frame); 592 } 593 OperaBrowserBot.prototype = new BrowserBot; 594 OperaBrowserBot.prototype.setIFrameLocation = function(iframe, location) { 595 if (iframe.src == location) { 596 iframe.src = location + '?reload'; 597 } else { 598 iframe.src = location; 599 } 600 } 601 602 function IEBrowserBot(frame) { 603 BrowserBot.call(this, frame); 604 } 605 IEBrowserBot.prototype = new BrowserBot; 606 607 IEBrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { 608 BrowserBot.prototype.modifyWindowToRecordPopUpDialogs(windowToModify, browserBot); 609 610 // we will call the previous version of this method from within our own interception 611 oldShowModalDialog = windowToModify.showModalDialog; 612 613 windowToModify.showModalDialog = function(url, args, features) { 614 // Get relative directory to where TestRunner.html lives 615 // A risky assumption is that the user's TestRunner is named TestRunner.html 616 var doc_location = document.location.toString(); 617 var end_of_base_ref = doc_location.indexOf('TestRunner.html'); 618 var base_ref = doc_location.substring(0, end_of_base_ref); 619 620 var fullURL = base_ref + "TestRunner.html?singletest=" + escape(browserBot.modalDialogTest) + "&autoURL=" + escape(url) + "&runInterval=" + runOptions.runInterval; 621 browserBot.modalDialogTest = null; 622 623 var returnValue = oldShowModalDialog(fullURL, args, features); 624 return returnValue; 625 }; 626 }; 627 628 IEBrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads = function(windowObject) { 629 this.pageUnloading = false; 630 this.permDeniedCount = 0; 631 var self = this; 632 var pageUnloadDetector = function() { 633 self.pageUnloading = true; 634 }; 635 windowObject.attachEvent("onbeforeunload", pageUnloadDetector); 636 BrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads.call(this, windowObject); 637 }; 638 639 IEBrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { 640 BrowserBot.prototype.pollForLoad.call(this, loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 641 if (this.pageLoadError) { 642 if (this.pageUnloading) { 643 var self = this; 644 LOG.warn("pollForLoad UNLOADING (" + marker + "): caught exception while firing events on unloading page: " + this.pageLoadError.message); 645 this.reschedulePoller(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 646 this.pageLoadError = null; 647 return; 648 } else if (((this.pageLoadError.message == "Permission denied") || (/^Access is denied/.test(this.pageLoadError.message))) 649 && this.permDeniedCount++ < 4) { 650 var self = this; 651 LOG.warn("pollForLoad (" + marker + "): " + this.pageLoadError.message + " (" + this.permDeniedCount + "), waiting to see if it goes away"); 652 this.reschedulePoller(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); 653 this.pageLoadError = null; 654 return; 655 } 656 //handy for debugging! 657 //throw this.pageLoadError; 658 } 659 }; 660 661 IEBrowserBot.prototype._windowClosed = function(win) { 662 try { 663 var c = win.closed; 664 // frame windows claim to be non-closed when their parents are closed 665 // but you can't access their document objects in that case 666 if (!c) { 667 try { 668 win.document; 669 } catch (de) { 670 if (de.message == "Permission denied") { 671 // the window is probably unloading, which means it's probably not closed yet 672 return false; 673 } 674 else if (/^Access is denied/.test(de.message)) { 675 // rare variation on "Permission denied"? 676 LOG.debug("IEBrowserBot.windowClosed: got " + de.message + " (this.pageUnloading=" + this.pageUnloading + "); assuming window is unloading, probably not closed yet"); 677 return false; 678 } else { 679 // this is probably one of those frame window situations 680 LOG.debug("IEBrowserBot.windowClosed: couldn't read win.document, assume closed: " + de.message + " (this.pageUnloading=" + this.pageUnloading + ")"); 681 return true; 682 } 683 } 684 } 685 if (c == null) { 686 LOG.debug("IEBrowserBot.windowClosed: win.closed was null, assuming closed"); 687 return true; 688 } 689 return c; 690 } catch (e) { 691 // Got an exception trying to read win.closed; we'll have to take a guess! 692 if (browserVersion.isHTA) { 693 if (e.message == "Permission denied") { 694 // the window is probably unloading, which means it's probably not closed yet 695 return false; 696 } else { 697 // there's a good chance that we've lost contact with the window object if it is closed 698 return true; 699 } 700 } else { 701 // the window is probably unloading, which means it's probably not closed yet 702 return false; 703 } 704 } 705 }; 706 707 SafariBrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { 708 BrowserBot.prototype.modifyWindowToRecordPopUpDialogs(windowToModify, browserBot); 709 710 var originalOpen = windowToModify.open; 711 /* 712 * Safari seems to be broken, so that when we manually trigger the onclick method 713 * of a button/href, any window.open calls aren't resolved relative to the app location. 714 * So here we replace the open() method with one that does resolve the url correctly. 715 */ 716 windowToModify.open = function(url, windowName, windowFeatures, replaceFlag) { 717 718 if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("/")) { 719 return originalOpen(url, windowName, windowFeatures, replaceFlag); 720 } 721 722 // Reduce the current path to the directory 723 var currentPath = windowToModify.location.pathname || "/"; 724 currentPath = currentPath.replace(/\/[^\/]*$/, "/"); 725 726 // Remove any leading "./" from the new url. 727 url = url.replace(/^\.\//, ""); 728 729 newUrl = currentPath + url; 730 731 return originalOpen(newUrl, windowName, windowFeatures, replaceFlag); 732 }; 733 }; 734 735 var PageBot = function(browserbot) { 736 this.browserbot = browserbot; 737 this._registerAllLocatorFunctions(); 738 }; 739 740 PageBot.prototype._registerAllLocatorFunctions = function() { 741 // TODO - don't do this in the constructor - only needed once ever 742 this.locationStrategies = {}; 743 for (var functionName in this) { 744 var result = /^locateElementBy([A-Z].+)$/.exec(functionName); 745 if (result != null) { 746 var locatorFunction = this[functionName]; 747 if (typeof(locatorFunction) != 'function') { 748 continue; 749 } 750 // Use a specified prefix in preference to one generated from 751 // the function name 752 var locatorPrefix = locatorFunction.prefix || result[1].toLowerCase(); 753 this.locationStrategies[locatorPrefix] = locatorFunction; 754 } 755 } 756 757 /** 758 * Find a locator based on a prefix. 759 */ 760 this.findElementBy = function(locatorType, locator, inDocument, inWindow) { 761 var locatorFunction = this.locationStrategies[locatorType]; 762 if (! locatorFunction) { 763 throw new SeleniumError("Unrecognised locator type: '" + locatorType + "'"); 764 } 765 return locatorFunction.call(this, locator, inDocument, inWindow); 766 }; 767 768 /** 769 * The implicit locator, that is used when no prefix is supplied. 770 */ 771 this.locationStrategies['implicit'] = function(locator, inDocument, inWindow) { 772 if (locator.startsWith('//')) { 773 return this.locateElementByXPath(locator, inDocument, inWindow); 774 } 775 if (locator.startsWith('document.')) { 776 return this.locateElementByDomTraversal(locator, inDocument, inWindow); 777 } 778 return this.locateElementByIdentifier(locator, inDocument, inWindow); 779 }; 780 } 781 782 PageBot.prototype.getDocument = function() { 783 return this.getCurrentWindow().document; 784 } 785 786 PageBot.prototype.getCurrentWindow = function() { 787 return this.browserbot.getCurrentWindow(); 788 } 789 790 PageBot.prototype.getTitle = function() { 791 var t = this.getDocument().title; 792 if (typeof(t) == "string") { 793 t = t.trim(); 794 } 795 return t; 796 } 797 798 // todo: this is a bad name ... we're not passing a window in 799 PageBot.createForWindow = function(browserbot) { 800 if (browserVersion.isIE) { 801 return new IEPageBot(browserbot); 802 } 803 else if (browserVersion.isKonqueror) { 804 return new KonquerorPageBot(browserbot); 805 } 806 else if (browserVersion.isSafari) { 807 return new SafariPageBot(browserbot); 808 } 809 else if (browserVersion.isOpera) { 810 return new OperaPageBot(browserbot); 811 } 812 else { 813 // Use mozilla by default 814 return new MozillaPageBot(browserbot); 815 } 816 }; 817 818 var MozillaPageBot = function(browserbot) { 819 PageBot.call(this, browserbot); 820 }; 821 MozillaPageBot.prototype = new PageBot(); 822 823 var KonquerorPageBot = function(browserbot) { 824 PageBot.call(this, browserbot); 825 }; 826 KonquerorPageBot.prototype = new PageBot(); 827 828 var SafariPageBot = function(browserbot) { 829 PageBot.call(this, browserbot); 830 }; 831 SafariPageBot.prototype = new PageBot(); 832 833 var IEPageBot = function(browserbot) { 834 PageBot.call(this, browserbot); 835 }; 836 IEPageBot.prototype = new PageBot(); 837 838 var OperaPageBot = function(browserbot) { 839 PageBot.call(this, browserbot); 840 }; 841 OperaPageBot.prototype = new PageBot(); 842 843 /* 844 * Finds an element on the current page, using various lookup protocols 845 */ 846 PageBot.prototype.findElement = function(locator) { 847 var locatorType = 'implicit'; 848 var locatorString = locator; 849 850 // If there is a locator prefix, use the specified strategy 851 var result = locator.match(/^([A-Za-z]+)=(.+)/); 852 if (result) { 853 locatorType = result[1].toLowerCase(); 854 locatorString = result[2]; 855 } 856 857 var element = this.findElementBy(locatorType, locatorString, this.getDocument(), this.getCurrentWindow()); 858 if (element != null) { 859 return this.highlight(element); 860 } 861 for (var i = 0; i < this.getCurrentWindow().frames.length; i++) { 862 element = this.findElementBy(locatorType, locatorString, this.getCurrentWindow().frames[i].document, this.getCurrentWindow().frames[i]); 863 if (element != null) { 864 return this.highlight(element); 865 } 866 } 867 868 // Element was not found by any locator function. 869 throw new SeleniumError("Element " + locator + " not found"); 870 }; 871 872 PageBot.prototype.highlight = function (element) { 873 if (shouldHighlightLocatedElement) { 874 Effect.highlight(element); 875 } 876 return element; 877 } 878 879 // as a static variable. 880 var shouldHighlightLocatedElement = false; 881 882 PageBot.prototype.setHighlightElement = function (shouldHighlight) { 883 shouldHighlightLocatedElement = shouldHighlight; 884 } 885 886 /** 887 * In non-IE browsers, getElementById() does not search by name. Instead, we 888 * we search separately by id and name. 889 */ 890 PageBot.prototype.locateElementByIdentifier = function(identifier, inDocument, inWindow) { 891 return PageBot.prototype.locateElementById(identifier, inDocument, inWindow) 892 || PageBot.prototype.locateElementByName(identifier, inDocument, inWindow) 893 || null; 894 }; 895 896 /** 897 * In IE, getElementById() also searches by name - this is an optimisation for IE. 898 */ 899 IEPageBot.prototype.locateElementByIdentifer = function(identifier, inDocument, inWindow) { 900 return inDocument.getElementById(identifier); 901 }; 902 903 /** 904 * Find the element with id - can't rely on getElementById, coz it returns by name as well in IE.. 905 */ 906 PageBot.prototype.locateElementById = function(identifier, inDocument, inWindow) { 907 var element = inDocument.getElementById(identifier); 908 if (element && element.id === identifier) { 909 return element; 910 } 911 else { 912 return null; 913 } 914 }; 915 916 /** 917 * Find an element by name, refined by (optional) element-filter 918 * expressions. 919 */ 920 PageBot.prototype.locateElementByName = function(locator, document, inWindow) { 921 var elements = document.getElementsByTagName("*"); 922 923 var filters = locator.split(' '); 924 filters[0] = 'name=' + filters[0]; 925 926 while (filters.length) { 927 var filter = filters.shift(); 928 elements = this.selectElements(filter, elements, 'value'); 929 } 930 931 if (elements.length > 0) { 932 return elements[0]; 933 } 934 return null; 935 }; 936 937 /** 938 * Finds an element using by evaluating the specfied string. 939 */ 940 PageBot.prototype.locateElementByDomTraversal = function(domTraversal, inDocument, inWindow) { 941 942 var element = null; 943 try { 944 if (browserVersion.isOpera) { 945 element = inWindow.eval(domTraversal); 946 } else { 947 element = eval("inWindow." + domTraversal); 948 } 949 } catch (e) { 950 e.isSeleniumError = true; 951 throw e; 952 } 953 954 if (!element) { 955 return null; 956 } 957 958 return element; 959 }; 960 PageBot.prototype.locateElementByDomTraversal.prefix = "dom"; 961 962 /** 963 * Finds an element identified by the xpath expression. Expressions _must_ 964 * begin with "//". 965 */ 966 PageBot.prototype.locateElementByXPath = function(xpath, inDocument, inWindow) { 967 968 // Trim any trailing "/": not valid xpath, and remains from attribute 969 // locator. 970 if (xpath.charAt(xpath.length - 1) == '/') { 971 xpath = xpath.slice(0, -1); 972 } 973 974 // Handle //tag 975 var match = xpath.match(/^\/\/(\w+|\*)$/); 976 if (match) { 977 var elements = inDocument.getElementsByTagName(match[1].toUpperCase()); 978 if (elements == null) return null; 979 return elements[0]; 980 } 981 982 // Handle //tag[@attr='value'] 983 var match = xpath.match(/^\/\/(\w+|\*)\[@(\w+)=('([^\']+)'|"([^\"]+)")\]$/); 984 if (match) { 985 return this._findElementByTagNameAndAttributeValue( 986 inDocument, 987 match[1].toUpperCase(), 988 match[2].toLowerCase(), 989 match[3].slice(1, -1) 990 ); 991 } 992 993 // Handle //tag[text()='value'] 994 var match = xpath.match(/^\/\/(\w+|\*)\[text\(\)=('([^\']+)'|"([^\"]+)")\]$/); 995 if (match) { 996 return this._findElementByTagNameAndText( 997 inDocument, 998 match[1].toUpperCase(), 999 match[2].slice(1, -1) 1000 ); 1001 } 1002 1003 return this._findElementUsingFullXPath(xpath, inDocument); 1004 }; 1005 1006 PageBot.prototype._findElementByTagNameAndAttributeValue = function( 1007 inDocument, tagName, attributeName, attributeValue 1008 ) { 1009 if (browserVersion.isIE && attributeName == "class") { 1010 attributeName = "className"; 1011 } 1012 var elements = inDocument.getElementsByTagName(tagName); 1013 for (var i = 0; i < elements.length; i++) { 1014 var elementAttr = elements[i].getAttribute(attributeName); 1015 if (elementAttr == attributeValue) { 1016 return elements[i]; 1017 } 1018 } 1019 return null; 1020 }; 1021 1022 PageBot.prototype._findElementByTagNameAndText = function( 1023 inDocument, tagName, text 1024 ) { 1025 var elements = inDocument.getElementsByTagName(tagName); 1026 for (var i = 0; i < elements.length; i++) { 1027 if (getText(elements[i]) == text) { 1028 return elements[i]; 1029 } 1030 } 1031 return null; 1032 }; 1033 1034 PageBot.prototype._namespaceResolver = function(prefix) { 1035 if (prefix == 'html' || prefix == 'xhtml' || prefix == 'x') { 1036 return 'http://www.w3.org/1999/xhtml'; 1037 } else if (prefix == 'mathml') { 1038 return 'http://www.w3.org/1998/Math/MathML'; 1039 } else { 1040 throw new Error("Unknown namespace: " + prefix + "."); 1041 } 1042 } 1043 1044 PageBot.prototype._findElementUsingFullXPath = function(xpath, inDocument, inWindow) { 1045 // HUGE hack - remove namespace from xpath for IE 1046 if (browserVersion.isIE) { 1047 xpath = xpath.replace(/x:/g, '') 1048 } 1049 1050 // Use document.evaluate() if it's available 1051 if (inDocument.evaluate) { 1052 return inDocument.evaluate(xpath, inDocument, this._namespaceResolver, 0, null).iterateNext(); 1053 } 1054 1055 // If not, fall back to slower JavaScript implementation 1056 var context = new ExprContext(inDocument); 1057 var xpathObj = xpathParse(xpath); 1058 var xpathResult = xpathObj.evaluate(context); 1059 if (xpathResult && xpathResult.value) { 1060 return xpathResult.value[0]; 1061 } 1062 return null; 1063 }; 1064 1065 /** 1066 * Finds a link element with text matching the expression supplied. Expressions must 1067 * begin with "link:". 1068 */ 1069 PageBot.prototype.locateElementByLinkText = function(linkText, inDocument, inWindow) { 1070 var links = inDocument.getElementsByTagName('a'); 1071 for (var i = 0; i < links.length; i++) { 1072 var element = links[i]; 1073 if (PatternMatcher.matches(linkText, getText(element))) { 1074 return element; 1075 } 1076 } 1077 return null; 1078 }; 1079 PageBot.prototype.locateElementByLinkText.prefix = "link"; 1080 1081 /** 1082 * Returns an attribute based on an attribute locator. This is made up of an element locator 1083 * suffixed with @attribute-name. 1084 */ 1085 PageBot.prototype.findAttribute = function(locator) { 1086 // Split into locator + attributeName 1087 var attributePos = locator.lastIndexOf("@"); 1088 var elementLocator = locator.slice(0, attributePos); 1089 var attributeName = locator.slice(attributePos + 1); 1090 1091 // Find the element. 1092 var element = this.findElement(elementLocator); 1093 1094 // Handle missing "class" attribute in IE. 1095 if (browserVersion.isIE && attributeName == "class") { 1096 attributeName = "className"; 1097 } 1098 1099 // Get the attribute value. 1100 var attributeValue = element.getAttribute(attributeName); 1101 1102 return attributeValue ? attributeValue.toString() : null; 1103 }; 1104 1105 /* 1106 * Select the specified option and trigger the relevant events of the element. 1107 */ 1108 PageBot.prototype.selectOption = function(element, optionToSelect) { 1109 triggerEvent(element, 'focus', false); 1110 var changed = false; 1111 for (var i = 0; i < element.options.length; i++) { 1112 var option = element.options[i]; 1113 if (option.selected && option != optionToSelect) { 1114 option.selected = false; 1115 changed = true; 1116 } 1117 else if (!option.selected && option == optionToSelect) { 1118 option.selected = true; 1119 changed = true; 1120 } 1121 } 1122 1123 if (changed) { 1124 triggerEvent(element, 'change', true); 1125 } 1126 }; 1127 1128 /* 1129 * Select the specified option and trigger the relevant events of the element. 1130 */ 1131 PageBot.prototype.addSelection = function(element, option) { 1132 this.checkMultiselect(element); 1133 triggerEvent(element, 'focus', false); 1134 if (!option.selected) { 1135 option.selected = true; 1136 triggerEvent(element, 'change', true); 1137 } 1138 }; 1139 1140 /* 1141 * Select the specified option and trigger the relevant events of the element. 1142 */ 1143 PageBot.prototype.removeSelection = function(element, option) { 1144 this.checkMultiselect(element); 1145 triggerEvent(element, 'focus', false); 1146 if (option.selected) { 1147 option.selected = false; 1148 triggerEvent(element, 'change', true); 1149 } 1150 }; 1151 1152 PageBot.prototype.checkMultiselect = function(element) { 1153 if (!element.multiple) 1154 { 1155 throw new SeleniumError("Not a multi-select"); 1156 } 1157 1158 }; 1159 1160 PageBot.prototype.replaceText = function(element, stringValue) { 1161 triggerEvent(element, 'focus', false); 1162 triggerEvent(element, 'select', true); 1163 var maxLengthAttr = element.getAttribute("maxLength"); 1164 var actualValue = stringValue; 1165 if (maxLengthAttr != null) { 1166 var maxLength = parseInt(maxLengthAttr); 1167 if (stringValue.length > maxLength) { 1168 LOG.warn("BEFORE") 1169 actualValue = stringValue.substr(0, maxLength); 1170 LOG.warn("AFTER") 1171 } 1172 } 1173 element.value = actualValue; 1174 // DGF this used to be skipped in chrome URLs, but no longer. Is xpcnativewrappers to blame? 1175 triggerEvent(element, 'change', true); 1176 }; 1177 1178 MozillaPageBot.prototype.clickElement = function(element, clientX, clientY) { 1179 1180 triggerEvent(element, 'focus', false); 1181 1182 // Add an event listener that detects if the default action has been prevented. 1183 // (This is caused by a javascript onclick handler returning false) 1184 var preventDefault = false; 1185 1186 element.addEventListener("click", function(evt) { 1187 preventDefault = evt.getPreventDefault(); 1188 }, false); 1189 1190 // Trigger the click event. 1191 triggerMouseEvent(element, 'click', true, clientX, clientY); 1192 1193 // Perform the link action if preventDefault was set. 1194 // In chrome URL, the link action is already executed by triggerMouseEvent. 1195 if (!browserVersion.isChrome && !preventDefault) { 1196 var targetWindow = this.browserbot._getTargetWindow(element); 1197 if (element.href) { 1198 targetWindow.location.href = element.href; 1199 } else { 1200 this.browserbot._handleClickingImagesInsideLinks(targetWindow, element); 1201 } 1202 } 1203 1204 if (this._windowClosed()) { 1205 return; 1206 } 1207 1208 }; 1209 1210 BrowserBot.prototype._handleClickingImagesInsideLinks = function(targetWindow, element) { 1211 if (element.parentNode && element.parentNode.href) { 1212 targetWindow.location.href = element.parentNode.href; 1213 } 1214 } 1215 1216 BrowserBot.prototype._getTargetWindow = function(element) { 1217 var targetWindow = this.getCurrentWindow(); 1218 if (element.target) { 1219 var frame = this._getFrameFromGlobal(element.target); 1220 targetWindow = frame.contentWindow; 1221 } 1222 return targetWindow; 1223 } 1224 1225 BrowserBot.prototype._getFrameFromGlobal = function(target) { 1226 pagebot = PageBot.createForWindow(this); 1227 return pagebot.findElementBy("implicit", target, this.topWindow.document, this.topWindow); 1228 } 1229 1230 OperaPageBot.prototype.clickElement = function(element, clientX, clientY) { 1231 1232 triggerEvent(element, 'focus', false); 1233 1234 // Trigger the click event. 1235 triggerMouseEvent(element, 'click', true, clientX, clientY); 1236 1237 if (this._windowClosed()) { 1238 return; 1239 } 1240 1241 }; 1242 1243 1244 KonquerorPageBot.prototype.clickElement = function(element, clientX, clientY) { 1245 1246 triggerEvent(element, 'focus', false); 1247 1248 if (element.click) { 1249 element.click(); 1250 } 1251 else { 1252 triggerMouseEvent(element, 'click', true, clientX, clientY); 1253 } 1254 1255 if (this._windowClosed()) { 1256 return; 1257 } 1258 1259 }; 1260 1261 SafariPageBot.prototype.clickElement = function(element, clientX, clientY) { 1262 triggerEvent(element, 'focus', false); 1263 var wasChecked = element.checked; 1264 1265 // For form element it is simple. 1266 if (element.click) { 1267 element.click(); 1268 } 1269 // For links and other elements, event emulation is required. 1270 else { 1271 var targetWindow = this.browserbot._getTargetWindow(element); 1272 // todo: what if the target anchor is on another page? 1273 if (element.href && element.href.indexOf("#") != -1) { 1274 var b = targetWindow.document.getElementById(element.href.split("#")[1]); 1275 targetWindow.document.body.scrollTop = b.offsetTop; 1276 } else { 1277 triggerMouseEvent(element, 'click', true, clientX, clientY); 1278 } 1279 1280 } 1281 1282 }; 1283 1284 IEPageBot.prototype.clickElement = function(element, clientX, clientY) { 1285 1286 triggerEvent(element, 'focus', false); 1287 1288 var wasChecked = element.checked; 1289 1290 // Set a flag that records if the page will unload - this isn't always accurate, because 1291 // <a href="javascript:alert('foo'):"> triggers the onbeforeunload event, even thought the page won't unload 1292 var pageUnloading = false; 1293 var pageUnloadDetector = function() { 1294 pageUnloading = true; 1295 }; 1296 this.getCurrentWindow().attachEvent("onbeforeunload", pageUnloadDetector); 1297 element.click(); 1298 1299 1300 // If the page is going to unload - still attempt to fire any subsequent events. 1301 // However, we can't guarantee that the page won't unload half way through, so we need to handle exceptions. 1302 try { 1303 this.getCurrentWindow().detachEvent("onbeforeunload", pageUnloadDetector); 1304 1305 if (this._windowClosed()) { 1306 return; 1307 } 1308 1309 // Onchange event is not triggered automatically in IE. 1310 if (isDefined(element.checked) && wasChecked != element.checked) { 1311 triggerEvent(element, 'change', true); 1312 } 1313 1314 } 1315 catch (e) { 1316 // If the page is unloading, we may get a "Permission denied" or "Unspecified error". 1317 // Just ignore it, because the document may have unloaded. 1318 if (pageUnloading) { 1319 LOG.logHook = function() { 1320 }; 1321 LOG.warn("Caught exception when firing events on unloading page: " + e.message); 1322 return; 1323 } 1324 throw e; 1325 } 1326 }; 1327 1328 PageBot.prototype._windowClosed = function(element) { 1329 return selenium.browserbot._windowClosed(this.getCurrentWindow()); 1330 }; 1331 1332 PageBot.prototype.bodyText = function() { 1333 return getText(this.getDocument().body); 1334 }; 1335 1336 PageBot.prototype.getAllButtons = function() { 1337 var elements = this.getDocument().getElementsByTagName('input'); 1338 var result = ''; 1339 1340 for (var i = 0; i < elements.length; i++) { 1341 if (elements[i].type == 'button' || elements[i].type == 'submit' || elements[i].type == 'reset') { 1342 result += elements[i].id; 1343 1344 result += ','; 1345 } 1346 } 1347 1348 return result; 1349 }; 1350 1351 1352 PageBot.prototype.getAllFields = function() { 1353 var elements = this.getDocument().getElementsByTagName('input'); 1354 var result = ''; 1355 1356 for (var i = 0; i < elements.length; i++) { 1357 if (elements[i].type == 'text') { 1358 result += elements[i].id; 1359 1360 result += ','; 1361 } 1362 } 1363 1364 return result; 1365 }; 1366 1367 PageBot.prototype.getAllLinks = function() { 1368 var elements = this.getDocument().getElementsByTagName('a'); 1369 var result = ''; 1370 1371 for (var i = 0; i < elements.length; i++) { 1372 result += elements[i].id; 1373 1374 result += ','; 1375 } 1376 1377 return result; 1378 }; 1379 1380 PageBot.prototype.setContext = function(strContext, logLevel) { 1381 //set the current test title 1382 var ctx = document.getElementById("context"); 1383 if (ctx != null) { 1384 ctx.innerHTML = strContext; 1385 } 1386 if (logLevel != null) { 1387 LOG.setLogLevelThreshold(logLevel); 1388 } 1389 }; 1390 1391 function isDefined(value) { 1392 return typeof(value) != undefined; 1393 } 1394 1395 PageBot.prototype.goBack = function() { 1396 this.getCurrentWindow().history.back(); 1397 }; 1398 1399 PageBot.prototype.goForward = function() { 1400 this.getCurrentWindow().history.forward(); 1401 }; 1402 1403 PageBot.prototype.close = function() { 1404 if (browserVersion.isChrome || browserVersion.isSafari) { 1405 this.getCurrentWindow().close(); 1406 } else { 1407 this.getCurrentWindow().eval("window.close();"); 1408 } 1409 }; 1410 1411 PageBot.prototype.refresh = function() { 1412 this.getCurrentWindow().location.reload(true); 1413 }; 1414 1415 /** 1416 * Refine a list of elements using a filter. 1417 */ 1418 PageBot.prototype.selectElementsBy = function(filterType, filter, elements) { 1419 var filterFunction = PageBot.filterFunctions[filterType]; 1420 if (! filterFunction) { 1421 throw new SeleniumError("Unrecognised element-filter type: '" + filterType + "'"); 1422 } 1423 1424 return filterFunction(filter, elements); 1425 }; 1426 1427 PageBot.filterFunctions = {}; 1428 1429 PageBot.filterFunctions.name = function(name, elements) { 1430 var selectedElements = []; 1431 for (var i = 0; i < elements.length; i++) { 1432 if (elements[i].name === name) { 1433 selectedElements.push(elements[i]); 1434 } 1435 } 1436 return selectedElements; 1437 }; 1438 1439 PageBot.filterFunctions.value = function(value, elements) { 1440 var selectedElements = []; 1441 for (var i = 0; i < elements.length; i++) { 1442 if (elements[i].value === value) { 1443 selectedElements.push(elements[i]); 1444 } 1445 } 1446 return selectedElements; 1447 }; 1448 1449 PageBot.filterFunctions.index = function(index, elements) { 1450 index = Number(index); 1451 if (isNaN(index) || index < 0) { 1452 throw new SeleniumError("Illegal Index: " + index); 1453 } 1454 if (elements.length <= index) { 1455 throw new SeleniumError("Index out of range: " + index); 1456 } 1457 return [elements[index]]; 1458 }; 1459 1460 PageBot.prototype.selectElements = function(filterExpr, elements, defaultFilterType) { 1461 1462 var filterType = (defaultFilterType || 'value'); 1463 1464 // If there is a filter prefix, use the specified strategy 1465 var result = filterExpr.match(/^([A-Za-z]+)=(.+)/); 1466 if (result) { 1467 filterType = result[1].toLowerCase(); 1468 filterExpr = result[2]; 1469 } 1470 1471 return this.selectElementsBy(filterType, filterExpr, elements); 1472 }; 1473 1474 /** 1475 * Find an element by class 1476 */ 1477 PageBot.prototype.locateElementByClass = function(locator, document) { 1478 return Element.findFirstMatchingChild(document, 1479 function(element) { 1480 return element.className == locator 1481 } 1482 ); 1483 } 1484 1485 /** 1486 * Find an element by alt 1487 */ 1488 PageBot.prototype.locateElementByAlt = function(locator, document) { 1489 return Element.findFirstMatchingChild(document, 1490 function(element) { 1491 return element.alt == locator 1492 } 1493 ); 1494 } 1495 1496 /** 1497 * Find an element by css selector 1498 */ 1499 PageBot.prototype.locateElementByCss = function(locator, document) { 1500 var elements = cssQuery(locator, document); 1501 if (elements.length != 0) 1502 return elements[0]; 1503 return null; 1504 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |