diff options
Diffstat (limited to 'tests/test_tools/selenium/core/scripts/htmlutils.js')
-rw-r--r-- | tests/test_tools/selenium/core/scripts/htmlutils.js | 842 |
1 files changed, 0 insertions, 842 deletions
diff --git a/tests/test_tools/selenium/core/scripts/htmlutils.js b/tests/test_tools/selenium/core/scripts/htmlutils.js deleted file mode 100644 index a3cd3dd9..00000000 --- a/tests/test_tools/selenium/core/scripts/htmlutils.js +++ /dev/null @@ -1,842 +0,0 @@ -/* - * Copyright 2004 ThoughtWorks, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// This script contains a badly-organised collection of miscellaneous -// functions that really better homes. - -function classCreate() { - return function() { - this.initialize.apply(this, arguments); - } -} - -function objectExtend(destination, source) { - for (var property in source) { - destination[property] = source[property]; - } - return destination; -} - -function $() { - var results = [], element; - for (var i = 0; i < arguments.length; i++) { - element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - results[results.length] = element; - } - return results.length < 2 ? results[0] : results; -} - -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -function fnBind() { - var args = $A(arguments), __method = args.shift(), object = args.shift(); - var retval = function() { - return __method.apply(object, args.concat($A(arguments))); - } - retval.__method = __method; - return retval; -} - -function fnBindAsEventListener(fn, object) { - var __method = fn; - return function(event) { - return __method.call(object, event || window.event); - } -} - -function removeClassName(element, name) { - var re = new RegExp("\\b" + name + "\\b", "g"); - element.className = element.className.replace(re, ""); -} - -function addClassName(element, name) { - element.className = element.className + ' ' + name; -} - -function elementSetStyle(element, style) { - for (var name in style) { - var value = style[name]; - if (value == null) value = ""; - element.style[name] = value; - } -} - -function elementGetStyle(element, style) { - var value = element.style[style]; - if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; - } else if (element.currentStyle) { - value = element.currentStyle[style]; - } - } - - /** DGF necessary? - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; */ - - return value == 'auto' ? null : value; - } - -String.prototype.trim = function() { - var result = this.replace(/^\s+/g, ""); - // strip leading - return result.replace(/\s+$/g, ""); - // strip trailing -}; -String.prototype.lcfirst = function() { - return this.charAt(0).toLowerCase() + this.substr(1); -}; -String.prototype.ucfirst = function() { - return this.charAt(0).toUpperCase() + this.substr(1); -}; -String.prototype.startsWith = function(str) { - return this.indexOf(str) == 0; -}; - -// Returns the text in this element -function getText(element) { - var text = ""; - - var isRecentFirefox = (browserVersion.isFirefox && browserVersion.firefoxVersion >= "1.5"); - if (isRecentFirefox || browserVersion.isKonqueror || browserVersion.isSafari || browserVersion.isOpera) { - text = getTextContent(element); - } else if (element.textContent) { - text = element.textContent; - } else if (element.innerText) { - text = element.innerText; - } - - text = normalizeNewlines(text); - text = normalizeSpaces(text); - - return text.trim(); -} - -function getTextContent(element, preformatted) { - if (element.nodeType == 3 /*Node.TEXT_NODE*/) { - var text = element.data; - if (!preformatted) { - text = text.replace(/\n|\r|\t/g, " "); - } - return text; - } - if (element.nodeType == 1 /*Node.ELEMENT_NODE*/) { - var childrenPreformatted = preformatted || (element.tagName == "PRE"); - var text = ""; - for (var i = 0; i < element.childNodes.length; i++) { - var child = element.childNodes.item(i); - text += getTextContent(child, childrenPreformatted); - } - // Handle block elements that introduce newlines - // -- From HTML spec: - //<!ENTITY % block - // "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | - // BLOCKQUOTE | F:wORM | HR | TABLE | FIELDSET | ADDRESS"> - // - // TODO: should potentially introduce multiple newlines to separate blocks - if (element.tagName == "P" || element.tagName == "BR" || element.tagName == "HR" || element.tagName == "DIV") { - text += "\n"; - } - return text; - } - return ''; -} - -/** - * Convert all newlines to \m - */ -function normalizeNewlines(text) -{ - return text.replace(/\r\n|\r/g, "\n"); -} - -/** - * Replace multiple sequential spaces with a single space, and then convert to space. - */ -function normalizeSpaces(text) -{ - // IE has already done this conversion, so doing it again will remove multiple nbsp - if (browserVersion.isIE) - { - return text; - } - - // Replace multiple spaces with a single space - // TODO - this shouldn't occur inside PRE elements - text = text.replace(/\ +/g, " "); - - // Replace with a space - var nbspPattern = new RegExp(String.fromCharCode(160), "g"); - if (browserVersion.isSafari) { - return replaceAll(text, String.fromCharCode(160), " "); - } else { - return text.replace(nbspPattern, " "); - } -} - -function replaceAll(text, oldText, newText) { - while (text.indexOf(oldText) != -1) { - text = text.replace(oldText, newText); - } - return text; -} - - -function xmlDecode(text) { - text = text.replace(/"/g, '"'); - text = text.replace(/'/g, "'"); - text = text.replace(/</g, "<"); - text = text.replace(/>/g, ">"); - text = text.replace(/&/g, "&"); - return text; -} - -// Sets the text in this element -function setText(element, text) { - if (element.textContent != null) { - element.textContent = text; - } else if (element.innerText != null) { - element.innerText = text; - } -} - -// Get the value of an <input> element -function getInputValue(inputElement) { - if (inputElement.type) { - if (inputElement.type.toUpperCase() == 'CHECKBOX' || - inputElement.type.toUpperCase() == 'RADIO') - { - return (inputElement.checked ? 'on' : 'off'); - } - } - if (inputElement.value == null) { - throw new SeleniumError("This element has no value; is it really a form field?"); - } - return inputElement.value; -} - -/* Fire an event in a browser-compatible manner */ -function triggerEvent(element, eventType, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) { - canBubble = (typeof(canBubble) == undefined) ? true : canBubble; - if (element.fireEvent) { - var evt = createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown); - element.fireEvent('on' + eventType, evt); - } - else { - var evt = document.createEvent('HTMLEvents'); - - try { - evt.shiftKey = shiftKeyDown; - evt.metaKey = metaKeyDown; - evt.altKey = altKeyDown; - evt.ctrlKey = controlKeyDown; - } catch (e) { - // On Firefox 1.0, you can only set these during initMouseEvent or initKeyEvent - // we'll have to ignore them here - LOG.exception(e); - } - - evt.initEvent(eventType, canBubble, true); - element.dispatchEvent(evt); - } -} - -function getKeyCodeFromKeySequence(keySequence) { - var match = /^\\(\d{1,3})$/.exec(keySequence); - if (match != null) { - return match[1]; - } - match = /^.$/.exec(keySequence); - if (match != null) { - return match[0].charCodeAt(0); - } - // this is for backward compatibility with existing tests - // 1 digit ascii codes will break however because they are used for the digit chars - match = /^\d{2,3}$/.exec(keySequence); - if (match != null) { - return match[0]; - } - throw new SeleniumError("invalid keySequence"); -} - -function createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) { - var evt = element.ownerDocument.createEventObject(); - evt.shiftKey = shiftKeyDown; - evt.metaKey = metaKeyDown; - evt.altKey = altKeyDown; - evt.ctrlKey = controlKeyDown; - return evt; -} - -function triggerKeyEvent(element, eventType, keySequence, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) { - var keycode = getKeyCodeFromKeySequence(keySequence); - canBubble = (typeof(canBubble) == undefined) ? true : canBubble; - if (element.fireEvent) { - var keyEvent = createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown); - keyEvent.keyCode = keycode; - element.fireEvent('on' + eventType, keyEvent); - } - else { - var evt; - if (window.KeyEvent) { - evt = document.createEvent('KeyEvents'); - evt.initKeyEvent(eventType, true, true, window, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown, keycode, keycode); - } else { - evt = document.createEvent('UIEvents'); - - evt.shiftKey = shiftKeyDown; - evt.metaKey = metaKeyDown; - evt.altKey = altKeyDown; - evt.ctrlKey = controlKeyDown; - - evt.initUIEvent(eventType, true, true, window, 1); - evt.keyCode = keycode; - evt.which = keycode; - } - - element.dispatchEvent(evt); - } -} - -function removeLoadListener(element, command) { - LOG.info('Removing loadListenter for ' + element + ', ' + command); - if (window.removeEventListener) - element.removeEventListener("load", command, true); - else if (window.detachEvent) - element.detachEvent("onload", command); -} - -function addLoadListener(element, command) { - LOG.info('Adding loadListenter for ' + element + ', ' + command); - var augmentedCommand = function() { - command.call(this, element); - } - if (window.addEventListener && !browserVersion.isOpera) - element.addEventListener("load", augmentedCommand, true); - else if (window.attachEvent) - element.attachEvent("onload", augmentedCommand); -} - -/** - * Override the broken getFunctionName() method from JsUnit - * This file must be loaded _after_ the jsunitCore.js - */ -function getFunctionName(aFunction) { - var regexpResult = aFunction.toString().match(/function (\w*)/); - if (regexpResult && regexpResult[1]) { - return regexpResult[1]; - } - return 'anonymous'; -} - -function getDocumentBase(doc) { - var bases = document.getElementsByTagName("base"); - if (bases && bases.length && bases[0].href) { - return bases[0].href; - } - return ""; -} - -function getTagName(element) { - var tagName; - if (element && element.tagName && element.tagName.toLowerCase) { - tagName = element.tagName.toLowerCase(); - } - return tagName; -} - -function absolutify(url, baseUrl) { - /** returns a relative url in its absolute form, given by baseUrl. - * - * This function is a little odd, because it can take baseUrls that - * aren't necessarily directories. It uses the same rules as the HTML - * <base> tag; if the baseUrl doesn't end with "/", we'll assume - * that it points to a file, and strip the filename off to find its - * base directory. - * - * So absolutify("foo", "http://x/bar") will return "http://x/foo" (stripping off bar), - * whereas absolutify("foo", "http://x/bar/") will return "http://x/bar/foo" (preserving bar). - * Naturally absolutify("foo", "http://x") will return "http://x/foo", appropriately. - * - * @param url the url to make absolute; if this url is already absolute, we'll just return that, unchanged - * @param baseUrl the baseUrl from which we'll absolutify, following the rules above. - * @return 'url' if it was already absolute, or the absolutized version of url if it was not absolute. - */ - - // DGF isn't there some library we could use for this? - - if (/^\w+:/.test(url)) { - // it's already absolute - return url; - } - - var loc; - try { - loc = parseUrl(baseUrl); - } catch (e) { - // is it an absolute windows file path? let's play the hero in that case - if (/^\w:\\/.test(baseUrl)) { - baseUrl = "file:///" + baseUrl.replace(/\\/g, "/"); - loc = parseUrl(baseUrl); - } else { - throw new SeleniumError("baseUrl wasn't absolute: " + baseUrl); - } - } - loc.search = null; - loc.hash = null; - - // if url begins with /, then that's the whole pathname - if (/^\//.test(url)) { - loc.pathname = url; - var result = reassembleLocation(loc); - return result; - } - - // if pathname is null, then we'll just append "/" + the url - if (!loc.pathname) { - loc.pathname = "/" + url; - var result = reassembleLocation(loc); - return result; - } - - // if pathname ends with /, just append url - if (/\/$/.test(loc.pathname)) { - loc.pathname += url; - var result = reassembleLocation(loc); - return result; - } - - // if we're here, then the baseUrl has a pathname, but it doesn't end with / - // in that case, we replace everything after the final / with the relative url - loc.pathname = loc.pathname.replace(/[^\/\\]+$/, url); - var result = reassembleLocation(loc); - return result; - -} - -var URL_REGEX = /^((\w+):\/\/)(([^:]+):?([^@]+)?@)?([^\/\?:]*):?(\d+)?(\/?[^\?#]+)?\??([^#]+)?#?(.+)?/; - -function parseUrl(url) { - var fields = ['url', null, 'protocol', null, 'username', 'password', 'host', 'port', 'pathname', 'search', 'hash']; - var result = URL_REGEX.exec(url); - if (!result) { - throw new SeleniumError("Invalid URL: " + url); - } - var loc = new Object(); - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - if (field == null) { - continue; - } - loc[field] = result[i]; - } - return loc; -} - -function reassembleLocation(loc) { - if (!loc.protocol) { - throw new Error("Not a valid location object: " + o2s(loc)); - } - var protocol = loc.protocol; - protocol = protocol.replace(/:$/, ""); - var url = protocol + "://"; - if (loc.username) { - url += loc.username; - if (loc.password) { - url += ":" + loc.password; - } - url += "@"; - } - if (loc.host) { - url += loc.host; - } - - if (loc.port) { - url += ":" + loc.port; - } - - if (loc.pathname) { - url += loc.pathname; - } - - if (loc.search) { - url += "?" + loc.search; - } - if (loc.hash) { - var hash = loc.hash; - hash = loc.hash.replace(/^#/, ""); - url += "#" + hash; - } - return url; -} - -function canonicalize(url) { - var tempLink = window.document.createElement("link"); - tempLink.href = url; // this will canonicalize the href - return tempLink.href; -} - -function extractExceptionMessage(ex) { - if (ex == null) return "null exception"; - if (ex.message != null) return ex.message; - if (ex.toString && ex.toString() != null) return ex.toString(); -} - - -function describe(object, delimiter) { - var props = new Array(); - for (var prop in object) { - try { - props.push(prop + " -> " + object[prop]); - } catch (e) { - props.push(prop + " -> [htmlutils: ack! couldn't read this property! (Permission Denied?)]"); - } - } - return props.join(delimiter || '\n'); -} - -var PatternMatcher = function(pattern) { - this.selectStrategy(pattern); -}; -PatternMatcher.prototype = { - - selectStrategy: function(pattern) { - this.pattern = pattern; - var strategyName = 'glob'; - // by default - if (/^([a-z-]+):(.*)/.test(pattern)) { - var possibleNewStrategyName = RegExp.$1; - var possibleNewPattern = RegExp.$2; - if (PatternMatcher.strategies[possibleNewStrategyName]) { - strategyName = possibleNewStrategyName; - pattern = possibleNewPattern; - } - } - var matchStrategy = PatternMatcher.strategies[strategyName]; - if (!matchStrategy) { - throw new SeleniumError("cannot find PatternMatcher.strategies." + strategyName); - } - this.strategy = matchStrategy; - this.matcher = new matchStrategy(pattern); - }, - - matches: function(actual) { - return this.matcher.matches(actual + ''); - // Note: appending an empty string avoids a Konqueror bug - } - -}; - -/** - * A "static" convenience method for easy matching - */ -PatternMatcher.matches = function(pattern, actual) { - return new PatternMatcher(pattern).matches(actual); -}; - -PatternMatcher.strategies = { - -/** - * Exact matching, e.g. "exact:***" - */ - exact: function(expected) { - this.expected = expected; - this.matches = function(actual) { - return actual == this.expected; - }; - }, - -/** - * Match by regular expression, e.g. "regexp:^[0-9]+$" - */ - regexp: function(regexpString) { - this.regexp = new RegExp(regexpString); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - }, - - regex: function(regexpString) { - this.regexp = new RegExp(regexpString); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - }, - -/** - * "globContains" (aka "wildmat") patterns, e.g. "glob:one,two,*", - * but don't require a perfect match; instead succeed if actual - * contains something that matches globString. - * Making this distinction is motivated by a bug in IE6 which - * leads to the browser hanging if we implement *TextPresent tests - * by just matching against a regular expression beginning and - * ending with ".*". The globcontains strategy allows us to satisfy - * the functional needs of the *TextPresent ops more efficiently - * and so avoid running into this IE6 freeze. - */ - globContains: function(globString) { - this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString)); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - }, - - -/** - * "glob" (aka "wildmat") patterns, e.g. "glob:one,two,*" - */ - glob: function(globString) { - this.regexp = new RegExp(PatternMatcher.regexpFromGlob(globString)); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - } - -}; - -PatternMatcher.convertGlobMetaCharsToRegexpMetaChars = function(glob) { - var re = glob; - re = re.replace(/([.^$+(){}\[\]\\|])/g, "\\$1"); - re = re.replace(/\?/g, "(.|[\r\n])"); - re = re.replace(/\*/g, "(.|[\r\n])*"); - return re; -}; - -PatternMatcher.regexpFromGlobContains = function(globContains) { - return PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(globContains); -}; - -PatternMatcher.regexpFromGlob = function(glob) { - return "^" + PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(glob) + "$"; -}; - -var Assert = { - - fail: function(message) { - throw new AssertionFailedError(message); - }, - -/* -* Assert.equals(comment?, expected, actual) -*/ - equals: function() { - var args = new AssertionArguments(arguments); - if (args.expected === args.actual) { - return; - } - Assert.fail(args.comment + - "Expected '" + args.expected + - "' but was '" + args.actual + "'"); - }, - -/* -* Assert.matches(comment?, pattern, actual) -*/ - matches: function() { - var args = new AssertionArguments(arguments); - if (PatternMatcher.matches(args.expected, args.actual)) { - return; - } - Assert.fail(args.comment + - "Actual value '" + args.actual + - "' did not match '" + args.expected + "'"); - }, - -/* -* Assert.notMtches(comment?, pattern, actual) -*/ - notMatches: function() { - var args = new AssertionArguments(arguments); - if (!PatternMatcher.matches(args.expected, args.actual)) { - return; - } - Assert.fail(args.comment + - "Actual value '" + args.actual + - "' did match '" + args.expected + "'"); - } - -}; - -// Preprocess the arguments to allow for an optional comment. -function AssertionArguments(args) { - if (args.length == 2) { - this.comment = ""; - this.expected = args[0]; - this.actual = args[1]; - } else { - this.comment = args[0] + "; "; - this.expected = args[1]; - this.actual = args[2]; - } -} - -function AssertionFailedError(message) { - this.isAssertionFailedError = true; - this.isSeleniumError = true; - this.message = message; - this.failureMessage = message; -} - -function SeleniumError(message) { - var error = new Error(message); - error.isSeleniumError = true; - return error; -} - -function highlight(element) { - var highLightColor = "yellow"; - if (element.originalColor == undefined) { // avoid picking up highlight - element.originalColor = elementGetStyle(element, "background-color"); - } - elementSetStyle(element, {"backgroundColor" : highLightColor}); - window.setTimeout(function() { - try { - //if element is orphan, probably page of it has already gone, so ignore - if (!element.parentNode) { - return; - } - elementSetStyle(element, {"backgroundColor" : element.originalColor}); - } catch (e) {} // DGF unhighlighting is very dangerous and low priority - }, 200); -} - - - -// for use from vs.2003 debugger -function o2s(obj) { - var s = ""; - for (key in obj) { - var line = key + "->" + obj[key]; - line.replace("\n", " "); - s += line + "\n"; - } - return s; -} - -var seenReadyStateWarning = false; - -function openSeparateApplicationWindow(url, suppressMozillaWarning) { - // resize the Selenium window itself - window.resizeTo(1200, 500); - window.moveTo(window.screenX, 0); - - var appWindow = window.open(url + '?start=true', 'main'); - try { - var windowHeight = 500; - if (window.outerHeight) { - windowHeight = window.outerHeight; - } else if (document.documentElement && document.documentElement.offsetHeight) { - windowHeight = document.documentElement.offsetHeight; - } - - if (window.screenLeft && !window.screenX) window.screenX = window.screenLeft; - if (window.screenTop && !window.screenY) window.screenY = window.screenTop; - - appWindow.resizeTo(1200, screen.availHeight - windowHeight - 60); - appWindow.moveTo(window.screenX, window.screenY + windowHeight + 25); - } catch (e) { - LOG.error("Couldn't resize app window"); - LOG.exception(e); - } - - - if (!suppressMozillaWarning && window.document.readyState == null && !seenReadyStateWarning) { - 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."); - seenReadyStateWarning = true; - } - - return appWindow; -} - -var URLConfiguration = classCreate(); -objectExtend(URLConfiguration.prototype, { - initialize: function() { - }, - _isQueryParameterTrue: function (name) { - var parameterValue = this._getQueryParameter(name); - if (parameterValue == null) return false; - if (parameterValue.toLowerCase() == "true") return true; - if (parameterValue.toLowerCase() == "on") return true; - return false; - }, - - _getQueryParameter: function(searchKey) { - var str = this.queryString - if (str == null) return null; - var clauses = str.split('&'); - for (var i = 0; i < clauses.length; i++) { - var keyValuePair = clauses[i].split('=', 2); - var key = unescape(keyValuePair[0]); - if (key == searchKey) { - return unescape(keyValuePair[1]); - } - } - return null; - }, - - _extractArgs: function() { - var str = SeleniumHTARunner.commandLine; - if (str == null || str == "") return new Array(); - var matches = str.match(/(?:\"([^\"]+)\"|(?!\"([^\"]+)\")(\S+))/g); - // We either want non quote stuff ([^"]+) surrounded by quotes - // or we want to look-ahead, see that the next character isn't - // a quoted argument, and then grab all the non-space stuff - // this will return for the line: "foo" bar - // the results "\"foo\"" and "bar" - - // So, let's unquote the quoted arguments: - var args = new Array; - for (var i = 0; i < matches.length; i++) { - args[i] = matches[i]; - args[i] = args[i].replace(/^"(.*)"$/, "$1"); - } - return args; - }, - - isMultiWindowMode:function() { - return this._isQueryParameterTrue('multiWindow'); - }, - - getBaseUrl:function() { - return this._getQueryParameter('baseUrl'); - - } -}); - - -function safeScrollIntoView(element) { - if (element.scrollIntoView) { - element.scrollIntoView(false); - return; - } - // TODO: work out how to scroll browsers that don't support - // scrollIntoView (like Konqueror) -} |