[ 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 // This script contains a badly-organised collection of miscellaneous 19 // functions that really better homes. 20 21 String.prototype.trim = function() { 22 var result = this.replace(/^\s+/g, ""); 23 // strip leading 24 return result.replace(/\s+$/g, ""); 25 // strip trailing 26 }; 27 String.prototype.lcfirst = function() { 28 return this.charAt(0).toLowerCase() + this.substr(1); 29 }; 30 String.prototype.ucfirst = function() { 31 return this.charAt(0).toUpperCase() + this.substr(1); 32 }; 33 String.prototype.startsWith = function(str) { 34 return this.indexOf(str) == 0; 35 }; 36 37 // Returns the text in this element 38 function getText(element) { 39 var text = ""; 40 41 var isRecentFirefox = (browserVersion.isFirefox && browserVersion.firefoxVersion >= "1.5"); 42 if (isRecentFirefox || browserVersion.isKonqueror || browserVersion.isSafari || browserVersion.isOpera) { 43 text = getTextContent(element); 44 } else if (element.textContent) { 45 text = element.textContent; 46 } else if (element.innerText) { 47 text = element.innerText; 48 } 49 50 text = normalizeNewlines(text); 51 text = normalizeSpaces(text); 52 53 return text.trim(); 54 } 55 56 function getTextContent(element, preformatted) { 57 if (element.nodeType == 3 /*Node.TEXT_NODE*/) { 58 var text = element.data; 59 if (!preformatted) { 60 text = text.replace(/\n|\r|\t/g, " "); 61 } 62 return text; 63 } 64 if (element.nodeType == 1 /*Node.ELEMENT_NODE*/) { 65 var childrenPreformatted = preformatted || (element.tagName == "PRE"); 66 var text = ""; 67 for (var i = 0; i < element.childNodes.length; i++) { 68 var child = element.childNodes.item(i); 69 text += getTextContent(child, childrenPreformatted); 70 } 71 // Handle block elements that introduce newlines 72 // -- From HTML spec: 73 //<!ENTITY % block 74 // "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | 75 // BLOCKQUOTE | F:wORM | HR | TABLE | FIELDSET | ADDRESS"> 76 // 77 // TODO: should potentially introduce multiple newlines to separate blocks 78 if (element.tagName == "P" || element.tagName == "BR" || element.tagName == "HR" || element.tagName == "DIV") { 79 text += "\n"; 80 } 81 return text; 82 } 83 return ''; 84 } 85 86 /** 87 * Convert all newlines to \m 88 */ 89 function normalizeNewlines(text) 90 { 91 return text.replace(/\r\n|\r/g, "\n"); 92 } 93 94 /** 95 * Replace multiple sequential spaces with a single space, and then convert to space. 96 */ 97 function normalizeSpaces(text) 98 { 99 // IE has already done this conversion, so doing it again will remove multiple nbsp 100 if (browserVersion.isIE) 101 { 102 return text; 103 } 104 105 // Replace multiple spaces with a single space 106 // TODO - this shouldn't occur inside PRE elements 107 text = text.replace(/\ +/g, " "); 108 109 // Replace with a space 110 var nbspPattern = new RegExp(String.fromCharCode(160), "g"); 111 if (browserVersion.isSafari) { 112 return replaceAll(text, String.fromCharCode(160), " "); 113 } else { 114 return text.replace(nbspPattern, " "); 115 } 116 } 117 118 function replaceAll(text, oldText, newText) { 119 while (text.indexOf(oldText) != -1) { 120 text = text.replace(oldText, newText); 121 } 122 return text; 123 } 124 125 126 function xmlDecode(text) { 127 text = text.replace(/"/g, '"'); 128 text = text.replace(/'/g, "'"); 129 text = text.replace(/</g, "<"); 130 text = text.replace(/>/g, ">"); 131 text = text.replace(/&/g, "&"); 132 return text; 133 } 134 135 // Sets the text in this element 136 function setText(element, text) { 137 if (element.textContent) { 138 element.textContent = text; 139 } else if (element.innerText) { 140 element.innerText = text; 141 } 142 } 143 144 // Get the value of an <input> element 145 function getInputValue(inputElement) { 146 if (inputElement.type.toUpperCase() == 'CHECKBOX' || 147 inputElement.type.toUpperCase() == 'RADIO') 148 { 149 return (inputElement.checked ? 'on' : 'off'); 150 } 151 return inputElement.value; 152 } 153 154 /* Fire an event in a browser-compatible manner */ 155 function triggerEvent(element, eventType, canBubble) { 156 canBubble = (typeof(canBubble) == undefined) ? true : canBubble; 157 if (element.fireEvent) { 158 element.fireEvent('on' + eventType); 159 } 160 else { 161 var evt = document.createEvent('HTMLEvents'); 162 evt.initEvent(eventType, canBubble, true); 163 element.dispatchEvent(evt); 164 } 165 } 166 167 function getKeyCodeFromKeySequence(keySequence) { 168 var match = /^\\(\d{1,3})$/.exec(keySequence); 169 if (match != null) { 170 return match[1]; 171 } 172 match = /^.$/.exec(keySequence); 173 if (match != null) { 174 return match[0].charCodeAt(0); 175 } 176 // this is for backward compatibility with existing tests 177 // 1 digit ascii codes will break however because they are used for the digit chars 178 match = /^\d{2,3}$/.exec(keySequence); 179 if (match != null) { 180 return match[0]; 181 } 182 throw SeleniumError("invalid keySequence"); 183 } 184 185 function triggerKeyEvent(element, eventType, keySequence, canBubble) { 186 var keycode = getKeyCodeFromKeySequence(keySequence); 187 canBubble = (typeof(canBubble) == undefined) ? true : canBubble; 188 if (element.fireEvent) { 189 keyEvent = element.ownerDocument.createEventObject(); 190 keyEvent.keyCode = keycode; 191 element.fireEvent('on' + eventType, keyEvent); 192 } 193 else { 194 var evt; 195 if (window.KeyEvent) { 196 evt = document.createEvent('KeyEvents'); 197 evt.initKeyEvent(eventType, true, true, window, false, false, false, false, keycode, keycode); 198 } else { 199 evt = document.createEvent('UIEvents'); 200 evt.initUIEvent(eventType, true, true, window, 1); 201 evt.keyCode = keycode; 202 } 203 204 element.dispatchEvent(evt); 205 } 206 } 207 208 /* Fire a mouse event in a browser-compatible manner */ 209 function triggerMouseEvent(element, eventType, canBubble, clientX, clientY) { 210 clientX = clientX ? clientX : 0; 211 clientY = clientY ? clientY : 0; 212 213 // TODO: set these attributes -- they don't seem to be needed by the initial test cases, but that could change... 214 var screenX = 0; 215 var screenY = 0; 216 217 canBubble = (typeof(canBubble) == undefined) ? true : canBubble; 218 if (element.fireEvent) { 219 LOG.error("element has fireEvent"); 220 if (!screenX && !screenY && !clientX && !clientY) { 221 element.fireEvent('on' + eventType); 222 } 223 else { 224 var ieEvent = element.ownerDocument.createEventObject(); 225 ieEvent.detail = 0; 226 ieEvent.screenX = screenX; 227 ieEvent.screenY = screenY; 228 ieEvent.clientX = clientX; 229 ieEvent.clientY = clientY; 230 ieEvent.ctrlKey = false; 231 ieEvent.altKey = false; 232 ieEvent.shiftKey = false; 233 ieEvent.metaKey = false; 234 ieEvent.button = 1; 235 ieEvent.relatedTarget = null; 236 237 // when we go this route, window.event is never set to contain the event we have just created. 238 // ideally we could just slide it in as follows in the try-block below, but this normally 239 // doesn't work. This is why I try to avoid this code path, which is only required if we need to 240 // set attributes on the event (e.g., clientX). 241 try { 242 window.event = ieEvent; 243 } 244 catch(e) { 245 // getting an "Object does not support this action or property" error. Save the event away 246 // for future reference. 247 // TODO: is there a way to update window.event? 248 249 // work around for http://jira.openqa.org/browse/SEL-280 -- make the event available somewhere: 250 selenium.browserbot.getCurrentWindow().selenium_event = ieEvent; 251 } 252 element.fireEvent('on' + eventType, ieEvent); 253 } 254 } 255 else { 256 LOG.error("element doesn't have fireEvent"); 257 var evt = document.createEvent('MouseEvents'); 258 if (evt.initMouseEvent) 259 { 260 LOG.error("element has initMouseEvent"); 261 //Safari 262 evt.initMouseEvent(eventType, canBubble, true, document.defaultView, 1, screenX, screenY, clientX, clientY, false, false, false, false, 0, null) 263 } 264 else { 265 LOG.error("element doesen't has initMouseEvent"); 266 // TODO we should be initialising other mouse-event related attributes here 267 evt.initEvent(eventType, canBubble, true); 268 } 269 element.dispatchEvent(evt); 270 } 271 } 272 273 function removeLoadListener(element, command) { 274 LOG.info('Removing loadListenter for ' + element + ', ' + command); 275 if (window.removeEventListener) 276 element.removeEventListener("load", command, true); 277 else if (window.detachEvent) 278 element.detachEvent("onload", command); 279 } 280 281 function addLoadListener(element, command) { 282 LOG.info('Adding loadListenter for ' + element + ', ' + command); 283 if (window.addEventListener && !browserVersion.isOpera) 284 element.addEventListener("load", command, true); 285 else if (window.attachEvent) 286 element.attachEvent("onload", command); 287 } 288 289 /** 290 * Override the broken getFunctionName() method from JsUnit 291 * This file must be loaded _after_ the jsunitCore.js 292 */ 293 function getFunctionName(aFunction) { 294 var regexpResult = aFunction.toString().match(/function (\w*)/); 295 if (regexpResult && regexpResult[1]) { 296 return regexpResult[1]; 297 } 298 return 'anonymous'; 299 } 300 301 function getDocumentBase(doc) { 302 var bases = document.getElementsByTagName("base"); 303 if (bases && bases.length && bases[0].href) { 304 return bases[0].href; 305 } 306 return ""; 307 } 308 309 function describe(object, delimiter) { 310 var props = new Array(); 311 for (var prop in object) { 312 props.push(prop + " -> " + object[prop]); 313 } 314 return props.join(delimiter || '\n'); 315 } 316 317 var PatternMatcher = function(pattern) { 318 this.selectStrategy(pattern); 319 }; 320 PatternMatcher.prototype = { 321 322 selectStrategy: function(pattern) { 323 this.pattern = pattern; 324 var strategyName = 'glob'; 325 // by default 326 if (/^([a-z-]+):(.*)/.test(pattern)) { 327 var possibleNewStrategyName = RegExp.$1; 328 var possibleNewPattern = RegExp.$2; 329 if (PatternMatcher.strategies[possibleNewStrategyName]) { 330 strategyName = possibleNewStrategyName; 331 pattern = possibleNewPattern; 332 } 333 } 334 var matchStrategy = PatternMatcher.strategies[strategyName]; 335 if (!matchStrategy) { 336 throw new SeleniumError("cannot find PatternMatcher.strategies." + strategyName); 337 } 338 this.strategy = matchStrategy; 339 this.matcher = new matchStrategy(pattern); 340 }, 341 342 matches: function(actual) { 343 return this.matcher.matches(actual + ''); 344 // Note: appending an empty string avoids a Konqueror bug 345 } 346 347 }; 348 349 /** 350 * A "static" convenience method for easy matching 351 */ 352 PatternMatcher.matches = function(pattern, actual) { 353 return new PatternMatcher(pattern).matches(actual); 354 }; 355 356 PatternMatcher.strategies = { 357 358 /** 359 * Exact matching, e.g. "exact:***" 360 */ 361 exact: function(expected) { 362 this.expected = expected; 363 this.matches = function(actual) { 364 return actual == this.expected; 365 }; 366 }, 367 368 /** 369 * Match by regular expression, e.g. "regexp:^[0-9]+$" 370 */ 371 regexp: function(regexpString) { 372 this.regexp = new RegExp(regexpString); 373 this.matches = function(actual) { 374 return this.regexp.test(actual); 375 }; 376 }, 377 378 regex: function(regexpString) { 379 this.regexp = new RegExp(regexpString); 380 this.matches = function(actual) { 381 return this.regexp.test(actual); 382 }; 383 }, 384 385 /** 386 * "globContains" (aka "wildmat") patterns, e.g. "glob:one,two,*", 387 * but don't require a perfect match; instead succeed if actual 388 * contains something that matches globString. 389 * Making this distinction is motivated by a bug in IE6 which 390 * leads to the browser hanging if we implement *TextPresent tests 391 * by just matching against a regular expression beginning and 392 * ending with ".*". The globcontains strategy allows us to satisfy 393 * the functional needs of the *TextPresent ops more efficiently 394 * and so avoid running into this IE6 freeze. 395 */ 396 globContains: function(globString) { 397 this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString)); 398 this.matches = function(actual) { 399 return this.regexp.test(actual); 400 }; 401 }, 402 403 404 /** 405 * "glob" (aka "wildmat") patterns, e.g. "glob:one,two,*" 406 */ 407 glob: function(globString) { 408 this.regexp = new RegExp(PatternMatcher.regexpFromGlob(globString)); 409 this.matches = function(actual) { 410 return this.regexp.test(actual); 411 }; 412 } 413 414 }; 415 416 PatternMatcher.convertGlobMetaCharsToRegexpMetaChars = function(glob) { 417 var re = glob; 418 re = re.replace(/([.^$+(){}\[\]\\|])/g, "\\$1"); 419 re = re.replace(/\?/g, "(.|[\r\n])"); 420 re = re.replace(/\*/g, "(.|[\r\n])*"); 421 return re; 422 }; 423 424 PatternMatcher.regexpFromGlobContains = function(globContains) { 425 return PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(globContains); 426 }; 427 428 PatternMatcher.regexpFromGlob = function(glob) { 429 return "^" + PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(glob) + "$"; 430 }; 431 432 var Assert = { 433 434 fail: function(message) { 435 throw new AssertionFailedError(message); 436 }, 437 438 /* 439 * Assert.equals(comment?, expected, actual) 440 */ 441 equals: function() { 442 var args = new AssertionArguments(arguments); 443 if (args.expected === args.actual) { 444 return; 445 } 446 Assert.fail(args.comment + 447 "Expected '" + args.expected + 448 "' but was '" + args.actual + "'"); 449 }, 450 451 /* 452 * Assert.matches(comment?, pattern, actual) 453 */ 454 matches: function() { 455 var args = new AssertionArguments(arguments); 456 if (PatternMatcher.matches(args.expected, args.actual)) { 457 return; 458 } 459 Assert.fail(args.comment + 460 "Actual value '" + args.actual + 461 "' did not match '" + args.expected + "'"); 462 }, 463 464 /* 465 * Assert.notMtches(comment?, pattern, actual) 466 */ 467 notMatches: function() { 468 var args = new AssertionArguments(arguments); 469 if (!PatternMatcher.matches(args.expected, args.actual)) { 470 return; 471 } 472 Assert.fail(args.comment + 473 "Actual value '" + args.actual + 474 "' did match '" + args.expected + "'"); 475 } 476 477 }; 478 479 // Preprocess the arguments to allow for an optional comment. 480 function AssertionArguments(args) { 481 if (args.length == 2) { 482 this.comment = ""; 483 this.expected = args[0]; 484 this.actual = args[1]; 485 } else { 486 this.comment = args[0] + "; "; 487 this.expected = args[1]; 488 this.actual = args[2]; 489 } 490 } 491 492 function AssertionFailedError(message) { 493 this.isAssertionFailedError = true; 494 this.isSeleniumError = true; 495 this.message = message; 496 this.failureMessage = message; 497 } 498 499 function SeleniumError(message) { 500 var error = new Error(message); 501 error.isSeleniumError = true; 502 return error; 503 } 504 505 var Effect = new Object(); 506 507 Object.extend(Effect, { 508 highlight : function(element) { 509 var highLightColor = "yellow"; 510 if (element.originalColor == undefined) { // avoid picking up highlight 511 element.originalColor = Element.getStyle(element, "background-color"); 512 } 513 Element.setStyle(element, {"background-color" : highLightColor}); 514 window.setTimeout(function() { 515 //if element is orphan, probably page of it has already gone, so ignore 516 if (!element.parentNode) { 517 return; 518 } 519 Element.setStyle(element, {"background-color" : element.originalColor}); 520 }, 200); 521 } 522 }); 523 524 525 // for use from vs.2003 debugger 526 function objToString(obj) { 527 var s = ""; 528 for (key in obj) { 529 var line = key + "->" + obj[key]; 530 line.replace("\n", " "); 531 s += line + "\n"; 532 } 533 return s; 534 } 535 536 var seenReadyStateWarning = false; 537 538 function openSeparateApplicationWindow(url) { 539 // resize the Selenium window itself 540 window.resizeTo(1200, 500); 541 window.moveTo(window.screenX, 0); 542 543 var appWindow = window.open(url + '?start=true', 'main'); 544 try { 545 var windowHeight = 500; 546 if (window.outerHeight) { 547 windowHeight = window.outerHeight; 548 } else if (document.documentElement && document.documentElement.offsetHeight) { 549 windowHeight = document.documentElement.offsetHeight; 550 } 551 552 if (window.screenLeft && !window.screenX) window.screenX = window.screenLeft; 553 if (window.screenTop && !window.screenY) window.screenY = window.screenTop; 554 555 appWindow.resizeTo(1200, screen.availHeight - windowHeight - 60); 556 appWindow.moveTo(window.screenX, window.screenY + windowHeight + 25); 557 } catch (e) { 558 LOG.error("Couldn't resize app window"); 559 LOG.exception(e); 560 } 561 562 563 if (window.document.readyState == null && !seenReadyStateWarning) { 564 alert("Beware! Mozilla bug 300992 means that we can't always reliably detect when a new page has loaded. Install the Selenium IDE extension or the readyState extension available from selenium.openqa.org to make page load detection more reliable."); 565 seenReadyStateWarning = true; 566 } 567 568 return appWindow; 569 } 570 571 var URLConfiguration = Class.create(); 572 Object.extend(URLConfiguration.prototype, { 573 initialize: function() { 574 }, 575 _isQueryParameterTrue: function (name) { 576 var parameterValue = this._getQueryParameter(name); 577 if (parameterValue == null) return false; 578 if (parameterValue.toLowerCase() == "true") return true; 579 if (parameterValue.toLowerCase() == "on") return true; 580 return false; 581 }, 582 583 _getQueryParameter: function(searchKey) { 584 var str = this.queryString 585 if (str == null) return null; 586 var clauses = str.split('&'); 587 for (var i = 0; i < clauses.length; i++) { 588 var keyValuePair = clauses[i].split('=', 2); 589 var key = unescape(keyValuePair[0]); 590 if (key == searchKey) { 591 return unescape(keyValuePair[1]); 592 } 593 } 594 return null; 595 }, 596 597 _extractArgs: function() { 598 var str = SeleniumHTARunner.commandLine; 599 if (str == null || str == "") return new Array(); 600 var matches = str.match(/(?:\"([^\"]+)\"|(?!\"([^\"]+)\")(\S+))/g); 601 // We either want non quote stuff ([^"]+) surrounded by quotes 602 // or we want to look-ahead, see that the next character isn't 603 // a quoted argument, and then grab all the non-space stuff 604 // this will return for the line: "foo" bar 605 // the results "\"foo\"" and "bar" 606 607 // So, let's unquote the quoted arguments: 608 var args = new Array; 609 for (var i = 0; i < matches.length; i++) { 610 args[i] = matches[i]; 611 args[i] = args[i].replace(/^"(.*)"$/, "$1"); 612 } 613 return args; 614 }, 615 616 isMultiWindowMode:function() { 617 return this._isQueryParameterTrue('multiWindow'); 618 } 619 }); 620 621 622 function safeScrollIntoView(element) { 623 if (element.scrollIntoView) { 624 element.scrollIntoView(false); 625 return; 626 } 627 // TODO: work out how to scroll browsers that don't support 628 // scrollIntoView (like Konqueror) 629 }
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 |