[ Index ]
 

Code source de PRADO 3.0.6

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/tests/test_tools/selenium/core/scripts/ -> selenium-browserbot.js (source)

   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  }


Généré le : Sun Feb 25 21:07:04 2007 par Balluche grâce à PHPXref 0.7